The HEXAGONAL Architecture Explained | Ports and Adapters Pattern

  Рет қаралды 6,496

Marco Lenzo

Marco Lenzo

Күн бұрын

Пікірлер: 35
@MarcoLenzo
@MarcoLenzo 10 ай бұрын
Will you use port and adapters in your next application?
@cmanship
@cmanship 5 ай бұрын
Hello Marco, thanks for this clear and helpful explanation. Keep in mind that you're the best that i find for this kind of hexagonal architecture explanation. You answered in 11 minutes all the questions that i had all the time
@MarcoLenzo
@MarcoLenzo 5 ай бұрын
@@cmanship You are too kind 🙏 Thank you
@ilyasezzahid9540
@ilyasezzahid9540 10 ай бұрын
Your know how to explain difficult technicals topics. Thank you for helping us, become better developers.
@MarcoLenzo
@MarcoLenzo 10 ай бұрын
Thank you very much! Knowing this content is of help is the best reward I can get for working on it 😊
@softwarengineeringwithfabri
@softwarengineeringwithfabri Ай бұрын
thanks for explaining hexagonal so well!
@MarcoLenzo
@MarcoLenzo Ай бұрын
Thank you 🙏
@RoamingAdhocrat
@RoamingAdhocrat 2 ай бұрын
This was very clear - thanks!
@MarcoLenzo
@MarcoLenzo 2 ай бұрын
Thank you!
@ariasalmeida
@ariasalmeida 4 ай бұрын
your support slides are excellents! thank you !
@MarcoLenzo
@MarcoLenzo 4 ай бұрын
Thank you
@gustavosserra
@gustavosserra 7 күн бұрын
Clear explanation. Thanks.
@MarcoLenzo
@MarcoLenzo 20 сағат бұрын
Thank you
@marko95g
@marko95g 10 ай бұрын
interesting topic for discuss is using hexagonal architecture with monolith modular architecture, Can you make video about it ? Can I get your opinion on whether the secondary adapter can use the primary ports directly?
@MarcoLenzo
@MarcoLenzo 10 ай бұрын
Hexagonal Architecture can be used at many levels: from serverless (functions), to application (monolith / modulith) and system. I will try my best to touch this particular aspect. I might do it in a short video. If you have some questions / doubts, feel free to write them here so I get a better idea of what you have in mind. As for the second question, explain to me what the role of this secondary adapter is in your context. If we stick to the classic definition, a secondary adapter does not invoke a primary port, but I wish to figure out better what your scenario is.
@marko95g
@marko95g 10 ай бұрын
@@MarcoLenzo I am making an app for college purpose. I want to use hexagonal architecture and monolith modular architecture. Problem is that I don't know how to model communication between modules. Each module has an interface (primary port) and easiest way is to bind that interface as a secondary port for module that needs to call another module. For example, I have 'Comment module' which should call 'User module', easiest way is to define user port, and than bind it to comment module as secondary port. I hope you understand my problem :D
@MarcoLenzo
@MarcoLenzo 10 ай бұрын
Yes, it is clear. I think your issue is that you need an additional layer in your application that specialized in orchestrating the interactions between modules. What you are implementing is a sort of choreographed system on top of the hexagonal architecture. A choreographed system is one where each component is responsible to invoke the next one in line through a direct call or a message. You are conceptually trying to model the output port of module A as the input port of module B to model your use case. This is possible but it will make the code effectively a bit more difficult to navigate and lead to coupling between the modules. Module A needs to know about Module B. Typically, choreographed systems are implemented with an event-driven architecture where module A generates an event that can be consumed by any other module. It might happen to be module B and that's how you end up creating your flow. In such system, the output port is always generating an event and can be generic (it doesn't need to correspond to the input port of a particular module). It's way more easy if you employ orchestration where you have a central point of control (it could be a function) that defines what the flow is and invokes all the necessary modules in the correct order. You can take inspiration from the concept of Application Business Rules or Use Cases described in the Clean Architecture by Uncle Bob (Robert C. Martin). You can also understand it better if you learn about Sagas. You will find videos about both in my channel, and there's a ton of material online. Keep in mind the hexagonal architecture focused on isolation of one layer, but onion and clean architecture expanded on it by highlighting the fact your application will typically have 3 to 4 layers. You're missing that layer that glues the module together. Hope this helps! If you need more help, don't hesitate to contact me. You find more info on my website!
@drissaitkassimusic
@drissaitkassimusic 10 ай бұрын
You are a jem thank you 🙏
@MarcoLenzo
@MarcoLenzo 10 ай бұрын
You made my day! Thank you! 🙏
@wadeaashraf2761
@wadeaashraf2761 7 ай бұрын
Great topic
@MarcoLenzo
@MarcoLenzo 7 ай бұрын
Thank you. I really like the hexagonal architecture
@FlaviusAspra
@FlaviusAspra 9 ай бұрын
I know you most probably know, but your audience might get confused: A port is an interface or a collection of related interfaces. It's not necessarily just one. A port of the model can also contain classes: typically those classes for passing data into the model or reading data out of the model. Typically these are value objects and DTOs. Key point: these are part of the domain model, because the model is not allowed to depend on anything outside of itself.
@MarcoLenzo
@MarcoLenzo 9 ай бұрын
Thank you for the clarification Flavius. 🙏 In this setup, do you rely on package naming to highlight what the port is? Or do you imply it?
@FlaviusAspra
@FlaviusAspra 9 ай бұрын
@MarcoLenzo neither, nor. I enforce it with fitness functions. "Naming" something in technical ways goes against DDD's ubiquitous language and towards pure fabrications. I try to minimize the number and "blast radius" of pure fabrications in domain models. Typical example, no "ProductRepository", better: "ProductDataStorage" (as to not confuse with storage places of products). Not perfect still, but it is what it is. Edit: I've re-read your question carefully: yes, they are grouped together, but the above still holds.
@MarcoLenzo
@MarcoLenzo 9 ай бұрын
Understood 😊 You gave me a good idea for a follow up video. I think adding fitness functions to the sample repository would be an interesting exercise showing how we can enforce the design (hexagonal or whatever we use in our app).
@FlaviusAspra
@FlaviusAspra 9 ай бұрын
​@MarcoLenzo wasn't aware of the repo, but I checked it out now. I think we work quite similarly and you got many things just right. Examples from others that I've seen were utterly wrong, with the domain importing all kind of stuff. I have a feeling that we would work well together, we probably wouldn't agree on everything, but we would understand each other and let it go. Which is healthy - bringing other perspectives. Perspective 1: I'm not a big fan of words like "services" in the domain. It's a pure fabrication, it steals the word "service" from projects which offer business services - and that is most. Whenever I can, I get rid of that abstraction and I have my usecase as a class. Perspective 2: I pack the parameters of the use case in VOs and pass them into the model rather than the raw values. I feel stronger about perspective 1, and I'm fine with living with perspective 2. But I think in my case P2 is motivated by another situation which is very sensitive in the way I approach it: Some VOs which are enums and each value is bound to a business process also has a factory method for the business process inside. Classical example: the request parameter "accountOperation" which can be close, verify, ... I know most programmers twitch at this factory method being there and say "but factory class", and all I'm thinking is: I already put the if in the VO to validate it, why make the same if somewhere else? And all bugs that would come with this. It would also imply having a VO getValue() method which makes ME twich: the VO is THE value, in OO there shouldn't be yet another value behind the value. How do you view this idea of VO::createBusinessStrategy()?
@MarcoLenzo
@MarcoLenzo 9 ай бұрын
Flavius I'm sure we would work well together. I like to learn and try new approaches, especially if driven by someone knowledgeable and passionate like you. Based on many interactions we had, I know that I am more lenient than you when it comes to applying principles in the codebase written by other teams. To be honest, I'm intrigued by your approach and I'm just waiting for the right occasion to try it. That said, regarding P1 I've seen many codebases with anemic models, no use cases, and just a bunch of services. That is why I decided to include them along side an entity with sample behavior. I wanted developers to see something they are familiar with in the context of a pattern like hexagonal. Totally agree on P2 (avoiding raw values in the use case interface) and that is actually something I am used to do as well. Regarding the factory method tied to the business strategy, I wish I could see a sample to make sure I'm understanding well your idea. I'll try to answer anyway. What I got till now is that you wish to partition validations according to the particular business process which is selected through the VO. That makes perfect sense to me. (Just for the sake of considering tradeoffs I'm going to ask you something back...) I wonder if your use case interface is generic (i.e. a single method is used to trigger different operations); or if the same VO is used in different methods. That said I'm wondering if you considered more fine grained methods at the use case interface level / or different VOs per business process.
@ToluwalaseAkintoye-jb2lm
@ToluwalaseAkintoye-jb2lm Ай бұрын
pls how can i start my new project using hexagonal architecture in Go or java
@MarcoLenzo
@MarcoLenzo Ай бұрын
Download a sample project. I have one linked in the video description and start from there. There are many more available scaffolds out there. If you're still stuck, contact me over email. You find the contact on my website.
@GregorGramlich
@GregorGramlich 2 күн бұрын
Thanks for the video. Unfortunately most of the examples for ports and adapter that I see, are very simple. This is fine to a start with, but when looking deeper I struggle with understanding how to do stuff in a real application. In your example: How would you deal with concurrent accesses to the WithdrawFundsUseCase. If the current balance is 80 EUR and there two concurrent withdrawals of 50 EUR, both read the 80 EUR and want to save with the new balance with 30 EUR. In a system that uses a SQL database and JPA Entities directly you might get an OptimisticLockException or something similar, but in your example it looks like you are completely decoupled from the database transaction. I could imagine, that you keep some Hash or Version number of the old state and send it while saving. But I am really interested in your answer.
@MarcoLenzo
@MarcoLenzo 18 сағат бұрын
This is a great comment! As usual, it's all about trade-offs! I'll just give you my honest opinion. We expect transactionality to be handled by the infrastructural layer or adapter. ACID transactions are a core feature of most database engines, so re-implementing them within our application's core would be redundant. The simplest approach is to add the @Transactional annotation on AccountService.withdrawFunds (which is the concrete implementation of the use case). Some might argue against using a Spring annotation in the core, but this concern seems misplaced to me. The annotation doesn't tie us to a specific transaction manager or database. It just declares that the method's operations should execute within a transaction. As for testing, this approach means that concurrency testing would primarily be handled through integration tests rather than being confined to unit tests within the core layer. Could we avoid using Spring @Transactional in the core? Certainly! We could replicate its behavior or adopt patterns like Unit of Work, two/three-phase commits, or optimistic locks (which are similar to what you described). This would eliminate the Spring dependency, but does the gain justify the complexity? In my view, it doesn't. In a distributed system, you eventually need to rely on the infrastructure to coordinate operations across multiple threads and processes. There's no way round it.
@MarcoLenzo
@MarcoLenzo 14 сағат бұрын
Just came to mind that you could even use the Jakarta @Transactional instead of the Spring one, and still have it being recognized by the framework. docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html
Want to make a video chat app? Watch this video for WebRTC!
1:22:35
Good Morning Developers
Рет қаралды 48 М.
"Идеальное" преступление
0:39
Кик Брейнс
Рет қаралды 1,4 МЛН
The Onion Architecture EXPLAINED | Should we use it?
13:12
Marco Lenzo
Рет қаралды 6 М.
Hexagonal Architecture (All You Need to Know)
9:51
Gui Ferreira
Рет қаралды 10 М.
Design Accelerator: Ports and Adapters Architecture Part 2
27:07
Vaughn Vernon
Рет қаралды 2,3 М.
Tired of Layers? Vertical Slice Architecture to the rescue!
12:26
Why I am using Hexagonal Architecture in my projects
11:11
Ivan Skodje
Рет қаралды 13 М.