Introduction

In this episode of the No Silver Bullet podcast, we discuss Clean Architecture and whether it’s overengineering or a best practice for organizing code. We talk about why the pattern is often controversial, when it makes sense to use it, and how to implement it effectively. We share our experiences using Clean Architecture across different projects and teams, including the common concerns developers have when first seeing it.

Quick takeaways

  • Clean Architecture is most beneficial for complex projects with larger teams - for small teams or simple projects, it can become overengineering.
  • Separation of concerns is the core benefit - keeping domain logic separate from implementation details makes code more maintainable.
  • It’s easy to go too far - using too many interfaces or too many layers without a clear reason creates unnecessary complexity.
  • Start simple and evolve your architecture - don’t force Clean Architecture from the start if your project doesn’t need it yet.
  • Understanding the “why” behind the pattern is crucial - blindly following it without understanding leads to poor implementations.

Notes

Quotes

In general, if you ask many people about clean architecture they will say that it’s overcomplicating things and making your project worse.

Robert

One of the main points of Clean Arch is to separate the interesting code from the implementation details.

Miłosz

The goal is not using any kind of architecture. But the goal is to use something that is useful for you. It supports your velocity because at the end of the day, every technique that we’re using, it should allow you to code faster and that’s it basically. So if you are using some architecture and it’s slowing your down, you cannot iterate faster, it’s probably the bad one.

Robert

If you have been in a team that spent hours discussing in which directory to put some code, then you might assume you don’t want to work with Clean Arch anymore because it’s just it’s too much hassle to keep discussing how to use it.

Miłosz

If you are building more complex applications and you are starting to mix all this stuff it’s super hard to maintain that. And this inversion of control helps you to cut this logic in multiple parts and make it easier to maintain.

Robert

Don’t do it because you want your code to be clean, but to better organize work in a complex project that will grow over time.

Miłosz

Clean architecture is not that complex pattern. You have three, four layers depending on the complexity of your application. You’re ensuring that layer from inside doesn’t know about layer outside, and you’re using interfaces to do inversion of control. That’s it.

Robert

The pattern is not exactly about project structure, which is also easy to fixate on. All the layers are more concepts, not exactly directories, although this is often the case.

Miłosz

Timestamps

  • 00:00:00 - Introduction
  • 00:01:28 - What is Clean Architecture?
  • 00:15:32 - Early Audience Comments
  • 00:23:30 - Controversies
  • 00:29:56 - Common Pitfalls
  • 01:02:47 - The Benefits of Using Clean Architecture
  • 01:21:20 - Team Collaboration & Splitting Work
  • 01:28:29 - Can we Just Keep It Simple?
  • 01:36:35 - Alternatives
  • 01:38:20 - Go-Specific Implementation Tips
  • 01:43:20 - Summary
  • 01:46:51 - Q&A Session
  • Transcript

    Miłosz [00:05]: Clean Architecture is an overengineering nightmare or the best way to organize projects. It all depends on who you ask. To make it work, you need to understand the “why” behind it and avoid the common anti-patterns. Today, we talk about why the pattern is so controversial and how it can help you in your projects. I’m Miłosz.

    Robert [00:25]: And I’m Robert. And this is the No Silver Bullet live podcast where we discuss mindful backend engineering. We spent almost twenty years working together in different projects and teams. During that time, we learned that following advice like “always do X” or “never do Y” doesn’t work and can limit your growth. In this show, we share multiple perspectives that will help you make smart choices that will help you to grow into principal engineer level.

    Miłosz [00:55]: If you have any follow-up questions, you can ask them in the chat. We’ll have a Q&A session at the end as usual. And we might also pick up your comments during the discussion.

    Robert [01:07]: This time, we’ll try harder to look on the chat and pick up your questions, especially that I think the today’s topic is pretty controversial one. And, yeah, I think it would be great to see some different point of views on that and also hear your experience with that. So we can also learn something maybe. How do you see that? And we can also create better content.

    Miłosz [01:32]: Alright. So the title says Clean Architecture for today’s topic but the pattern actually has a few other names like Hexagonal, Ports and Adapters, or Onion. They are not exactly the same thing. There are some differences in the implementation. But I think we can assume that the main idea, the core idea behind them is similar. Right? So similar that we can treat them as pretty much the same pattern. And we won’t dive deep into the differences today, And we’ll just stick to the clean architecture just because that’s how we started calling it and I think it’s quite popular anyway.

    Robert [02:18]: Probably the most common term because, yeah, you could probably heard some terms like hexagonal architecture, ports and adapters, onion architecture. But, yeah, the idea on a high level is quite similar.

    Miłosz [02:33]: Yeah, and while it’s popular I think everyone understands it a bit differently which is common with complex patterns.

    Robert [02:41]: And probably this is the reason why there are also a lot of misunderstanding about that because many people actually are messing clean architecture with domain driven design. So some people don’t have a good idea how to connect that because, okay, in many clean architecture implementations you have the domain layer. So for some reason it’s like, okay, you have domain layer so we are doing domain driven design. Or some reason also some people also think that okay, clean architecture is some Java or it’s some enterprise. It’s not something that you can use.

    Miłosz [03:14]: That’s only for enterprise super complex projects.

    Robert [03:17]: Yeah, yeah. And in general, if you ask many people about clean architecture they will say that it’s overcomplicating things and making your project worse.

    Miłosz [03:29]: Which is problematic because if you don’t understand something, chances are you won’t implement it properly in your project. So that’s risky. And I think often it’s also a very controversial pattern. If you mention it to someone and they had bad experiences from the past usually they won’t react well, like, they won’t be happy about you using the pattern, let’s say.

    Robert [03:58]: Yeah, and I think it’s interesting that we worked in multiple teams and usually we have some people that were not happy about using clean architecture but at the end we’re kind of able to convince them that it’s nice. Probably we can have one person confirm that. So Firmino said that he’s missing working with Milosz. So it’s a good sign. So at least one person is missing working with you. Maybe clean architecture helped a bit.

    Miłosz [04:28]: Thank you Firmino, at least one person misses me. You can mention if you like clean architecture or not. So it might be one example for today’s discussion. Maybe it’s not that bad.

    Robert [04:41]: What I think is interesting about that the thing that I already mentioned that you know, we were leading, multiple teams in our lives and it wasn’t uncommon for us to have some people coming from other projects. And, well, we had pretty good experience with clean architecture and they were coming to our project and most of the people were like, oh, like, okay, it’s cool. Please tell me how it’s working. But some people, I think usually some people who have already done have more experience or thought, oh, no, clean architecture or over engineering stuff. But in most cases, it was like, okay, it took some time, like, it wasn’t weeks. It was like sitting with this person for a half hour showing how everything works. And at the end, most of it people were saying, yeah, it’s actually cool. I’m using it in my projects after the job. Actually, I remember one person even said that he was building a game and he used the architecture in that because he could exchange, I think, engine or something like that. It was quite cool.

    Miłosz [05:43]: So does it mean we should use it everywhere? Would you say it’s a silver bullet?

    Robert [05:52]: No. But, you know, I think pet projects after work, it’s probably a pretty good place to experiment and do some crazy experiments. But, yeah, long story short, I think we’re pretty surprised to later hear that it’s not everywhere like that, like in our team. So there are people that try to clean architecture and at the end, they were saying that it’s always bad. And we started to wonder what is the reason why people hate architecture in all projects.

    Miłosz [06:24]: Maybe we can answer it today. But maybe let’s start with a very short definition. Let’s try to boil it down to the very core ideas because there are many flavors and, you know, even if you use one of the flavors, you can use it in a different way than someone else. So let’s just try to agree on what’s behind the idea. For me, the first one is separation of concerns, and it often comes with the layers idea in those architectures. But after years of using it, I think you could just summarize it as, you know, you agree that your- project has code of two categories, The boring code, which is the implementation details that you don’t care that much about.

    Robert [07:17]: Or you should not care. Because, unfortunately, often it’s the opposite.

    Miłosz [07:21]: Yeah, like the SQL queries you use or what database engine you use. It is important, of course, but probably doesn’t make your business win automatically. And on the other hand, there is the the interesting code, the domain code, the logic of what your application does, sometimes called business logic. But I think this is a bit unfortunate term because it, you know, it again has those enterprise vibes. And I think people writing usual web applications maybe don’t think of business code when they write the logic they do. But the fact is it is some kind of domain code anyway. Right?

    Robert [08:05]: Yeah. But it’s worth mentioning that it depends heavily on what kind of application you’re working on. So just a kind reminder. So this is no silver bullet podcast, live podcast, and, yeah, it can suggest that it depends on different projects. And so as you said, so sometimes you have business logic, but sometimes it’s as simple that you can have it in controllers mixed with SQL queries. But sometimes it’s not that simple. I mean, you can go this way, but and we did it in our lives but it’s a nightmare a bit later.

    Miłosz [08:37]: But I think we can agree that the main point of one of the main points of CleanArch is to separate those two, right? To separate the interesting code from the implementation details.

    Robert [08:51]: Yes, and probably it’s worth mentioning how it’s done. So it’s all about the well, I think it’s not the first time when we’re mentioning that there are some old patterns that are still valid and the same is for, inversion of control. And the idea is that you can implement, you can implement so you can define interface on some behaviors that you expect for example, from the database, from external providers. So and thanks to having interface for that your implementation doesn’t need to know really how it’s implemented under the hood. And, again, if you’re creating a simple application it’s not a big deal because the logic is not that complicated needed there. But if you are building more complex applications and you are starting to mix all this stuff it’s super hard to maintain that. And this inversion of control helps you to cut this logic in multiple parts and, well, make it easier to maintain.

    Miłosz [09:52]: And it’s not that complicated, right? Inversion of control sounds a bit complex but in reality this is accept interfaces instead of implementations.

    Robert [10:03]: Yes. But we’ll come into that because, well, like always the idea is simple but in practice people unfortunately are overcomplicating that and there are multiple ways on how you can overcomplicate that but we’ll touch on that in a while.

    Miłosz [10:19]: So we have, separation of concerns of the domain and implementation details and second inversion of control of dependencies. Often there is some concept of layers, which are basically groups of code you use that are dedicated to something. So often we have the Adapters, which are for, you know, external communication of external things like databases or API clients or even for entry points to your applications which we like to separate often.

    Robert [10:58]: So in other words, it can be calling other microservice or other module. So it it can be database, it can be external API, external by not your company but well, if you are building real microservices, you know, other microservice should be kind of like separate, something totally separate for you.

    Miłosz [11:17]: And this layer is quite boring usually. It just maps your code onto some external code and that’s it. It should be boring. Then there is some kind of application or use cases or controllers maybe, layer where the logic is or orchestration of your application. And sometimes also domain layer which is this pure business logic layer, which does not always have to be.

    Robert [11:49]: So the second layer is so again we’ll use multiple names for that because as we said that at the beginning so there are multiple names for let’s say similar idea like clean architecture, ports and adapters etc. So we’ll just use multiple names to be compatible with more. So the second layer is interfaces or entry points or sometimes ports. And the idea is that this is the place where you’re defining your HTTP handlers, your gRPC handlers, your message handlers, even CLI. So any entry point to your applications. The idea is that any operation that is coming into your application, it should go through this layer. And what’s super cool about this, layer is that it’s allowing you to have different entry point for the same operation. So, for example, let’s imagine that you have application that allows you to create a customer and for some reason you need to create customers through message and also through HTTP API. It’s nice because at the end you can do the same operation share a bit less code and support multiple different ways of interacting with your application from external world.

    Miłosz [13:00]: I really like this approach because, you know, when when you take a look at the project, it’s very easy to see what are the entry points. So it’s very clear where is the API if you want to interact with it.

    Robert [13:13]: And it works pretty nicely with the pattern that we touched in the previous episode. So MVC. So this is basically your controller from your MVC.

    Miłosz [13:24]: But, given all those layers, it’s also important to keep in mind that the pattern is not exactly about project structure, which is also easy to, you know, fixate on. So all the layers are more concepts, not exactly doesn’t have to be directories, although this is often the case. But we probably will touch on it a bit later.

    Robert [13:57]: So the next layer. I think this is pretty problematic layer because I think many people don’t understand what this layer is but this is application layer. So this is the layer that is doing the orchestration of everything. So I think it’s not probably the best place to describe how it can look in practice. At the end, we’ll give some materials that we believe are covering how to implement application layer nicely. But, yeah, long story short, this is the orchestration of what you are doing in your application. And this should be called by your ports.

    Miłosz [14:31]: Ports or interfaces or entry points.

    Robert [14:35]: And it should call your domain layer if you have this layer, and your adapter’s layer, long story short.

    Miłosz [14:44]: So that’s the parts of the puzzle, I guess. The separation of concerns, and inversion of dependencies and layers, right?

    Robert [14:57]: And I think we forgot about one layer or maybe you mentioned it. So the domain layer. The optional one because I think it’s worth mentioning that it’s sometimes useful but not always. And but it yeah. It’s the layer with the logic. So the layer that should be free of any database logic of any adapters, it should be, relevant. Again, it’s probably something for I think it’s better to read code than talk about that to show how domain layer works. But again, we’ll give you some material.

    Miłosz [15:28]: It’s probably also not the place to go into details on application versus domain, but you may find some of it on our blog.

    Robert [15:37]: Let’s maybe take a look on the chat so I’ve seen a lot of messages there so we can catch on it. So, yeah, there are some voices that, yeah, I like it often and use it often and like it. So, yeah, we have some positive things about clean architecture. The second comment, I love that clean architecture and your articles helped me to show how to code is not about language but about structure and functionality. Thank you.

    Robert [16:05]: We will later link to some articles that we have on our blog. So, yeah, I think it will be just explaining better how those layers work because, again, it’s pretty hard probably to just talk about that without showing the code. What else? Nice topic. I believe that we shouldn’t face architectural choices in dogmatic sense. Definitely. We’ll touch on that a bit later.

    Miłosz [16:28]: Yeah, we’ll touch on it.

    Robert [16:30]: Oh, another person missing working with Miłosz.

    Miłosz [16:34]: Even though we didn’t work together. Yeah, maybe in the future Oleg, who knows.

    Robert [16:40]: Greetings. Yes, so there’s one comment about overengineering. I see when using interfaces a lot. A lot of projects are created with a single interface each struct. We’ll touch on that also.

    Miłosz [16:57]: Yeah, I think that’s a very misunderstood part of the pattern like how to use interfaces.

    Robert [17:04]: And it’s actually, I think, pretty easy to overcome and also to have some way of understanding when needed problem. But no worries, we’ll touch on that. It’s like using abstraction without being abstract.

    Miłosz [17:19]: Yeah, that’s a good point.

    Robert [17:20]: I think it’s exactly that. But again, we’ll go into that. As I understand clean architecture, you can’t depend on layers that are deeper one level. So you have to duplicate structures every time that makes me sad. Yes, but not always. I think we’ll also touch on it. Okay, so hi, I work at a big e-commerce company with 10k+ IT area with 4,000 microservices. That’s the scale. Okay, to give some context, there is an area which is a clean architecture for most of their microservices. So this is probably around what we said a bit earlier so Or maybe not.

    Miłosz [18:12]: And there is a follow-up, I think you need to include this.

    Robert [18:15]: You can touch on it.

    Miłosz [18:18]: Yeah, it’s implemented across apps and libs, all Java of microservices. This fact implies that all the areas have an important learning curve to understand and add code here. Yeah. So you mean that there’s, bigger learning curve to understand the code because of it? Which can happen, and we will also cover this.

    Robert [18:51]: But I think it depends a lot on how you’re implementing that. So again, I would say that it should be some hint like if it’s taking a week to explain a person how can architecture clean architecture work in your company probably something went wrong and it’s maybe not really clean architecture but something around. Because, again, explaining clean architecture and showing it in the code, it should be quite quick.

    Miłosz [19:14]: Should be, yeah, but not always. I think people always start with this big chart of different circles and shapes and it can be confusing at first. Yeah. I think we will talk about controversies in a bit. So let’s start there.

    Robert [19:35]: So maybe let’s finish with the comments. So, people write the interfaces next to concrete type when it should belong to the client code. Only including the methods itself depends on common mistake.

    Miłosz [19:48]: So this is exactly this misuse of interfaces. Right? So if you do it this way, then there is no inversion of control, basically. Or maybe there is but gives you nothing in return.

    Robert [20:06]: So another thing that we’ll also cover, so no worries, is starting a new project with this architecture. We’ll cover that. How to explain to my colleague that it’s worth using this approach? I think we’ll also cover that. And again, later I will also recommend checking the articles that we’ll link a bit later. So we are also in those articles giving some context where when it works and why it’s, makes sense. Okay. And to catch on the last comment so far, I’m really proud of you guys. Oh, thank you. Because you have decided to run your own company as your main. Now, we’re also pretty happy about that. Alright, cool. So, now, we’re finished with the comments so far. Again, if you have anything to comment in, we’ll be happy to go over it. Alright. So layers. We talked about layers. I already mentioned that it’s not necessary to always use all layers and I think it’s one reason of reason of one common mistake that people are always using the all layers and because of that it’s making it more complicated. So somebody in the chat mentioned that it sometimes hurts because you need to copy structs between layers and it’s a waste of time and it’s true. But it’s mostly true in cases when it’s not needed because you’re just using all layers when its project is not complex enough.

    Miłosz [21:39]: You start with the big idea instead of seeing where the project leads you. Especially if you start small. Probably, it’s better to let the architecture evolve over time than to force some complex ideas in the beginning.

    Robert [21:55]: I think we’re always mentioning that that, you know, you need to be pragmatic at the end of the day. So if you see that pattern is creating more mess and require more effort that it’s giving you back probably it’s something wrong because at the end of the day it should help you and, well, that’s it. And it’s connected to the dogmatic approach of that. I think dogmatic approach is pretty often the case why it’s over complicated because often often there are some people that are saying no we need to do it in this way. It needs to be consistent with everything else.

    Miłosz [22:29]: We like consistency. And I think the topic that we talk about in every episode just keeps coming back.

    Robert [22:36]: But, if you didn’t have chance to check our previous episode about the low quality code highly recommended because it’s also connected to that. Right, but let’s go back to the architecture.

    Miłosz [22:52]: So maybe just to summarize, I think you can it’s very easy to to say what will be the the opposite of the architecture. I think that will be having all your code in an HTTP handler. Your logic, your validation, and, your database code is all mixed in the same handler or controller. I think that will be the opposite, basically.

    Robert [23:20]: And it’s a better approach? No.

    Miłosz [23:23]: It depends.

    Robert [23:23]: We’ve been doing that. Sometimes it was good enough. Sometimes, well, I hope nobody needs to maintain this codebase any longer.

    Miłosz [23:37]: Somehow clean architecture is quite controversial, right? We already mentioned this. And I think for us it was quite surprising because when we started using it, we were quite happy about it and people in our teams were also quite happy. We even heard of them spreading the pattern to other companies as they left our team. Yeah. So why do you think it happens?

    Robert [24:10]: I have one theory. So I think that the theory may be that we are trying to be extremely programmatic. So I heard that I heard it multiple times. So if we have seen that somewhere it was making our lives harder than more helping us it was probably we’re not using this pattern in this case for you and we’re not blindly following that and I know that it’s opposite compared to other companies.

    Miłosz [24:39]: You mean if someone forces you to use it? Or maybe someone someone has seen it implemented in a way that wasn’t the best to work with?

    Robert [24:50]: Or even worse, somebody is forcing you to use that without understanding it. And this is the ultimate combo.

    Miłosz [24:57]: For the sake of consistency, for example. All microservices in our company will follow Clean Architecture. So, yeah, that might be controversial and that might scare people, I guess. And for some reason, this is tends to divide people. And often I hear something like, you must be Uncle Bob cultist because you use those patterns. So it starts to get almost political maybe, I don’t know. It’s funny.

    Robert [25:38]: But for what I can see in the chat? I can see that some people actually also see it pretty pragmatic. So, I don’t consider hexagonal architecture over engineering at all. When building a bigger than just couple of weeks project, first, it allows to register stubs for our own implementations, details, and tests. Yep, it’s true. The second comment saying that I believe clean architectural learning is not that hard. Yep, that’s true. And we believe that it’s true. I have seen people moving to similar way of development without knowing those concepts exist. Yeah. But I think we can compare that. And actually, one team will have ultimate combo because we’ve been building a project in Go that and that time Go wasn’t that popular language and 90% of the team was learning Go and Clean architecture at the same moment and it wasn’t an issue. Maybe we’ve just had a great team. It was probably also important reason there and very open minded and great team. But, yeah, at the end, it was cool.

    Miłosz [26:57]: I think you skipped one. I think you skipped one comment.

    Robert [27:02]: Did I? Yeah. Hi folks, I’m wondering how well clean architecture matches the lang’s initial idea. From the little that I’ve read about it, I had feeling that Go apps were supposed to be a little simpler. Oh, yeah.

    Miłosz [27:24]: My favorite topic of keeping it simple and we will touch on this and on Go later. So stay with us, please.

    Robert [27:36]: Right.

    Miłosz [27:41]: Those comments are very much about the architecture not being that complex in the first place. I think maybe it is clear when when you learn it. But I think if someone doesn’t know it yet and sees a codebase, then it can become quite confusing. Right? I remember once when our team was using it, but other team in the company was not, and people there were not aware how it works. And for some reason, they had to debug something in our codebase one night. And that was quite confusing for them because if you don’t know the rules, know where the dependencies are, and so on, it can be quite confusing at first.

    Robert [28:31]: Yeah. But I think important part of this is being kind of open minded because if somebody is like, oh, clean architecture is bad over engineering. I don’t want to look on that. So obviously, if somebody have approach like that, well, it will not work. But if somebody’s open minded and he’s open to learn how it works, it helps a lot. Yeah. But And I think that that was part of the problem that other teams were like, no, I don’t like this idea and why we are doing that?

    Miłosz [29:03]: We like consistency, as we said. So, you know, if we use the simple Go mindset, for example, let’s say, it can be it can add to this controversy of using it. I mean, that might be one of the reasons.

    Robert [29:19]: And it’s also worth mentioning that often within a company you have multiple teams solving different problems. So some of the teams may be solving some simpler problems that doesn’t require some advanced techniques and some teams in the company may be working on very complicated domains. And it’s not a matter of using any tool that it’s complicated. It’s just complicated by design and you can help to tackle that, but it’s just helping you to make it simpler. But it has some base complexity, let’s say, that you can try to tackle, but it will be always complex because just logic is super complex.

    Miłosz [29:56]: So should we talk about some common issues maybe? How it fails basically?

    Robert [30:08]: Yeah. Because we were discussing this topic a bit earlier with people on some social media or in real life. Yeah, it was a very common topic to understand why it’s not working in multiple projects. So we gather multiple reasons that we know that it’s leading to making the architecture overcomplicated or even project failing. By the way, if you have any, any stories from you, also please leave it on the chat so it will be also cool to hear about that. Right. So the first thing is, over engineering architecture. So as we said multiple times and it was also mentioned multiple times on the chat, clean architecture is not that complex pattern. So you’ll have three, four layers. It depends on the complexity of your application. You’re ensuring that layer from inside doesn’t know about layer of in the outside, and you’re using interfaces to do inversion of control. That’s it. But, unfortunately, people are going sometimes a bit too far with that.

    Miłosz [31:14]: Yes. Because what you said doesn’t sound like proper architecture. It reminds me of this, what we discussed in previous episodes about this belief that we can figure out the architecture now, and in the future, we will just cookie cut the services or applications. It sounds a bit similar to me that we try to figure out the perfect architecture first, all the rows in place and layers and so on, and then just apply it. It sounds much much better than just following some simple rules of using interfaces. And it’s easy to go too far, right, and become a purist and just force this idea everywhere.

    Robert [32:06]: So, overconsistency, let’s say.

    Miłosz [32:09]: Yeah. This is the hard part, when you want to be consistent and when there is too much consistency.

    Robert [32:19]: It’s always a cost. so the second thing that I have in mind about clean architecture and I think this is probably the most common one so it’s and I think somebody mentioned it on the chat so it’s using too many interfaces. So in general, the interfaces are needed if you are kind of communicating between layers so those layers inside will not know how what’s implemented then. But that’s it. But very often I’ve seen that within the layers before putting more interfaces. For example, you have domain layer and under the hood it has multiple interfaces. And what’s even more funny often it’s under the hood have only one implementation. And it’s pretty problematic because one, it’s harder to inject that because your dependency injection is starting to be super hard. And this is something that is also probably common thing common thing between between multiple episodes because people were saying that they have complex of complex problem with complex dependency injection and from my experience, it’s often the problem is that your dependency tree is too complex. It’s not a problem with some dependency injection framework or whatever you are using. So if you’re not able to inject your dependencies by hand, probably something over complicated.

    Miłosz [33:37]: It’s part of the over engineering, I guess. You know, just forcing the ideas because there’s a rule that says accept interfaces because you might want to change them with something else, and then you create some domain service, let’s say, that accepts some some structure. You might you might go and think, oh, maybe I will use an interface here because I am supposed to use interfaces, right? Maybe in the future we will want to change the implementation. And it’s exactly this trap that you take the base ideas and just use them everywhere even when it where it doesn’t make sense. So maybe I no. A good a good a good heuristic here is to think of, what what you want to use mocks for in your tests. That’s probably what you want to use an interface for.

    Robert [34:30]: Yeah, and obviously between layers but this is a different case. And I think it’s very important to mention that, okay, if you are mocking things you should probably mock only things that are IO in general. So it’s database, some external API. You should mock not mock your domain logic because you have no benefit of that. So your test will be worse because you will be not checking the, the real code plus well, it will not speed up your tests basically. So mocking makes sense in most cases when you need to speed up your tests or or simulate some external logic. In your domain code, you should be able to do it through your public API.

    Miłosz [35:13]: Exactly. You can tell you went too far if you’re, you know, if you use too many mocks and all your testers do are checking some function calls on the mocks you used. It probably means you went too far and you don’t need to mock that much.

    Robert [35:30]: Yeah, but there are some exceptions. So there’s no silver bullet. So exceptions are very very very complex domains. So sometimes you may have some complex domain and within the domain layer, you may have interfaces to hide this complexity somewhere. But you never should start with that because it will go in the wrong way. So I guess, I don’t know, within one year probably it will be not possible to have such the complex domain code to, need to have really layers within layers. A couple years old codebase that is super complex, maybe, but I would watch out for that.

    Miłosz [36:07]: Layers within layers actually sound like the Great idea. Yeah. Like the You’re so smart. The next pitfall, right? It’s again over engineering in the layers area. I remember this Reddit post. You know which one? The other day at the Golang sub subreddit there was a Reddit post where the OP said something like, Don’t use pin architecture, it’s over engineering. And of course it, you know, invited me to click. And in the content they said something like, you should have at most three layers in clean architecture. And I thought, yes, of course, what’s the problem? Again, this is how different the implementations can look like. I guess what this person found in the code was, I don’t know, six layers? I can’t even imagine what was there. But that’s another issue, you know, if you just take the idea of layers too far.

    Robert [37:24]: Another surprise. I mean, if I would work in projects where you have six layers at least, I would also hate using that and would love to go with a simple approach, obviously.

    Miłosz [37:36]: Yeah. So maybe it’s good to start with the basics. So you want to separate the implementation details from the logic, from the domain code. And that’s two layers for starters. It doesn’t have to be much more. You can separate the entry points if you want. That’s kind of a hard layer, but I would call it part of the adapters as well. It’s a bit similar. I’m not sure why would you use something beyond the domain layer. What’s the fifth one? I don’t know.

    Robert [38:16]: Maybe you know somebody is using layers from hexagonal and onion architecture.

    Miłosz [38:23]: Yeah, maybe. So if you see more than four, I would be very, very careful. I would ask some questions.

    Robert [38:33]: Definitely. The next thing that I have in mind about the common problems about clean architecture is using it everywhere. So one point that we’d like to, you know, give you with this live podcast is that there’s no one single way to use something as we’re mentioning, in the intro. So if somebody is saying you always do x or never do y, It’s pretty big chance that this person just work in some specific type of projects, but it’s not universal advice.

    Miłosz [39:09]: Or they want to sell you something.

    Robert [39:11]: Or this. Some shortcuts as usual. But what is the message? So the message is that, you know, clean architecture is nice, but it doesn’t matter that you need to use it in an entire company. So the thing that I mentioned a bit earlier. So often in company, you have teams and services that are complex and simple and using the same approach for everything is just crazy because in some places it will be over engineering and sometimes it will just suffer from from the complexity that is not handled properly and it will be also the problem.

    Miłosz [39:51]: Sometimes even in the same project in different modules, it also has some trivial domain that doesn’t need it. Just what we have in the White Workouts, our example project, the Users module or service is basically a Scrub domain with no layers at all. Yeah, and it’s different for your past projects because if

    Robert [40:14]: You are working on something after work, it doesn’t matter that much. I think it’s worth trying multiple approaches to have your opinion on how it works. But in a job, it well, it’s worth to be pretty mindful. And if your project is not complex maybe clean architecture may be not needed but sometimes it may be worth with starting with some simple one without domain layer, for example. It doesn’t cost that much. But if you know that your team is bigger, then it can make sense to start with that.

    Miłosz [40:46]: Yeah. And and some apps are are may most of them are not be a good fit or maybe if you create a library, for example, maybe it’s not the best idea because the users might not be familiar with it or for things like CLI apps maybe or something infrastructure related.

    Robert [41:06]: And you if you think about that, so libraries are usually living in inside of some other layers. They are not covering multiple of them. So usually, it’s probably adapters or ports. Like, for example, Watermill library that we’re maintainers are also It’s living within ports and it’s not going to other layers basically.

    Miłosz [41:26]: Yeah, exactly. So you don’t want to tie it with your application logic or the domain. A similar one is Project Structure, which we mentioned before. It also keeps coming up in our previous episodes that it’s easy to focus too much on the project structure in the beginning. Again, it’s this idea of, you know, let’s prepare this great environment, great architecture, and then we can just keep adding features. Most of the time it’s not that easy and the project will evolve anyway, in some way you don’t know yet. And you can always refactor, right, if it changes. So I wouldn’t start with thinking of the, you know, what’s the perfect project structure or what’s the perfect number of layers. Just start with the basics, something simple and then refactor as you go.

    Robert [42:40]: And assume that you may be wrong. I mean, we have almost twenty years experience with coding in general. Also pretty much years, you know, with architecture and still we are not always right. But I I think it’s important to know how you can be not right and how to handle that and not go too deep into the wrong architecture, basically.

    Miłosz [43:05]: It’s probably not possible to invent the perfect structure in the beginning anyway.

    Robert [43:16]: If somebody is saying that he can do that, don’t trust this person.

    Miłosz [43:21]: They want to sell you something.

    Robert [43:25]: And overall I think it’s if you’re thinking about some pitfalls of architecture or problems with that. So the most important thing that I believe made our teams happy about using this is keeping in mind that it should be helpful for you. So the goal is not using any kind of architecture.

    Miłosz [43:44]: Oh, it’s a big one.

    Robert [43:47]: But the goal is to use something that is useful for you. It supports your velocity because at the end of the day, every technique that we’re using, it should allow you to code faster and that’s it basically. So if you are using some architecture and it’s slowing your down, you cannot iterate faster, it’s probably the bad one.

    Miłosz [44:12]: I mean, it’s very easy to start being dogmatic about it, to become like a purist. And it is tricky because we have a bigger team and it helps to have this consistency around the project. So Clean Architecture gives you this consistency in supports. But then there might be places or features where it’s not a great fit. But if you want to break the rules, then someone needs to decide if it’s fine to break the rules or not. And it often starts those endless discussions about it doesn’t follow clean architecture or it breaks.

    Robert [44:57]: Which layer it should be in? Is it domain logic or it should be in domain or application layer?

    Miłosz [45:03]: Okay. Let’s call it a meeting. A meeting to discuss is super important. And sometimes it is important but sometimes it’s not. It’s not. It’s just, you know, a detail.

    Robert [45:14]: And, unfortunately, this is the topic that we cannot give cannot give you a simple ask for like always do x. The best way, unfortunately, here is to just do it over time and learn by doing and probably this is the best advice that we can give here. But, well, it’s hard to have any shortcuts here because there are just many different kinds of applications. And, again, it’s important to be open minded. Also listen to your teammates because it’s also easy to be, you know, the architect or the person that gives architecture. And if you are going to holidays and going back, you see that it was all removed. It’s probably the sign that.

    Miłosz [45:54]: Have to change everything.

    Robert [45:55]: So, you know, it’s also probably the sign that, okay, maybe something that you invented is not that helpful for people because if it would be if it would be helpful for them, they would not remove it during your holidays.

    Miłosz [46:08]: I think this this factor is for sure part of the controversy around it. Because if you if you have been in a team that, you know, spent hours discussing in which directory to put some some codes, then you you might assume you don’t want to work with Cleanarch anymore because it’s just it’s too much hassle to to keep discussing how to use it instead of this right code. Yeah. And especially if you didn’t have the proper onboarding for new people

    Robert [46:39]: In your team because often, you know, people are changing teams, changing companies. And this is also important thing to ensure that, okay, the new person is joining the team, the person will know how it works in your company and how to navigate about that. Because if you will not do this, the person may be not happy about it.

    Miłosz [47:00]: Yeah, it’s probably best to show them instead of having some documentation because I think it’s easier to show it as an example maybe than reading about something. Definitely. But on the other hand, I think clean atch also enables some nice onboarding because you can have those you can have new joiners implement something quite simple because of the separation of layers. Like, you can give them an HTTP handler to implement and it will be a quite simple task. They can probably do it in one day and get started with the codebase.

    Robert [47:41]: And again, we’ve mentioned it already a couple of times but if explaining to some person your clean architecture takes more than half hour, probably it’s something wrong there. So we can say probably it’s some not very accurate metric but more or less like this.

    Miłosz [48:06]: So overall, don’t ignore developer experience. Think this would be the summary. Yes. I think it’s very important because it’s basically what everyone will be working with daily. So you just don’t make a religion out of it at the end of the day and don’t try to use arguments like this is not clean. It’s the worst worst kind of discussions you want to have. You don’t want to have them.

    Robert [48:39]: It’s probably worth mentioning to also set some expectations. So if you have everything in your HTTP handler your dependency injection can be as simple as it doesn’t exist. If you have clean architecture, it’s more complex because you need to inject more things. But again, it should be manageable by doing it by hand and okay, it depends on the language a lot. So with Milosz, we are mostly working with Go where there is it’s compiled language. So it’s a bit harder to do some magical dependency injection. But it’s actually quite good because because you need to do it. So in our opinion, it’s easiest to do it by hand. And if you’re in the position when it’s too complex to do it by hand, probably it’s showing you the problem with your maybe clean architecture, maybe architecture in general, but it should be doable by hand. In other languages, we know that it depends. So we also worked a lot in PHP where it was working automatically. Sometimes it was nice but it was harder to debug with more complex dependency tree.

    Miłosz [49:48]: There are some libraries usually. I’ve seen someone in chat mentioned fx. We haven’t used this one, but we used wire from Google. It was okay. But currently, we just wired wired it up manually in in the main function, basically. And it it grows. It’s big. But most of the time, that’s not an issue, really. You just fix it and if it compiles you’re good to go.

    Robert [50:18]: And I think it’s one risk maybe that some people maybe don’t see at the first sight that but, you know, it’s something making your it’s something making your super complex dependency tree easier to handle. It’s actually opening some kind of gate of hell because you can do we can make this dependency tree more complex if something is helping you with that. Are going deeper and deeper into.

    Miłosz [50:42]: Those layers within layers. Interfaces within interfaces.

    Robert [50:46]: If you are doing it by hand probably you sooner see that something is wrong there.

    Miłosz [50:53]: It’s also a good general rule to start fixing the pain once you start feeling it because if there is no issue maybe you don’t need all these solutions.

    Robert [51:03]: And if you are starting to blame dependency injection framework probably the problem may be not in the dependency injection framework but between laptop and wall.

    Miłosz [51:17]: Tough pill to swallow, but sometimes, yeah.

    Robert [51:20]: Yes. Firmino is actually mentioning that even in Java, dependency injection can be easily done by hand but developers could use using auto wired from Sprint. Yep. That’s true. But again, we’re also not that against using such frameworks but again, you need to watch out. It’s like with every tool. Okay, not every tool but there are some tools that are encouraging you to do bad things and probably dependency injection framework is on this list. But again, it all have its use cases like ORMs also, I would say. So many people also doesn’t like ORMs because it can also lead to some issues. But, in my opinion, it’s like with knife in the kitchen. I mean, you can hurt yourself with a sharp knife. But from other side, it’s also pretty useful. I like sharp knives. I think you also like You need to just watch out. So that’s it. It’s much better than using blunt knife. And, yeah, the last thing that can lead to problems with clean architecture and we have some solution for that fortunately is using the wrong resources. So many resources that we’ve seen in the internet are unfortunately missing the point of clean architecture and it’s encouraging to use it in the wrong way that is far from being pragmatic. Probably doesn’t help that many of those clear architecture hexagonal onion architecture they don’t have super strict rules on how to implement that and it’s nice because it’s giving flexibility but it’s not nice because it’s giving flexibility on what you

    Miłosz [52:58]: Have to decide for yourself. And it’s exactly where this starts getting difficult because you’re just starting out and there are no, definitive rules. And this is where you start thinking, okay, what’s my perfect project structure? Which can be a trap. And I think many of those open source examples often miss the point or they show some very trivial domains like, you know, to do apps that have two entities and two endpoints. And if you take a look at this as such a simple domain implemented in the architecture, it will look like over engineering, of course, because it makes no sense if you can fit this into files to split it across the project. So you have to be careful of this.

    Robert [53:53]: But there is also one, tricky part about this because so we have run repository in Go where we are showing how to you can connect everything. And I think it’s, you know, fully worked application. It’s not that complex still because it’s still some more pet project even if it’s fully functional. But also, if project is too complicated, it’s also hard to grasp the most important parts of that. So it’s it’s all about the balance. So as mentioned multiple times, at the end of the we’ll give you links to the useful resources. But, yeah, it’s important to just use those resources.

    Miłosz [54:35]: Yeah. I see an interesting question in the chat. So does clean architecture fit in projects with lots of tiny and simple microservices or better fits in a monolith application?

    Robert [54:51]: It depends. There is no silver bullet.

    Miłosz [54:54]: Yeah, what’s a simple microservice? I guess that’s that’s the question. I I hope if you have, a monolith, it is split into modules just like those microservices, and then it’s pretty much the same answer. If if the module or service is complex enough, to benefit from Cleanark, maybe a good idea to implement it. If it’s truly trivial and crowd domain, probably not.

    Robert [55:24]: Yeah. But I think there is one risk that I’ve seen multiple in my life. You’ve seen it as well. So because microservices are cool for splitting complex problems into smaller but the problem is that often people are splitting it to granular. So you have multiple so instead of having one service that can handle some, use case you have five, ten microservices that are handling that. It’s okay. Maybe every service is pretty simple and you don’t need to have clean architecture inside of that. But each time when you’re implementing a new feature it takes changes in five or 10 microservices.

    Miłosz [56:03]: Yeah, because because it’s different entities, I guess. Yes. Yes. My favorite from the past is the Avatars microservice. Stored Avatars.

    Robert [56:14]: And, you know, if you have sub granular microservices, okay, and then you split at your complexity but if implementing one functionality takes changes in 10 microservices, I’m quite sure that it will be much easier to implement it within one service that is not maybe microservice, whatever microservice is. But doing it in one service will be easier. And okay, this one service will be more complex but Clean Architecture can help you with, handling this complexity because you don’t need to split this complexity in multiple services. You can instead split it by layers. And it’s making your so this is the thing that we’ve done multiple times. So it was 10 microservicization operations. So moving multiple microservices into one service and obviously this one service was more complex but clean architecture was helpful to handle this complexity because we didn’t have one big sum of everything but it was data in multiple layers and at the end implementing features was much easier. So, yeah, I hope it’s useful.

    Miłosz [57:21]: Yeah. Looking at the chat, I’m gonna read the next one. So, Tony says, For me, the most difficult part of clean architecture is when implemented in a team and different people diverge in some details and the mess appears when little by little the project becomes less consistent. This is exactly the developer experience issues we talked about previously. I think it’s very hard and probably what can help is having some team leader in place who can just cut the discussions and make a decision. Because otherwise, yeah, you can take long hours discussing, and it’s natural that some people in your team will be like consistency more. There are many developers who strive for this consistency and like to have everything neat and tidy. And if someone starts doing something in a different way they will be annoyed and you want it to be the same way. And I think it’s probably worth mentioning that,

    Robert [58:33]: At least, I believe that democracy doesn’t work in programming teams, unfortunately.

    Miłosz [58:38]: Yeah, unless you have infinite time and can spend days discussing and voting.

    Robert [58:42]: So probably sometimes usually something closer to totalitarianism works a bit better. But better to not overuse that obviously. But it sometimes helps with these discussions.

    Miłosz [58:55]: It’s a tough balance, I would say. You want some discussion with the team but you also need someone to say, ‘Guys, let’s just focus on important stuff.’ But it’s very hard to make those know, exceptions because if everything is consistent, why would you use a different way in this in this case? You know, maybe it’s just more easy this way. Maybe it’s fine. But if you do advanced then, no, people exactly what what the comment says people might think that, oh, okay. It doesn’t need to be consistent so let’s just do whatever.

    Robert [59:38]: And then also, if you’re not a team leader but team leader is doing a bit of totalitarianism when you are going too deep into some discussions also don’t be mad at this person because we’ve been in this position and, you know, it’s also not that hard. But well, after you are in this position, sometimes you see that it’s easy to overdo some discussions and that’s it. So sometimes at the end of the day, it’s better to have something that works, but it’s not perfect, but it works because sometimes you can throw it out. Probably you can listen more in the previous episode about code quality.

    Miłosz [01:00:13]: Yeah. I think it’s one of the most difficult parts of implementing clean arch. We don’t know definitive answers here.

    Robert [01:00:24]: Yeah, there’s also a nice comment about frameworks. Frameworks like Rails that define a clean directory structure seems to be harder to apply that architecture and I would say it’s still possible. So I don’t have that much experience with Ruby on Rails but I worked more in PHP with PHP frameworks like Symfony or whatever and those frameworks usually okay, it requires some effort but usually you can hide them in some layers. So mostly those frameworks are about your ports but it’s also sometimes a bit application layer but it’s doable and it’s often worth doing but often it’s also not worth doing. So it’s getting probably hard to give some universal advice here but you can do that in general. And sometimes it may be beneficial for more complex domains because those frameworks are nice and we’re discussing it in the previous episode also about frameworks. But long story short is that they can give you some velocity at the beginning but later it may be harder to do some more context scenarios. And if you went with this framework structure all in, it’s much harder to customize that as and sometimes, you know, the product after a couple years, it’s still within the framework and we work sometimes in such companies and it’s even impossible to get rid of this framework because it’s so integrated with your code. And if somebody will split that in the screen architecture way, it will be maybe possible to replace that and maybe just not use it at all. And it will be possible to develop this, product further. But often, unfortunately, it’s something like that. And it’s super hard to develop the product further because it’s so limited. But it’s probably worth mentioning that often those projects were successful because at the beginning they’re they’re managed to have free fast velocity and win the market.

    Miłosz [01:02:22]: Yeah. That’s that’s the benefit of using them. But if you can introduce even some, you know, thin domain layer or something that’s separate from from the framework, that might be helpful if you want to move on. Not to use everything it gives you. But, of course, then then it’s kind of, you know, defeats the purpose of of using the framework in the first place.

    Robert [01:02:52]: Right. So we talked about, what are the common issues of clean architecture, what are the contraversions, but I think there are also some upsides that we’ve seen multiple projects and some reasons why this maybe was invented because it’s like with many techniques like it wasn’t invented for no reason.

    Miłosz [01:03:14]: Yeah, exactly. So the why behind it is important. So maybe let’s start like we did, yeah, with the burning it down with separation of concerns. And, you know, it’s the reason we we want to separate those concerns is this this logic independent of implementation details. Right? And, basically, the what it gives you is you’re you’re able to easily replace one implementation with another, which we talked about about mocking. That’s one use case. Super useful. But also you can replace it with something completely different like changing the database.

    Robert [01:04:16]: It’s quite interesting because you can do that, but how often are you doing that?

    Miłosz [01:04:19]: Yeah, that’s a good question. It’s often a counterargument I hear about clean architecture or interfaces in general. Like, yeah, yeah, you talk about how it’s easy to change from one database to another, but in reality, it never happens. But it happened to us recently, so that’s one example when it was useful. So we switched from Firestore to Postgres, and using Zaprouted was quite easy. Another nice example we did, in the past was starting with in memory implementation. So creating a domain domain code with some very simple, in memory implementation of the database. And then later when we know this is what we want we can just replace it with SQL or whatever implementation. It’s also quite nice.

    Robert [01:05:22]: Yes, but I think it’s also worth mentioning that this is not the end of the architecture. So the end goal so it’s designed. So if you can replace your database or port easily. It means that, okay, you did a good job with implementing architecture, but it’s only showing you that it’s done properly. But it’s not the end goal in general.

    Miłosz [01:05:51]: Yeah. In reality, you’re not going to be changing the database every few weeks. So it’s it’s not why you do it. But I think but it gives you this nice separation of, you know, the implementation details from from the interesting code in your in your project.

    Robert [01:06:11]: Yeah. And why it matters? So it’s mostly because of, cognitive overload. So as I mentioned a bit earlier, so when you have multiple microservices that were too granular, you are joining it into one service. If you would be all in your handlers probably it will be very complicated. But if you’re splitting it in multiple layers, it’s allowing you to so as long as you know how the clean architecture works, it’s it’s making you a bit much easier to reason about the code base because you see what are the entry points of your applications, what use cases are supported, and how you’re interacting with the database. If it’s everything here in your HTTP controllers, for example, it’s super hard to understand that because you can have some query that is called in some weird way, but it’s hard to backtrack how it’s called.

    Miłosz [01:07:03]: Yeah. And and usually it spills over somehow to your to your logic.

    Robert [01:07:07]: And it’s nice if you have some transaction, but often it’s not.

    Miłosz [01:07:15]: And if you don’t have the separation of any kind, it’s also very easy to lock yourself in with some framework or library because, you know, you just scatter the library method calls all over your domain code. And if you want to migrate later you have all those places you need to change which is much more complex.

    Robert [01:07:39]: And there is one interesting comment about abstracting the database layer, that it makes sense when you need to support different databases. So you need to choose what to deploy. And it’s a very good point. And once in our life, we actually did something one level higher. Long story short, we worked, with the product that needed to be deployed in two ways, as microservices and as monolith. And it wasn’t some it wasn’t some crazy architectural idea. It was a pragmatic thing. So it would have, two deployments. So one in physical, servers and physical device and one in the cloud with the kind of simulated device. And because of that, it needed to be deployed in this way. And architecture was quite cool because of that because it was a matter of having two set of ports and adapters. One for the cloud deployment and one for the more bare metal deployment. And it worked Mhmm. Pretty nicely. And it thanks to that, it was manageable to do this.

    Miłosz [01:08:39]: Yeah. That’s quite quite a specific approach, but that’s a good fit for for clean architecture in general.

    Robert [01:08:46]: Don’t do that. You probably don’t need to do that, but, yeah, sometimes it’s useful. Alright, so the first thing was the cognitive overload. But the second thing is that help is much easier with clean architecture is testing. And like cognitive overload which is important for a more complex project with bigger team, etcetera etcetera. The same goes for testing because when your, project service or whatever is small, probably doesn’t matter what you test. I mean, you can probably just test it end to end and you can do that. But if you are working in the application that have thousand of use thousands of use cases, a lot of complex interaction with your database, testing it end to end is impossible because probably most of the use cases you cannot trigger with the public interfaces and it will be super super slow. It’s especially, true for applications where the domain layer is very complicated because you can have even thousands of use cases and test cases and running it with the database, it will be just super slow. So mocking the extra level is the must because in other, I mean, obviously, you can wait a week for running test suite and I know that such application exists but probably it’s not something that you would like to do.

    Miłosz [01:10:09]: Yeah, and often having parallel tests in the same database is not often trivial to do. You can have conflicts between the use cases and so on.

    Robert [01:10:19]: At some point it will be slow. I mean, obviously you can scale it horizontally but Yeah.

    Miłosz [01:10:24]: There’s often this argument that you can you have Docker, right, or test containers. You can just spin it and run all on this infrastructure. And it’s true. That tests are so critical, you know, path of local development and CI that you probably want them the fastest you can.

    Robert [01:10:45]: Exactly. So for example, if you’re changing some important functionality, you don’t want to then wait ten minutes every time when you change and change that. You would like to wait at most one second and see. Okay. It works. Oh, no. And thousands of unit tests are running and checking that. But it’s the thing that it’s again important for bigger projects, not all projects. If your project can just have end to end tests, it’s fine. I mean, we worked with some projects. The main project that we’re working on now in Tridos Labs, the Academy, is at the at the beginning we just have end to end tests for a pretty long time. It was just enough. So

    Miłosz [01:11:25]: Yeah. I mean, if we were if we had unit tests, it would be even better. But sometimes you have to optimize for delivery speed. Exactly. So that’s what we did. Yeah. Speaking about tests, maybe we can just quickly talk about how we speed them. If you have multiple layers, you you probably don’t want the same testing approach for for all of them. So, for example, as we mentioned, for the domain layer, unit tests are are great fit because it is purely logic. There is no usually little dependencies that you can mock out, and you can have many many test cases that run fast using just viewing tests. That’s that’s pretty nice. And on the other hand, the adapters usually are a good fit for integration tests. So this is where we run some Docker database, for example, and just test the repository or the client or whatever it is in in separation from the domain. Right. And for the entry points and the application layer, we usually have little tests here, if any, because if all it does is translates one layer to the other and orchestrates things, it’s probably not no big benefit in testing it.

    Robert [01:12:52]: And I think it’s actually one common issue that we’ve seen multiple times and I think we forgot about mentioning that. But, yeah, if you have domain layer and application layer, running a lot of unique tests for your application layer probably doesn’t make sense, especially if you’re mocking everything around because it’s

    Miłosz [01:13:10]: Yeah. There are all kinds of tests. Especially if you have those mocking libraries that let you assert whether a function has been called, then your your test becomes become basically an application of your code. And every time you change anything, you have to go to a test and adjust it and basically gives you zero value.

    Robert [01:13:31]: Yeah. I think it’s actually great symptom, let’s say, of why you have the bad tests. So when you are copying your logic of your logic in application from application error, for example, literally to the test. It’s it means that it’s something wrong with your tests. Yeah. And especially if everything around is mocked. But I think there is one nice, type of tests that are solving this problem nicely.

    Miłosz [01:14:01]: Which is?

    Robert [01:14:02]: Components tests that I think at least from my experience not many people knows of but long story short, idea of component tests is that you’re mocking everything from external word and usually you’re using so you’re running your application in for example, Docker, you’re mocking all external words or external APIs, everything. You have just your database in the Docker and maybe and everything else is mocked. And you’re calling public APIs of your application and that’s it actually. So, it’s different from end to end tests because you’re not integrating entire application. You are just having actually stops for the external words and it’s nice balance because you don’t need to, have super big environment to integrate everything with the downside that obviously you may mock some wrongs in the wrong way. But this is this standard problem with mocks but it doesn’t mean that you shouldn’t have end to end tests that are integrating everything. But you can cover much more cases than in end to end tests because you can define behavior of, the external APIs plus you’re also checking the integration of everything. So it’s covering a bit.

    Miłosz [01:15:18]: Yeah. Probably the biggest benefit, Maybe the benefit, but the characteristic is that you don’t call other services in inside those tests. So you have to somehow stop them or use numerators or something like that. Because you you want to test this one service end to end basically basically not the entire infrastructure around it. So it’s also quite fast thanks to this.

    Robert [01:15:46]: Yes. And it’s much easier to also run local because if you are running end to end tests with entire infrastructure, it’s not possible to run it on your laptop. And we’re big fans of being able to run as much as you can locally and test against that because it’s much easier to and faster to iterate over that.

    Miłosz [01:16:05]: But no one enjoys, like, another team service breaking the test URL locally. It’s the worst experience. It’s not productive. So if you want to learn more about, testing this architecture, we have also a blog post about it, and we will link it in the description. Maybe another, like, like, less technical benefit I like about clean arch is, how it changes your mental model over time. So it gives you this kind of consistency in the project, so it’s easy to find what you look for. For example, if you if you want to add a new API entry point, API method, or message handler, you know, to which directory to, you know, to go and which files to edit.

    Robert [01:17:10]: And this is actually the often the counterpoint of many people that’s, yeah, I’m looking on this clean architecture project and I have no idea where everything is. Come on, spend fifteen minutes to understand where it is.

    Miłosz [01:17:23]: Yeah, if the project is big enough and you work with multiple people on it, and this investment in learning, you know, the structure probably pays off, especially if it’s consistent with how you do other projects in the team. And I think it also gives you this if this mental model spreads among everyone in the team, it gives you this nice vocabulary to to use. So, you know, when you discuss how to implement on some feature and someone says, okay. We need SQL adapter. Then everyone knows what is this, and it’s quite clear how to implement it. So it’s it’s very easy to, to discuss the the project.

    Robert [01:18:14]: And then what’s useful in this because I know that it may take some time what layer you can import to what layer and works forbidden. The good, the good news is that there are leaders that can do that usually. So, for Go, there is go clean arch linter I written a couple years ago and it seems that it’s pretty useful for many people. I guess it have probably around thousand stars in GitHub so probably it’s useful. Often you have also linters I think in Java like, ArchLint or something like that that you can define some, I think it’s in Java and PHP. So you can define what are the modules interaction. So, yeah, it’s recommended to check for that, and it’s pretty useful to because you can ensure that the dependency between, layers is properly handled.

    Miłosz [01:19:10]: Yeah. In in Go, it’s especially useful to have this clear direction because you you can have import cycles. Your code won’t compile otherwise. So if you have some, you know, some clear way to to import between packages, it becomes just easier to stick to one way and don’t worry about it again. So that’s that’s quite nice. Maybe maybe the next one would be what I also like about cleanarch is how it becomes easy to extend the application over time. And it’s a it’s a bit similar to this idea of having, you know, great architecture from the start. But I think it’s a bit different because you don’t really need to have all the use cases. But thanks to this clear structure, for example, it’s easy to to add new SQL implementation or or or, for example, to to change one database query with another. That’s that’s faster. And the impact is very low because I mean, it’s the the plus radius is small because you you don’t touch multiple files and areas. You just change this one little part and it works. So you don’t need to think of all use cases in the beginning, you just adapt over time with new adapters, with more application use cases, And this way you avoid side effects. In contrast, if you have this huge HTTP handler with everything in it and you make some changes to it, you don’t really know what can happen. That’s, you know, the worst scenario you can have when you work with a project you don’t know well, and you see this huge method of thousands of lines, let’s say, and you make some edits but, yeah, who knows what happens next. We don’t really know this. It can affect many, many areas.

    Robert [01:21:25]: And, yeah, the last upside that it’s coming into my mind is the one that I think many people doesn’t think about, but we used it pretty heavy in previous teams. So it’s how how it helps you to split work.

    Miłosz [01:21:41]: Oh, yeah.

    Robert [01:21:42]: Basically, the idea is that you can plan some work so you have some feature to implement. You know that you need to implement it pretty quickly as usual. It will be great to parallelize your work as much as possible. And how we’re usually approaching that was, agreeing on the interfaces between layers and just splitting the work. So, for example, we had some feature to implement. So we agreed that, okay, for example, we need such interface to integrate interact with database. This is more or less what we need to have in the domain layer and we could split this work for four people, for example, and each person was responsible of implementing one layer and it was quite simple after they agreed on one interface. And thanks to that, implementing one feature instead of taking, I don’t know, three weeks, it was possible to finish it within one week including deploying that. And it was most important for features that we needed to just implement quickly. And this created some nice separation for each person and they were sure that we’re not, not conflicting that much. And, obviously, sometimes there were some changes into the interfaces because, well, you will not be always sure always right from the beginning. But assume that you are talking to each other.

    Miłosz [01:22:58]: Yeah. But I can just it gives you this nice vocabulary to use. So, for example, when you when you split, the feature into smaller tasks, someone can say, okay, I will take care of the HTTP layer. And it’s super easy for them to, you know, create this API definition that will just do nothing in the beginning but will be merged, can even be deployed, and everyone else can integrate with it.

    Robert [01:23:24]: And you can also split by complexity often. So, for example, you have some junior person, some principal person, and some mid developer. And more or less you know how much complexity will be in each layer. So usually, for example, your HTTP layer shouldn’t be that complex usually because sometimes you have. Sometimes your domain logic will be very complex. Sometimes it will be quite simple. But for example, adapters will be complex or vice versa. And it’s also very helpful to kind of assign work properly.

    Miłosz [01:23:56]: Yeah. And it helps helps you create smaller tasks and PRs which is also a great thing. If you have, you know, a one file change in SQL adapter, I can review it in two minutes probably or something like that versus this whole feature where you need to focus on everything else. I think it’s quite unique overall, this approach. Mhmm. Because I think in most teams, you would expect to see something like, Okay, Robert, you’re supposed to work on this feature now. So see you in two weeks and you will show us what you have. And then you will come up with a PR that’s, like, I don’t know, 4,000 lines long. And then everyone spends reviewing it two days.

    Robert [01:24:47]: And you have 100 comments like why you did like that or I don’t like this. Exactly. I think it’s even a good situation because often you will also struggle to find somebody who will do your reviews because this is the problem often when you are not working as a team but a set of individual stuff. Yeah. Your, goal is to your goal is to implement feature. It’s not a team goal. And if you are working at it as a team of four, for example, or five, you have always people to review that and work is just going much, much, much faster. Yeah. But important disclaimer again, it’s for, as we mentioned earlier, it’s for more complex projects with bigger team. Again, for a full team, it’s not a big team but it’s not two or one person team, obviously. And we assume that it the features are complex enough to take one week of four people. So Yeah. Also important to keep in mind because, you know, sometimes there are features that one person can implement within one week. And using four people to implement that with green architecture, it will be just over engineering probably, and it will be just waste of time.

    Miłosz [01:25:55]: Yeah. But it’s good to keep in mind it’s possible to to speed work, actually. I think it’s not the the default for sure in the industry and somehow we accept that, you know, it’s normal to just have someone sit on a picture for two weeks and then review what they did. Or other two weeks? Yeah. It’s really not that productive. And sometimes if you have the layers especially, you can have three people or four or two work on the same thing and you know, do it in parallel on different areas. It’s super effective because you have those small small PRs, smaller, bus radios of of the changes. You can deploy early often and all those good things.

    Robert [01:26:42]: Yeah. And I’m not sure if you remember but I remember this feeling like just work flowing.

    Miłosz [01:26:48]: Yeah.

    Robert [01:26:50]: Yeah. It was just pleasure because it was super effective and even very complex features were able to, you know, deploy it within one week. So it was cool.

    Miłosz [01:27:01]: Another benefit that’s kind of not relevant to Clean Arch, but you have those small subtasks in each feature and you can see how it moves on the board every day, you don’t really need stuff like estimations maybe because, you know, whoever is responsible for the product or any stakeholder can just take a look at the board and see, okay, five out of eight subtasks are done in two days. So probably in two days they will be done with this. Okay.

    Robert [01:27:33]: It requires the team to have a pretty big, let’s say, engineering culture to achieve that.

    Miłosz [01:27:39]: Yeah.

    Robert [01:27:41]: It’s very highly recommended to at some day work in such a team.

    Miłosz [01:27:46]: Yeah. I think that goes a bit beyond clean arch. But I think clean arch is what really enables it. If you don’t have this clean separation in the code of different layers, then it’s very hard to split work because you will just keep getting, you know, in like, merge conflicts are the probably the least issue, but just conflict of who who works and what and how it impacts each other’s work.

    Robert [01:28:19]: Yeah. Yeah. Probably it’s a topic for a separate episode how to do this splitting because it’s also not obvious how to agree on this, let’s say, one week work and everything like that. But definitely we’ll touch on it at some point.

    Miłosz [01:28:34]: So we talked about the benefits, talk about talk about the issues. The the question that’s asked very often when someone asks about architecture is Can we just do it simple?

    Robert [01:28:49]: And I think it was even mentioned on the chat.

    Miłosz [01:28:51]: Yeah. Especially on on the chat, I think it was related to Go, which is a very good point because Go is seen as this simple language, you know, in contrast to Java, I guess, or C++ or whatever you want. And this is true. But does it mean that clean architecture has no place in Go? So, I think, you know, believing that if you keep things simple, it will save you is kind of lazy thinking, and it can work well if the problems you solve are simple. But if you start modeling something complex, it can it can be worse than having some more complex architecture in place.

    Robert [01:29:47]: Yeah, and I think we’re lucky enough to work in different kind of projects and I think it was nice to try different approaches. Try to do as simple as possible as over complicated as we can to try some techniques and, yeah, I think it’s nice to showing that this balance is not simple, but it’s not like you can always do simple way. It would be great always to go with the simple way. But, well, unfortunately, most of the applications are okay. Maybe not most, but many applications are not that easy. To make it even worse, I think probably we may end up in the situation when those simplest applications can be handled by AI because it’s not complex. I mean, it it can already handle some simple scenarios, but the deeper problems, well, it’s a bit hard to reason let’s say reason AI, but you know what I mean.

    Miłosz [01:30:47]: And it’s hard to define what simple code is too. And, of course, everyone wants to create simple code. I I don’t think anyone will tell you that they don’t want to do it. But, for example, in Go, in the beginning especially, it was, I think, a seamless Flat structure of a project was considered simple. So probably you don’t want to create any packages at all or just a few and then use these files in them. Works well for a standard library. That’s a good idea if you write a standard library. But good luck managing this project with 10 people. When everyone creates files they want, I don’t know. How do you create some consistency then? That’s the hard part.

    Robert [01:31:38]: How do you manage conflicts? So when you have more people working on one service and you have everything in one package, it’s a much bigger chance that you will conflict on something.

    Miłosz [01:31:48]: Yeah. So it’s very, very hard to not be naive about simplicity. But if your team is two people, we are just alone, maybe three people, manageable. Or if you can just fit the entire code in your head.

    Robert [01:32:05]: Or you have 10 times more microservices than people in your team. You laugh but probably you remember some projects where it was the case.

    Miłosz [01:32:16]: I see the solution. You just need to have one file microservices and then it’s not an issue anymore.

    Robert [01:32:23]: Very recommend checking but, yeah, long story short, unfortunately, it’s it can give you some impression that it’s simplifying things. But again, implementing one change in 10 services, it’s no way that you will be able to work efficiently.

    Miłosz [01:32:42]: So basically, complex projects needs need proper modeling and can be approached with this primitive structure. But of course if you use some very simple domain then it makes sense to keep it super simple.

    Robert [01:32:59]: Yeah, and I also noticed that many people think about clean architecture in terms of product structure like you have the structure, multiple directories, but I think it’s not the most important part about clean architecture. So it’s more about the mental model. So I would say that interior you can probably have clean architecture with one package because it’s more it’s harder to manage obviously because you probably will have more conflicts. It’s harder to ensure that you are not interacting between the layers. But, well, in theory, probably, you can do that. But I don’t see a really point in doing that. But, again, it’s not about the structure of the product project. It’s more about how you’re splitting, functionalities in your application. And I think it’s also pretty consistent with the Go philosophy where you should have one package with one responsibility. And in some way, it’s compatible because you can have HTTP package that is responsible for handling HTTP. You have domain layer that is responsible for the domain layer. You have adapters that are interacting with the outside world. So I would say that it’s very compatible with the approach of the language.

    Miłosz [01:34:15]: eah. Yeah. If you put it like that, it’s clearly this. Maybe it’s the issue of being dogmatic but the other way around. So if you are too dogmatic about being simple, it can also hurt you.

    Robert [01:34:33]: It’s quite ironic. I mean, both sides of the barricade are doing the same issue. So they’re dogmatic but just in the opposite direction. But they’re making exactly the same issue.

    Miłosz [01:34:50]: So it’s probably good to remember the the basics and to understand why you do it in the first place. So don’t don’t do it because you want your code to be clean, but to, you know, better organize work in in a complex project that will grow over time will be there in a few months or years, and you have many people working on it. That’s probably good good idea to use in architecture or some flavor.

    Robert [01:35:21]: Yeah. But if your team are two people, it’s easy to go in the wrong direction of the spectrum and over original things and make it just too complicated. So not see any benefits of clean architecture and just pay the price. That is usually not that big if you will not over engineer that because, again, it’s not adding that much overhead if you know what you are doing, but still worth worth keeping in mind.

    Miłosz [01:35:52]: Similar to the, question of should I write high quality or low quality code that we discussed in the first episode. Right? So if you if you have two person team, not, you know, developers who work together for a long time, and they trust each other, know how they work, and so on, you probably don’t need that many roles in place. But if you have a fresh team that just started working together of 10 people, you probably want more more guidelines. So there is some consistency in the project, so they can just work better together. So pick also depending on the team and how how much mature it is. What about some alternatives to clean architecture?

    Robert [01:36:45]: Well, so we already touched a bit on microservices. So as we talked earlier, clean architecture is useful with the handling complexity, making testing things easier. So it sounds like what microservices are promising you. But please keep in mind one thing that we touched multiple times because this is very often the issue that we have seen that people just went too far with microservices and you have more microservices than, people in your team much more.

    Miłosz [01:37:19]: And it’s usually Pretty common.

    Robert [01:37:21]: Yeah. Yeah. And usually, it’s ending up in the situation when implementing one functionality takes changes in 10 microservices. So I’m not saying that microservices are bad, but they are bad if you are splitting them too granularity. And I think it’s one of the sign that it’s done with how many services you need to touch to implement our functionality or, for example, how many services you need to test one entire functionality. So, for example, if testing one use case that is handled requires 10 microservices, it probably may also mean that, there are two granular.

    Miłosz [01:37:59]: Mhmm. Yeah. And there’s also the vertical slices architecture, but we didn’t use it as much yet. We probably have nothing smart to say about it. Yeah. So maybe next time, the next episodes.

    Robert [01:38:15]: Or maybe somebody has some experience with that, so you can write in the chat.

    Miłosz [01:38:26]: Okay, since we work with Go most of the time maybe we can just give some hints about Go specifically using clean arch. I think my favorite part is the implicit interfaces in Go. If you don’t use Go, in contrast to languages like Java, for example, you don’t need to specify that your your structure implements an interface. You just need to define the methods with the same signature as the interface, has. And while some approaches like ports and adapters, such as these separate ports layers for interfaces because you have to keep them somewhere to implement them, in Go you can implement them just close to where they are used, which is, I think, super convenient and also in line with the idea. So you can just define an interface next to the constructor with the dependency it needs. And basically, it’s the only place that knows about the interface in your entire project.

    Robert [01:39:42]: And I think it’s also nice that you can make it work with interface segregation principles. So you can just use some subset of the interface that you’re implementing in the consumer, let’s say. So you don’t need to always use entire interface everywhere. You can just use some subsets of the metal. And it’s useful when you are doing some refactoring and, for example, changing some external adapter and you it’s nicely visible where it’s needed.

    Miłosz [01:40:12]: I think someone mentioned it in the in the chat before. But this anti-pattern of creating, interface with exactly the same methods as the implementation. So you often see something like, you know, interface and then an implementation called the name of interface implementation, something like that. It makes no sense. And on the other hand, if you have the smaller interfaces, many things become easier like testing because your mock just becomes one method instead of 10. That’s a super nice feature of Go that plays well with clean arch.

    Robert [01:40:51]: The second problem that is pretty high a big problem is the fact that many sources are a missing point of clean architecture. It probably doesn’t help that it’s not defined that strictly, let’s say. So it’s adding a big, big, interpretation area. Let’s see. So, yeah, look for good sources. So if you’re writing in Go or you would like to write in Go, we recommend checking our blog obviously because we covered it already a couple years ago and it’s still totally relevant. I think even if you’re writing in a different language, it’s the many ideas are common so it might be worth checking, what we’re writing there. But remember that different languages have a bit different, let’s say, idioms and some things are done a bit differently. So we know it from Go because many people try to port, clean architecture or other techniques directly to go from Java, for example, and it was terrible idea because of what you mentioned a bit earlier. Not, for example, in Go, we have duck typing. And because of that, it’s implemented a bit differently. And it’s worth keeping it in mind.

    Miłosz [01:42:11]: Yeah. And probably the biggest anti pattern you can see in the examples are the single single model used for everything. So So you can have a structure that’s used for, you know, the domain logic, but also it it has database and JSON tags on them, which probably means, you know, it’s also used for storage and for API responses.

    Robert [01:42:35]: And it probably means that we’re getting into this problem that implementing an architecture in such a way will lead to over engineering. Because if you are able to use the same model everywhere, it means that probably you don’t need such architecture and you could just use it everywhere and you don’t need to have all this strange mapping, etcetera. You can just simplify it a lot. But if so if you don’t see benefit so you’ll not see benefit from using this approach. But if you have more complex models and your domain model is not exactly what you’re returning from the API that works in multiple domains like, for example, financial, domain. The benefit of having different models in different places is is there.

    Miłosz [01:43:29]: I think it’s time to summarize and Yeah. Go to the Q&A. So remember about the basics. Right? You want to separate domain logic, whatever it means for your app, from implementation details. That’s the that’s the primary idea of of clean arch or and similar patterns. And try to focus on the on this idea, on the why behind it, not on the how or or directory structure for for starters.

    Robert [01:44:10]: Yeah. And there are a couple things that the architecture should give you and if those things are not met, probably it may mean that it’s not maybe you don’t need to use Clear Architecture like managing complexity with the bigger project, easier to test and write faster tests, you can parallelize your development, you can insulate your changes, and improve navigation. If you don’t have those problems, maybe you don’t need clean architecture, maybe your application is not that complex. Maybe, you know, just having everything in your HTTP controller it’s fine. It’s totally fine. We’re doing it in some cases when because even within one application you can have Twin architecture in some places and doesn’t have it in other places and it’s totally, totally fine. And No use approach. Will save you a lot of time.

    Miłosz [01:45:07]: Yeah. On the other hand, there are some pitfalls. So it might be confusing at first for people who don’t know it yet. So take time to explain it to your colleagues so that you are on the same page. And watch out for common issues like using too many interfaces or too many layers or just over engineering the the basic idea, and watch out for using it everywhere, as Robert just said. So if you if you use modular monolith, I hope you do, not all not all modules need to follow the same architectural patterns. You can use something different in different modules. It’s fine.

    Robert [01:45:52]: And, yeah, to analyze your benefits and pitfalls of your application, it’s worth putting to this equation the team size, your experience, and, well, watching out to not be too dogmatic when you’re doing that.

    Miłosz [01:46:09]: A good tip for whatever you do. So we’ll link some materials in the description. Check out our blog post on clean architecture, on testing strategies as well. And there’s one about integrating clean architecture with DDD and CQRS. In Go. And also the one about the repository pattern is probably quite relevant to clean architecture in general. And all those posts are just a series that describe the white workers repository, the example project. So you can check it out too.

    Robert [01:46:51]: Let’s take a look on comments. So we already covered some of them but let’s check what we have missed. Where are comments? Oh here, okay, so let’s start from the beginning. Yeah, so again a couple comments that people are missing working with me, Osh. Good sign. So usually we’re using clean architecture so, you

    Miłosz [01:47:28]: Know. Yeah. I think it’s the only pattern that I’ve heard of people using beyond, the teams we worked on. So, you know, we met one year later and they told us, oh, you know, I spread it in my team and now we also follow Clean Architecture’.

    Robert [01:47:47]: Or I missed the project that we worked together. The current one is so.

    Miłosz [01:47:53]: But I mean, the the architecture is a pattern I’ve heard mentioned multiple times, but it’s probably also the the only one mentioned so often. So that must be a sign. Right? Looking at the bottom, there’s a question about how clean architecture differs from hexagonal. And I would boil it down to naming with a different approach. I would say we use a combination of both. So it’s not important. I would say it’s implementation details.

    Robert [01:48:36]: But, yeah, I think it’s all about you have some inner layers and outside layers and inner layers doesn’t know how outside layers are implemented.

    Miłosz [01:48:47]: Yeah. And all those variants call them a bit differently but the core core idea is the same.

    Robert [01:48:56]: Yeah. And, you know, my theory about this is that, you know, the multiple techniques are reinvented every 15 years because, you know, there is a hype cycle of every technique that at the beginning it’s, hype time. Oh, yeah. It’s solving all of our problems. So everybody is going into that without understanding how to do it. Multiple teams are implementing that. Some people in very dogmatic way. So people are starting to hate this technique and the word is spreading that, this is a bad technique. Don’t use it ever. It’s super bad. It’s overcomplicating stuff, etcetera. And less and less people are using that. And after some time, somebody is thinking, oh, okay. It’s so nice idea but let’s it’s the name is already so spoiled that we need and we need to name it a bit differently and so people will be ederabad about that. And, you know, it sounds absurd, but it works.

    Miłosz [01:49:58]: So are are you suggesting we need a new name? Yes. And your standards too?

    Robert [01:50:04]: Yeah. So if you have any idea how to name next, iteration of clean architecture, listed on the chat.

    Miłosz [01:50:16]: There’s a question about tests. We kind of mentioned this before. So do you ever add tests on the application layer and how do you go about it? Mocks or fakes in memory by implementing the interfaces? So it depends how many logic do we have there. If we have a separate domain layer, we usually have almost no test in the application layer because it becomes mostly orchestration of things. Yeah.

    Robert [01:50:45]: And it should be covered by the component tests, basically. So you are calling the component tests and it’s going over all layers and checking that everything is integrated with that problem.

    Miłosz [01:50:55]: But sometimes it makes sense if there’s some some logic you can test.

    Robert [01:50:59]: Especially when you don’t have domain layer, for example, because sometimes you may not have enough logic to have a separate domain layer. So you may have more logic in application layer. But in this case, what will for example, what you can do can you can have functions that you can just, test independently without entire words.

    Miłosz [01:51:19]: Yeah. And in this case, in memory fakes work well. And this this is where having small interfaces is super important.

    Robert [01:51:27]: Yeah, and what’s important there is ensuring that you are mocking this IO stuff that I mentioned a bit earlier. So don’t mock your, I don’t know, logic, let’s say, because it your test will be just mocking some subset of logic and they will not give you a lot. So, you know, mock your database, mock your mock your external dependencies, don’t mock your logic.

    Miłosz [01:51:52]: And we are big fans of writing the fakes, manually. I know many people use mocking libraries but we find them usually not that helpful.

    Robert [01:52:04]: At least in Go. I think it may be, let’s say, problem of Go because of its compiled language and often those libraries are using a lot of reflection. For example, I remember that in PHP there were some nice libraries for testing but in PHP it’s a bit easier due to not being compiled language but, well, upsides and downsides.

    Miłosz [01:52:29]: And sometimes it also creates, like, brittle tests. If you you start testing the function calls, for example, then you often need to change them if you change anything in the code.

    Robert [01:52:46]: And, yeah, the problem with mocking libraries so it’s another thing in the bucket of things opening the gate of hell so it’s making easier to mock too much. In other words, it should be painful to mock things because you can mock too much.

    Miłosz [01:53:03]: Yeah. That’s what Todd in the comments mentioned before that if you need a mocking library, you are mocking too much.

    Robert [01:53:09]: Exactly.

    Miłosz [01:53:10]: Yeah. That’s kind of the idea. I think that Yeah. And Firmino had some experiences with architect and his Gomock lib. I don’t remember which one gomock is. Is it the one using reflection or the one using generation?

    Robert [01:53:29]: I guess so. I already forgot it intentionally.

    Miłosz [01:53:36]: Yeah. I just found another one from Todd. The first step I use when trying to introduce layers to people who don’t use them is to explain that the application shouldn’t be tightly coupled to the API. So, yeah, it’s a great approach, and also shouldn’t be coupled to the adapters, the database, for example. I guess the hard part of explaining it is explaining someone why it is good to decouple them.

    Robert [01:54:05]: And if you don’t see any reason again maybe you don’t need the architecture because if you have a CRUD application and you are mapping your CRUD structure before your at least at least four layers, in worst case six layers or how many, it’s just a waste of time.

    Miłosz [01:54:28]: Yeah. And sometimes it’s also not that trivial to explain the benefits because you can use the typical reasons like if you ever want to change the database it will be easy. But it’s easy to counter this with. We won’t. Which is also true.

    Robert [01:54:54]: Don’t use this argument.

    Miłosz [01:54:57]: Yeah, I mean, it’s it’s hard to have a discussion that that it doesn’t start to be about this dogmatic approach. Our code needs to be clean. Our code needs to be simple. So watch out for that. Yeah, but this is definitely a nice idea.

    Robert [01:55:17]: It’s also probably worth mentioning that, you know, you won’t be able to always work in the teams following this approach, which is fine, but also don’t be a rebel that is just using clear architecture in your small project. I mean, if you’re working the team that, okay, you’re not following this, don’t be the rebel. I mean, sometimes disagree and commit, it’s sad, but well, maybe it’s not sad. It’s something that you need to use in you should work in a team, not alone.

    Miłosz [01:55:48]: It, I guess, depends on how well the project is doing. You know, if I know it’s hard to, you know, disagree and commit if you see all the issues that following some pattern could solve. That’s that’s the hard part, you know.

    Robert [01:56:05]: But you will be not always able to just convince everybody. It’s different.

    Miłosz [01:56:10]: Yeah. Just you need to know why you you want to use some pattern. Right? We discussed this in the first episode that we had this one project where everyone was super happy to work with because it it used, many cool patterns, and we kept talking about it years after it. And the project was shut down because it had no paying users.

    Robert [01:56:40]: Well, at least it was great.

    Miłosz [01:56:42]: So that’s the hard part. You need to be productive and avoid getting into this big ball of mud issue. But sometimes it doesn’t matter that much as well.

    Robert [01:57:00]: Yeah. So at the beginning, we have a couple of comments that somebody is missing working with you. We have also one comment that please come to my team and make team follow architecture and solid. I use elixir, and I don’t know if it’s the language or the community, but, oh my, everything is coupled.

    Miłosz [01:57:21]: I don’t think it’s the language. I think it’s just it is what it is.

    Robert [01:57:27]: I think it’s also something connected. I mean, the mindset and language. I will not mention language names started with r or

    Miłosz [01:57:38]: But Yeah. But, you know, even if in Go, which is supposed to be a simple language and, I don’t know, somehow make it magically better or your applications easier to develop, We know the reality is it’s just as easy to create something coupled in Go than in other languages. Maybe with less magic. That’s the good part.

    Robert [01:58:01]: That’s true.

    Miłosz [01:58:02]: But, for example, you know, the struct tags in Go make it super easy to couple layers and it’s not that easy to see if you don’t know what you’re doing.

    Robert [01:58:12]: But I think it’s something in that, you know, a lot of Go people are very open minded because it’s, you know, fresher language and in general, you you know, if somebody was eager to learn some new language and try something different, it’s at least from my experience, it many cases, it was real open minded person and it was somewhere there. But, yeah, about about the team, you know, if you are not able to change the team, change the team. It’s sometimes like it and it’s just sometimes not possible to change what you’re doing in the team. So, you know, it might be worth, you know, leveling you up in your skill set and trying to find a better place. Unfortunately, there are a lot of great places and hard bad places to work in. It’s also a bit unfortunate that we know that it’s hard to join good teams that are, you know, following some good practices. But from other side, you know, also grass in your neighbor’s garden is always, more greener than yours. But yeah. It you can always find a better team. But for that, you often need to

    Miłosz [01:59:20]: There’s also there’s a risk there that you start thinking that the team using clean architecture is better than yours. Yeah. Who knows? Maybe they over engineer it so much you would hate it even more.

    Robert [01:59:34]: Yes. Yes. But yeah, about the quality again, I recommend checking the episode about how to write bad code qualities. We’re also touching a bit on how to set expectations because well, none of the team is perfect. There are always problems and but, yeah, there are better and worse teams.

    Miłosz [01:59:57]: Okay. Are we out of questions?

    Robert [02:00:01]: I think so.

    Miłosz [02:00:04]: I think we are just on the two hour mark.

    Robert [02:00:08]: Perfect.

    Miłosz [02:00:14]: Cool. So thank you everyone for joining us. If you want to not miss the next episode, you can subscribe to our newsletter on our blog, and we will let you know. You can, of course, subscribe to YouTube, our YouTube channel, but we’re not sure if they will notify you, so our newsletter is the best one, the best place to get notified. And you will also not miss posts, our notifications of our our our posts, so that’s another reason. Yeah. Leave us any comments. Tell us if you liked it and what you can improve. If you are listening to this after the live happened, you can just comment under the video. And if you listen to this on any podcast application, give us five star rating.

    Robert [02:01:17]: Yeah. Unfortunately, we’re ruled by the algorithm so your, thumb up or flight style review can help us a lot and I think this is the best way how you can support us and well, help us to record more episodes.

    Miłosz [02:01:37]: Which, will happen in two weeks.

    Robert [02:01:39]: Yeah. About what we are talking in two weeks? I don’t remember.

    Miłosz [02:01:42]: I think how to learn quickly.

    Robert [02:01:45]: So I think it will be another episode that is nicely connected to what we were talking earlier. And, yeah, if, Nicholas, you were mentioning that you would like to join your team, We are not looking for a job, but what can help is, well, learn more and being able to join better teams. So this is the tactic that we definitely recommend.

    Miłosz [02:02:09]: Or spread some ideas within your your team.

    Robert [02:02:13]: Yep. That’s true. So, yeah, the next episode is about that. Hope you see.

    Miłosz [02:02:19]: Thank you everyone for joining us today. Thank you, Robert.

    Robert [02:02:22]: Thank you, Miłosz. And see you in two weeks. Bye bye.

    Miłosz [02:02:25]: Bye bye.

    Let's stay in touch

    Never miss a new episode: get notified directly, without relying on unpredictable social media algorithms.

    You'll know when we're live, get updates on new episodes, and receive exclusive content.

    Last update:
    • April 2, 2025