{"id":18966937,"url":"https://github.com/link-intersystems/clean-architecture-example","last_synced_at":"2025-10-16T20:02:02.279Z","repository":{"id":164290828,"uuid":"621703415","full_name":"link-intersystems/clean-architecture-example","owner":"link-intersystems","description":"An clean architecture example application implemented in pure Java.","archived":false,"fork":false,"pushed_at":"2024-05-04T16:14:54.000Z","size":3669,"stargazers_count":13,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-16T08:10:43.586Z","etag":null,"topics":["architecture","clean-architecture","clean-code","example","java"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/link-intersystems.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-31T07:56:04.000Z","updated_at":"2025-01-23T11:08:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"c976d4f4-3dbf-42da-ac3f-dbf4ad3531b0","html_url":"https://github.com/link-intersystems/clean-architecture-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fclean-architecture-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fclean-architecture-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fclean-architecture-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fclean-architecture-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/link-intersystems","download_url":"https://codeload.github.com/link-intersystems/clean-architecture-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249711563,"owners_count":21314267,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["architecture","clean-architecture","clean-code","example","java"],"created_at":"2024-11-08T14:39:09.176Z","updated_at":"2025-10-16T20:01:57.258Z","avatar_url":"https://github.com/link-intersystems.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Java CI with Maven](https://github.com/link-intersystems/clean-architecture-example/workflows/Java%20CI%20with%20Maven/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/link-intersystems/clean-architecture-example/badge.svg?branch=main)](https://coveralls.io/github/link-intersystems/clean-architecture-example?branch=main)\n\n# Clean Architecture in Pure Java\n\nThis repository contains an example implementation of the clean architecture in [pure Java](#as-pure-as-possible).\nYou can either use this example as a starting point for discussions about the clean architecture and its various\nimplementation details, or you can use it to learn more about the clean architecture.\n\n![Clean Architecture by Uncle Bob (Robert C. Martin)](src/site/resources/CleanArchitecture.jpg)\n\n[The Clean Architecture, Robert C. Martin, 13 August 2012](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)\n\n## Table Of Contents\n\n- [Screaming Architecture](#screaming-architecture)\n- [Package By Component](#package-by-component)\n- [Modules And Components](#modules-and-components)\n    - [Components In CleanArchitecture](#components-in-clean-architecture)\n- [Domain Events And The Event Bus](#domain-events-and-the-event-bus)\n- [As Pure As Possible](#as-pure-as-possible)\n- [Implementation Notes](#implementation-notes)\n    - [Use Cases And Interactors](#use-cases-and-interactors)\n    - [This Example Architecture](#this-example-architecture)\n- [More Sources](#more-sources)\n- [The Example Domain](#the-example-domain)\n    - [Domain Modules](#domain-modules)\n    - [Domain Events](#domain-events)\n    - [Details](#details)\n        - [User Interface](#user-interface)\n        - [Database](#database)\n- [Any Questions?](#any-questions)\n\n## Screaming Architecture\n\nUncle Bob told us that good architecture is focused on the use cases and not on details like frameworks, tools and so\non.\nFollowing the \"screaming architecture\" rule I tried to focus on domain aspects. Therefore, you will\nfind domain-related terms at the top level of this project.\n\n## Package By Component\n\nAll [modules](#modules-and-components) in this project are structured using the *package by component* strategy as\ndescribed by Simon Brown in the Clean\nArchitecture book - chapter 34, the missing chapter.\n\n![Package By Component, Simon Brown, The Missing Chapter, Clean Architecture Book](src/site/resources/package-by-component.png)\n\nThe package by component strategy makes use of Java's default access modifier that only allows access from\nclasses within the same package. It would also be possible to use the Java module system or OSGI, but I wanted\nto use the simplest solution that works.\n\nIf you would like to learn more about the other packaging strategies take a look at chapter 34, the missing chapter, in\nthe [Clean Architecture book](https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164).\n\n## Modules And Components\n\nEvent though the terms module and component are widely used, there is often a lot of confusion about the meaning of\nthem.\nIf you ask 5 developers: \"What are the differences?\", you might get 5 different answers, so here is mine:\n\n\u003e A component is a group of elements. A component can contain other components.\n\nComponent is derived from the latin word *componere*, which means \"to put together\".\n\n\u003e A module is a replaceable component.\n\nThe term module is derived from the latin word *modulus*, which means \"measure\".\nToday the meaning in general is \"interchangeable part\".\n\nThe example application is organized in 2 [domain modules](#domain-modules) that you find at the top level\nof this project, like a [screaming architecture](#screaming-architecture) should be organized.\n\n### Components In Clean Architecture\n\nA component in the clean architecture spans all layers, so it's hard to explain what a component is if you only use\na 2D diagram. So I tried to visualize my thoughts in 3D.\n\n![Components in Clean Architecture](src/site/resources/components-in-clean-architecture.png)\n\n## Domain Events And The Event Bus\n\nComponents in the clean architecture should be completely separated, but sometimes they share common entities. The\ncommunication between components can be done using domain events. A domain event is usually the outcome of the execution\nof a use case and is published somehow.\n\nI would call the publishing mechanism a domain-event bus. The domain-event bus is a component that is responsible for\nthe delivery of domain events. Domain events are published by use cases and can are consumed by controllers or other\ncomponents within the interface adapters layer, e.g. a gateway that sends the event to an external system, like a\nmessage queue.\n\n![Domain Event Bus](src/site/resources/domain-event-bus.png)\n\n## As Pure As Possible\n\nThis example does not use a lot of frameworks and libraries. Especially not for the application bootstrap,\nthe use cases or entities and the object-relational mapping. Thus, you will not find any Spring or Hibernate and\neven no apache commons library.\n\nAlthough I like frameworks and libraries as much as you probably do, I want to show how a complete application works\nthat is implemented in pure Java. You will probably be surprised that many frameworks and libraries can be omitted\nwithout significantly increasing the implementation effort. We should consider this before using a framework or library,\nespecially if we made the experience that framework updates sometimes make a lot of effort. Also license issues do not\narise if we do not use them and a fix is easy to make. I don't want to say that frameworks and libraries are bad,\nbut they come at a cost that we often forget. So if we use them we should know why we use them, and we should separate\nthem from the core of our application to protect it. Most libraries I use in this example application are written by\nmyself.\n\n## Implementation Notes\n\nWhen you browse the source code you should keep in mind that you see one solution for every particular technical problem\nthat arises when implementing the clean architecture. For a lot of situations there are more than one way to solve them.\nAnyway, all solutions must honor the dependency rules of the architecture. Feel free to play with the architecture and\nrefactor any aspect you would like to change to see what is easy to change and what is not.\n\n### Use Cases And Interactors\n\nIn the context of the clean architecture you will often see a diagram that uses the terms:\n\n- use case interactor\n- input and output boundary\n- request/response models.\n\n![Clean Architecture](src/site/resources/boundaries%20and%20layers.jpg)\n\nThese terms are a mix between the boundary-controller-entity (BCE) by Ivar Jacobson, the hexagonal architecture\nby Alistair Cockburn and the clean architecture by Robert C. Martin.\n\nIn the BCE architecture you have a boundary, a controller and an entity, as the name implies. In the hexagonal\narchitecture\nyou talk about input and output ports and the clean architecture uses the terms interactors, request and response\nmodels,\nand entities.\n\n#### This Example Architecture\n\nIn this example I use the term use case for the API instead of input boundary and interactor for the use case\nimplementation.\nRequest and Response models are the input and output models of the use case.\n\n![Example Architecture](src/site/resources/example-architecture.png)\n\nIn the UI presenters are used by a controller to present response models to the user and to transform user input to\nrequest models. The controller is invoked by the UI as a result of an event. It then uses the presenter to create a\nrequest\nmodel and invokes the use case.\n\nIn this point my architecture is different to the diagram I showed above, because it does not decouple a presenter from\na\ncontroller, and thus it doesn't need to pass an output boundary to a use case interactor. Therefore, my architecture\nhas a lot less complexity in this area, but at the cost that controllers are not separated from presenters. It's true\nthat I don't have the benefits of decoupling them, but I also don't have a lot of implementation issues that arise from\nthe decoupling. It's a tradeoff that I made in the UI/use case integration to reduce the complexity in that area. I made\nthat decision, because the focus of the example application is the use case part, how these classes are structured and\nhow different modules integrate.\n\nSince this example should be used as a starting point for discussions, feel free to refactor the UI/use case integration\npart\nand [start a discussion](https://github.com/link-intersystems/clean-architecture-example/discussions).\n\n## More Sources\n\nIf you would like to learn more about clean code and the clean architecture,\nyou should take a look at my [youtube channel - clean-code.guru (german)](https://www.youtube.com/@cleancodeguru).\n\nI also would like to recommend the [cleancoders.com](https://cleancoders.com) website, where you can find a lot of\nvideos about clean code. Most of them provided by Robert \"Uncle Bob\" Martin and Micah Martin.\n\n## The Example Domain\n\nFor this clean architecture example I chose a car rental application which is complex enough to address common\nimplementation issues, but simple enough\nto stay focused on the architecture and not the domain.\n\n### Domain Modules\n\nThe application is separated in 2 domain module in order to show how communication via [domain](#domain-events) events\ncan be done.\nEach module implements several use cases that are the modules components.\n\n- car-booking\n\n  The car-booking module contains the use cases a customer executes, like find car offers and book a car.\n- car-management\n\n  The car-management module contains the use cases a salesperson executes, like handover a car to a customer and return\n  one.\n\nYou might want to explore the clean architecture further by implementing more use cases.\n\nHere is a list of user story proposals:\n\n1. As a sales manager I would like to define multiple rental rates with\n   a different, but never overlapping, validity period, so that rates can vary over time.\n2. As a sales manager I would like to specify different stations where the customer can pick up cars.\n3. As a customer I would like to get offers for stations in the city where I live (my address).\n\n## Domain Events\n\nThe domain modules are completely separated, which means that each one uses its own dedicated data storage. At the\nmoment they\nare separated by two different database schemas, but they could also use their own database. The management module\nreacts\nto domain events that are fired by the car-booking module in order to update its database. I chose that way to\ndemonstrate how domain events can be implemented.\n\nIn the current implementation the domain events are synchronously published on the same thread. Since I use local\ntransactions that are bound to the thread, the event subscribers logic is executed in the same transaction as the\npublisher.\n\nFeel free to refactor the domain event bus to use asynchronous event publishing or even an external event queue.\n\n## Details\n\n### User Interface\n\nThe example application comes with a very basic swing ui that you can use to try out the application. Since it\nis a basic ui it neither has any convenience features, like validation, nor it is very nice. The purpose of the\nuser interface is to provide a simple GUI to access the use cases. It also shows the basics of how use cases are\nconnected to controllers and how controllers use presenters in order to update models. Feel free to implement a\nweb server and provide rest controllers in order to support a web ui.\n\n![Simple Swing UI](src/site/resources/ui-screenshot.png)\n\n### Database\n\nThe application uses a H2 file database that is automatically created in the working directory when you start the\napplication. This will contain some test data. If you need to reset the database, just delete the carrental.mv.db in the\nworking directory.\n\nThe example data is the same as the data that the unit tests use. So you can also browse it here:\n\n- [car booking test data](car-booking/entities/src/site/markdown/TestFixtures.md)\n\n## Any Questions?\n\nIf you have any questions about\n\n- this example application you\n  can [start a discussion](https://github.com/link-intersystems/clean-architecture-example/discussions).\n- the clean architecture and clean code in general you can\n  browse [my answers on stackoverflow](https://stackoverflow.com/search?q=user%3A974186+%5Bclean-architecture%5D) or\n  post\n  a new answer. I usually watch new answers to\n  the [clean-architecture](https://stackoverflow.com/questions/tagged/clean-architecture) and\n  [hexagonal-architecture](https://stackoverflow.com/questions/tagged/hexagonal-architecture) tag.\n- clean code in general or software architecture, you can either take a look at\n  my [youtube channel - clean-code.guru (german)](https://www.youtube.com/@cleancodeguru) or\n  [contact me](https://link-intersystems.com/contact-us/) for trainings and coaching or book a session\n  on [![codementor.io](https://www.codementor.io/m-badges/renlink/book-session.svg)](https://www.codementor.io/@renlink?refer=badge).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flink-intersystems%2Fclean-architecture-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flink-intersystems%2Fclean-architecture-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flink-intersystems%2Fclean-architecture-example/lists"}