{"id":461,"date":"2025-04-06T15:12:44","date_gmt":"2025-04-06T15:12:44","guid":{"rendered":"https:\/\/devopsopen.com\/?p=461"},"modified":"2025-04-10T18:56:45","modified_gmt":"2025-04-10T18:56:45","slug":"layer-onion-clean-hexagonal-architecture","status":"publish","type":"post","link":"https:\/\/devopsopen.com\/index.php\/2025\/04\/06\/layer-onion-clean-hexagonal-architecture\/","title":{"rendered":"Layer, Onion, Clean, Hexagonal Architecture"},"content":{"rendered":"<h1>Layer Architecture<\/h1>\n<ul>\n<li>Structur of layer Architecture<\/li>\n<\/ul>\n<hr \/>\n<pre><code>src\/\n\u2514\u2500\u2500 com\/example\/app\/\n    \u251c\u2500\u2500 controller\/           # Handles HTTP requests (UI layer)\n    \u2502   \u2514\u2500\u2500 UserController.java\n    \u251c\u2500\u2500 service\/              # Business logic\n    \u2502   \u2514\u2500\u2500 UserService.java\n    \u251c\u2500\u2500 repository\/           # Data access\n    \u2502   \u2514\u2500\u2500 UserRepository.java\n    \u2514\u2500\u2500 model\/                # Entities \/ DTOs\n        \u2514\u2500\u2500 User.java<\/code><\/pre>\n<hr \/>\n<p>problem : UserService is tightly coupled to UserRepository as metionned below<\/p>\n<hr \/>\n<pre><code>public class UserService {\n    private UserRepository userRepository = new UserRepository();\n    public void registerUser(User user) {\n        if (!user.getEmail().contains(\"@\")) {\n            throw new IllegalArgumentException(\"Invalid email\");\n        }\n        userRepository.save(user);\n    }\n}<\/code><\/pre>\n<hr \/>\n<h1>Onion Architecture<\/h1>\n<ul>\n<li>\n<h2>Structur of Onion Architecture<\/h2>\n<p>src\/<br \/>\n\u2514\u2500\u2500 com\/example\/app\/<br \/>\n\u251c\u2500\u2500 domain\/<br \/>\n\u2502   \u251c\u2500\u2500 model\/            # Core entities<br \/>\n\u2502   \u2502   \u2514\u2500\u2500 User.java<br \/>\n\u2502   \u251c\u2500\u2500 port\/             # Interfaces (like UserRepository)<br \/>\n\u2502   \u2502   \u2514\u2500\u2500 UserRepository.java<br \/>\n\u2502   \u2514\u2500\u2500 usecase\/          # Business use cases<br \/>\n\u2502       \u2514\u2500\u2500 RegisterUserUseCase.java<br \/>\n\u251c\u2500\u2500 infrastructure\/<br \/>\n\u2502   \u2514\u2500\u2500 repository\/       # Implements ports<br \/>\n\u2502       \u2514\u2500\u2500 InMemoryUserRepository.java<br \/>\n\u2514\u2500\u2500 web\/<br \/>\n\u2514\u2500\u2500 controller\/       # CLI \/ REST \/ UI<br \/>\n\u2514\u2500\u2500 UserController.java<\/p>\n<\/li>\n<\/ul>\n<hr \/>\n<ul>\n<li>\n<p>Site du fondateur<br \/>\n<a href=\"https:\/\/jeffreypalermo.com\/2008\/07\/the-onion-architecture-part-1\/\">https:\/\/jeffreypalermo.com\/2008\/07\/the-onion-architecture-part-1\/<\/a><br \/>\n<a href=\"https:\/\/github.com\/splaw88\/onion-architecture?tab=readme-ov-file\">https:\/\/github.com\/splaw88\/onion-architecture?tab=readme-ov-file<\/a><\/p>\n<h1>Clean Architecture<\/h1>\n<\/li>\n<li>\n<p>Structur of clean Architecture<\/p>\n<\/li>\n<\/ul>\n<hr \/>\n<pre><code>src\/\n\u2514\u2500\u2500 com\/example\/app\/\n    \u251c\u2500\u2500 entities\/            # Enterprise-wide business rules\n    \u2502   \u2514\u2500\u2500 User.java\n    \u251c\u2500\u2500 usecases\/            # Application-specific business logic\n    \u2502   \u2514\u2500\u2500 RegisterUser.java\n    \u251c\u2500\u2500 interfaceadapters\/   # DTOs, Presenters, Gateways\n    \u2502   \u251c\u2500\u2500 controller\/\n    \u2502   \u2502   \u2514\u2500\u2500 UserController.java\n    \u2502   \u2514\u2500\u2500 repository\/\n    \u2502       \u2514\u2500\u2500 UserRepositoryImpl.java\n    \u2514\u2500\u2500 frameworks\/\n        \u251c\u2500\u2500 db\/\n        \u2502   \u2514\u2500\u2500 UserJpaRepository.java\n        \u2514\u2500\u2500 web\/\n            \u2514\u2500\u2500 SpringBootApp.java<\/code><\/pre>\n<hr \/>\n<h1>Hexagonal Architecture<\/h1>\n<ul>\n<li>Structur of clean Architecture<\/li>\n<\/ul>\n<hr \/>\n<pre><code>src\/\n\u2514\u2500\u2500 com\/example\/app\/\n    \u251c\u2500\u2500 application\/         # Core logic (use cases)\n    \u2502   \u2514\u2500\u2500 RegisterUser.java\n    \u251c\u2500\u2500 domain\/              # Domain models & business rules\n    \u2502   \u2514\u2500\u2500 User.java\n    \u251c\u2500\u2500 ports\/               # Interfaces (input\/output)\n    \u2502   \u251c\u2500\u2500 input\/\n    \u2502   \u2502   \u2514\u2500\u2500 RegisterUserInputPort.java\n    \u2502   \u2514\u2500\u2500 output\/\n    \u2502       \u2514\u2500\u2500 UserRepositoryPort.java\n    \u251c\u2500\u2500 adapters\/            # Implementations of ports\n    \u2502   \u251c\u2500\u2500 inbound\/         # Web, CLI, etc.\n    \u2502   \u2502   \u2514\u2500\u2500 RestControllerAdapter.java\n    \u2502   \u2514\u2500\u2500 outbound\/        # DB, email, etc.\n    \u2502       \u2514\u2500\u2500 JpaUserRepositoryAdapter.java\n    \u2514\u2500\u2500 config\/              # App wiring (DI, configs)\n        \u2514\u2500\u2500 ApplicationConfig.java<\/code><\/pre>\n<hr \/>\n<ul>\n<li>Site du fondateur<br \/>\n<a href=\"https:\/\/web.archive.org\/web\/20140329201018\/http:\/\/alistair.cockburn.us\/Hexagonal+architecture\">https:\/\/web.archive.org\/web\/20140329201018\/http:\/\/alistair.cockburn.us\/Hexagonal+architecture<\/a><br \/>\n<a href=\"https:\/\/alistair.cockburn.us\/\">https:\/\/alistair.cockburn.us\/<\/a><\/li>\n<\/ul>\n<p>exemple de code : <a href=\"https:\/\/github.com\/SvenWoltmann\/hexagonal-architecture-java\/tree\/main\">https:\/\/github.com\/SvenWoltmann\/hexagonal-architecture-java\/tree\/main<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Layer Architecture Structur of layer Architecture src\/ \u2514\u2500\u2500 com\/example\/app\/ \u251c\u2500\u2500 controller\/ # Handles HTTP requests (UI layer) \u2502 \u2514\u2500\u2500 UserController.java \u251c\u2500\u2500 service\/ # Business logic \u2502 \u2514\u2500\u2500 UserService.java \u251c\u2500\u2500 repository\/ # Data access \u2502 \u2514\u2500\u2500 UserRepository.java \u2514\u2500\u2500 model\/ # Entities \/ DTOs \u2514\u2500\u2500 User.java problem : UserService is tightly coupled to UserRepository as metionned below public class UserService { private UserRepository userRepository = new UserRepository(); public void registerUser(User user) { if (!user.getEmail().contains(&#8220;@&#8221;)) { throw new IllegalArgumentException(&#8220;Invalid email&#8221;); } userRepository.save(user); } } Onion Architecture Structur of Onion Architecture src\/ \u2514\u2500\u2500 com\/example\/app\/ \u251c\u2500\u2500 domain\/ \u2502 \u251c\u2500\u2500 model\/ # Core entities \u2502 \u2502\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":""},"categories":[3],"tags":[],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":5}},"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"admin","author_link":"https:\/\/devopsopen.com\/index.php\/author\/admin_bak\/"},"uagb_comment_info":0,"uagb_excerpt":"Layer Architecture Structur of layer Architecture src\/ \u2514\u2500\u2500 com\/example\/app\/ \u251c\u2500\u2500 controller\/ # Handles HTTP requests (UI layer) \u2502 \u2514\u2500\u2500 UserController.java \u251c\u2500\u2500 service\/ # Business logic \u2502 \u2514\u2500\u2500 UserService.java \u251c\u2500\u2500 repository\/ # Data access \u2502 \u2514\u2500\u2500 UserRepository.java \u2514\u2500\u2500 model\/ # Entities \/ DTOs \u2514\u2500\u2500 User.java problem : UserService is tightly coupled to UserRepository as metionned below&hellip;","_links":{"self":[{"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/posts\/461"}],"collection":[{"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":2,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"predecessor-version":[{"id":463,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/posts\/461\/revisions\/463"}],"wp:attachment":[{"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devopsopen.com\/index.php\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}