 Jeznjak je tudi očetan. Tako je to da je tajga tezdu, kako se na Kainojne je začala z kratiljnjom zjebitih všeč, tudi očetanje in tudi očetanj. Vsih je, da sem tukaj tukaj, početnja moji vziv vse izgov na cistem desine, ne zanoj vse, kako vsečem, ... in tudi, vsečen, tudi. To mi je, če ne možeš vzlušati, pa je vzlušati vzlušati na bloga. Vzlušajte, da vzlušajte na bloga. Vzlušajte, da vzlušajte na Python. TDD, kriptografi in infrastruktur. To je vzlušajte vzlušajte vzlušajte. Vzlušajte, da vzlušajte na kriptografi in infrastruktur. To je kriptografi in stivno na bož naminga na boža. Tad me je moratilo, da je bilo arhitektu, vzlošajte, da je to? Ko je to? Vzlušajte, da je bilo boastiprosniko, razsig se na vzlušav, ki je tez na boža. Tako razstavojove tvojeh milijs. Vitruvius, ki je romansk, arhitek, in inženir, izgleda, že všeč je o Firmitas, Utilitas in Venustas, kaj je v moderni ingričnih vsečen, je djurabilitva, utilitva in vsečen. Vitruvius izgleda, že všeč je o vsečenih vsečenih, te govorila, kaj je vsečen, bo vsečen. And for me this was very interesting, because how many times do you think about your code as something that has to be useful, beautiful and durable. Useful, yes. Nobody wants to write something that is useless. But what about durable? Zvukam framor nam je kredil jen da je na svojo grozo za dnev. So nekaj scifi, kaj je bilo stavil. I nekaj lepši. To je bilo všeč je zelo način. Pa vzpomeni, da vse zato mu prip upbeatj vse vzlučili in vse več. Taj drugi pogledov ne bilo včesk, in taj je občasno, da inginira, ovrčenak, je inginersk, in ingin, kaj smo tudi pravati, kaj je vse se način več, in ingin je inginuacija, kar je lati, nič nekaj prav, nič nekaj prav, nič nekaj prav, nič nekaj prav. Zelo, sem vzal, da sem počekal, da je zelo na kvalitku, nekaj in ljudi kvalitku, pa je bilo to vzal, da je zelo na vse definitivi kriče. Eno je vsega in svojnozaj na zelo na naštavljenje in vsega zelo. Vsega in vsega je zelo način o komputeri, a je svega vsega in vsega komputeri, zelo vsega, zelo način o komputeri, ta je vsega zelo način, I wanted to come up with something a bit more compact. So I tried to merge them into these, which is the art and science, in which the components of a computer system are organized and integrated. I want to stress art and science. How many times do you think about what you do daily as art and science? As science, yes, data science, computer science, the mechanical part, right? What about art? When do you look at your code and think this is art? Why is it not data art? Why is it not computer art? Not as in, you know, painting something with a computer. Our code is beautiful, or it can be. And the other two interesting words here are organized and integrated, because a system architecture, when it comes to computer science, is all about where components of the system are, and how data flows between them. So this is the integration part. So now that I defined architecture, the following question is, do we need it? So do we need things, our code, to be useful, durable, and beautiful? And this is up to you. I'm positive about this, otherwise I wouldn't be here. But I want to give you a couple of examples. One comes from the traditional architecture, and it's the bridge that is in front of this building, somewhere back at the bridge. It's interesting, I was looking at it these days, and I thought, does this bridge have to be shaped like an harp? If the requirement of the bridge is just to take cars from one side to the other, it doesn't have, you just need a plain bridge, something that I could design, because I don't know anything about bridge design. But if the requirement is to make your journey better, while being shaped like a harp in Dublin, it's a nice thing to have. So this is food for thought, maybe. What is the requirement of your code? What is it that you are creating? When you create a library, do you just create some machinery, or do you create something to make the journey better? The other example I have, it's about something lasting a long time. The unit system, the operating system was designed in 1971, so 50 years ago, and it was well thought. Not everything in a unit system is perfect, sometimes it's far from it, but it was well thought. So well designed that I am running a Linux machine, and Linux is a clone of Unix, and many of you use macOS, which is a derivative of Unix. 50 years. So, again, how many times do you look at your code, the code that you write, and you think, in 50 years people will still use this code, or at least these ideas? Anyway, I'm not the only one who thinks that system design is an interesting thing. There are much smarter people than me, who wrote a lot of books, there are vast literature about this. I selected five books that I read, which I believe are interesting about the topic. Some of these are door stoppers, pretty thick, so if you are not up for the challenge, I recommend retrieving at least the two in orange, so design patterns and enterprise integration patterns. At least read the introduction. And I'm not joking, the introduction to these two books, the two introductions are short, but they give you a narrative of the challenges and some of the solutions that you might have when you design a system. And I was really flabbergasted when I read the introduction to design patterns, because it was like, hey, I face these issues every day. I want to mention another thing about enterprise integration patterns. This is a book about messaging, message-based systems, more about distributed systems, if you want. But it's interesting that message-based systems, microservices, for example, the software design and languages, they are all in the same league. They share a common trait, which is messages. Object-oriented programming, and you can quote me on this, is supposed to be about objects that exchange messages. So every time you call a method on an object, you are sending a message to something. So it is a distributed system. And if you think about that, when you code in Python, if you think about messages, this might not change the code itself, because you are still calling methods, but it will definitely change the way you think about your code. It's a bunch of objects, it's a distributed system, and I'm exchanging messages. Anyway, this might be for another talk, another time. Now that I defined architecture, I decided for you that we need it. Let me define clean, because this is about the clean architecture. I found it easy to define the opposite of clean, the picture in the background. If you look at that system, you can definitely say this is not clean. It's not tidy. Good luck maintaining something like that. They said pull the green cable. Good luck. This is an extreme example, probably, but sometimes our code looks like that. You change something, and suddenly everything crashes, and nothing works anymore. Instead, in a clean system, or in a tidy system, if you want, you have these characteristics. For each component, you know the three w's. You know where it is. It's easy to find the component in the system. It's isolated. You know what it is from the name, for example. And you know why it is in the system. You can say why it's been included. In the pictures in the background, there are two hardware systems, and they are tidy. It's easy to trace where a cable goes. Some are color-coded, so it's easy to understand why they are there, what they are doing. Ok, now that I define the clean architecture in terms of the words, let's go for the concept F1 example. So what is the clean architecture? It is a concept that was introduced by Robert Martin some years ago. Robert Martin is a system designer, developer, and I'm not here to advertise Robert Martin's work, mostly because Robert Martin is very good at advertising himself, you know, so. But I'm going to use the same name. It's important for me to stress that the concepts that Robert Martin dubbed the clean architecture predate his work, so they have been around for a long while. So let's call it the clean architecture, but it's a set of concepts that predate what Robert Martin did. What is it? It's a layered approach, so it's a way to structure your software project, your code. It's layered and it's circular. So in the traditional, say, definition, we have four layers. You can have more of them, but these are the traditional ones. Entities, use cases, gateways, and external systems. What happens is that when you create something in a clean architecture, this something, this component, will belong to one of these layers. And there are rules. There is actually one simple rule, one rule at least, which is that your component can see, I'm going to define what C is, can see only what has been defined in an inner layer. So if you create something in the use cases layer or ring, you can see everything that has been defined in the same layer, use cases, and everything that has been defined in entities. You are not allowed to use, to access anything that has been defined outside. And that has to do with dependencies. The problem of unclean systems, remember the cables before, is dependencies between components. When you have a component that depends on other components and these other components depends on other components, and you can't trace these dependencies, and sometimes they are circular dependencies. In a clean architecture there are no circular dependencies. The golden rule, I'm going to introduce it now and then show you an example that clarifies it, is that you talk inward in the use cases. What does it mean? Simple structures are data types that have been defined inside. So, for example, again, something in use cases can use data types, and I mean data types in Python, for example, you can instantiate them, if they have been defined in use cases and if they have been defined in entities. If something has been defined in systems, you don't see it. You can't instantiate it. Interfaces. Interfaces have to do, so they are related to dependency injection, which is something I will introduce later. What is an interface? Going back to what I said about objects and sending messages, when you send a message to something you expect it to be able to receive that message. In Python, we don't have an explicit way to state interfaces, to create them. Even though we have now protocols, we have abstract-based classes, there are many ways to work with interfaces, and we can discuss about this another time, because there is not enough time today. Anyway, I'm coming back to this slide later after the example. The example today is simple. The code I will show is Python. It's valid Python, but I stripped all the error-checking, a lot of things that are not useful. Obviously, the real code is a bit more complicated. My use case is to retrieve a list of items. It's very simple. When do we want to retrieve a list of items? You have a social network and you want to retrieve a list of posts. Or you are Amazon, you want to show a list of proper items that you are selling. In this example my use case is just a simple function. It exists in the use cases layer and for the time being it doesn't do anything. Then I define some entities. Entities are models. They represent real items that are in my business logic. So in this case, for example, something with a code and a price. Just a simple class that captures data and encapsulates data. The entities live in the entities layer and they are known to all other components. It's 2022 so we probably want to build a web application, but this is not required. It's just an example. The web application requires a web framework because I don't want to implement the logic to deal with HTTP requests and all these things. There are smart people who did it for me. In this case I'm using Flask, but I can use any other web framework. The web framework exists in the external systems. I want to say a couple of things about this. I mentioned business logic before. The business logic is what you market. It's the core of your application. The web framework is not, generally speaking, part of your business logic. You are not marketing Django. You are not marketing Flask. You are marketing a social network. You are marketing items, delivery, whatever. It's reasonable for the web framework to be in a very external layer where we use it, but we don't manipulate it. The core, the most important thing in a clean architecture, I would say in any architecture is the business logic. This is what 99% of your time should go. Every time you spend configuring external systems, it's not wasted, but it's not given to the core of your business. Anyway, this is the web application, the web framework. Now, what is the task of the web framework? The web framework is there because it has to translate HTTP requests into calls. This is all a web framework that has to do. Granted, it's not an easy task. There are many things involved, but this is what the web framework should do. Get an HTTP request and transform it into a call, for example, for a Python function. In this case, this is exactly what I'm doing. I'm calling the use case, which is a function. Here you see that the web framework communicates with the use case simple structures. What does it mean? In this case, I'm using request args for the sake of simplicity. It's just a dictionary. It's a simple structure because it has been defined in the language. It might be an entity or it might be something that the language defines. All these things exist in Python. Whatever is defined in Python as a core language is available. The use case is a simple structure. Something that the use case can understand. For example, I shouldn't send anything that is defined in the web framework. Some structure that has been defined there. A type that Flask uses to manage an HTTP request. Because the use case doesn't do anything. Doesn't know anything about HTTP requests and it shouldn't know anything. Then we have to retrieve items and data. Data is stored usually in a repository. We are used to think about the repository as a database, which is what I have in the example here. But I want to stress that a repository is much more than a database. For starters, it doesn't have to be a relational database. It might be no SQL. MongoDB, for example. Or it might be for example, a web API. It's a source of data. You call the API, you get data. It's exactly what you do with a database. It might be a bunch of text files, which is a rudimentary database. It might be a hardware sensor. That is a source of data. It's a repository. Let's think about it as a database. I'm going to say database, probably a lot of times. But the repository is the right word here. And the database, the repository, exists in the external systems layer. Because again, it's something that is not part of my core business. It's not my business logic. In system design we usually call the web framework, the database, everything that is outside as a detail. We call it a detail. And many times it surprises people that what detail, I mean configuring Postgres and all these things, it's complicated. It's not secondary. It's not just so simple. A detail means that it's not part of the business logic. This is not what I'm marketing. If my product works with Postgres or works with MongoDB, you are not concerned. You as a client are not concerned. Your problem is to receive a service. So this is why it is a detail. While the specific algorithm I use for my recommendation system, for example, is the core business, is what you like of my product. OK, so this is the difference between core business logic and a detail. So the database is a detail, even though it might be complicated. However, it exists in the external systems. So as I said before, the use case is not allowed to communicate directly with the database. In Python terms the use case is not allowed to instantiate anything that is tightly coupled with the database that is connected with the database directly. Because if I had code in my use case something which is, I don't know, Postgres, a library to interact with Postgres or to interact with MongoDB, I am coupling my use case with the implementation of the database. And this is not good because at that point I have my core business, my core business logic coupled with a detail which might change, might not be the same thing in time. So I create an interface. This is, in this case, we are talking about Python, it's an object that provides a facade. So this is a set of methods that are common to databases. So the web framework instantiates the database interface or the repository interface. The web framework can do it because it's in an outer layer. So the web framework sees can see what's in the gateways. And passes to the use case. This is called dependency injection. If you are not familiar with the concept, I have a slide for that later. But look at it, the use case, the code of my use case doesn't have Postgres repo hardcoded in it. I'm receiving an object that provides methods that might be an object of Postgres repo, MongoDB repo type, whatever. The important thing is the interface or the set of methods that thing provides. Cool, now internally I'm in the use case now and I have finally my business logic. This is where my brain comes into play. I have to write something that implements the recommendation system, whatever filtering you want. Eventually, sooner or later I have to use the database interface to retrieve the data. In this case, I'm calling repo list. Passing the parameters that I received from the HTTP request or from outside I should say where they come from is not important. The business logic might be, for example, to prepare the parameters to add some filtering or to do something else. Anyway, back to the database interface I'm calling repo list here, repo list. I'm in the database interface now and the database interface is tightly coupled with the database. That is Postgres repo so it has been designed to work with Postgres. It's in the name. The two communicate with a specific language. In this case I'm using SQL alchemy. It's an object of additional data but eventually I'm in a mindset of querying a relational database. This is what I'm doing here. I'm committed to relational databases at this point and this is what I'm doing. The two things are tightly coupled. What the database interface does is to, as I said, query the database and then it transforms the output and the database just sends me values. It's SQL. Standard types known to SQL databases. The database interface has the task to convert those values into entities because at this point everybody can see entities as a layer. It's a very inner layer. The database interface can say these SQL values become items as in items that I defined. And these items send back to the use case as a result of the repo list. At this point I can add more business logic. Just to say that obviously if you want to, if you have to call your repository you can do it at any time. Your business logic is around that call. It's where you augment results, ok, with your algorithm, with your cleverness, your product. At this point the use case has the result and it can send it back to the web framework or to whatever called it. And the web framework so this is again, sorry, entities. The web framework can knows about entities. So this can still be an entity, a model that I created. The web framework again has one task that of converting the entities, which are specific models of my business into something that is understandable outside. For example, JSON. This is the task of the web framework. My use case doesn't know anything about JSON, it doesn't care because the use case is ok with entities. It's part of my business. This is the journey of the data in a clean system at least in this example in a clean architecture. I want to go back quickly to the initial slide about the golden rule. Talk in words through simple structures and outwards through interfaces. Have a look at this code. These are two different possible implementations of a use case. The second one is the one I used. The first one is the incorrect one, if you want. Why is it incorrect? It works. Ok, first of all, so it's not incorrect from that point of view. But these couples my code, the code of my use case with the Postgres repo. It means that I can't use anything else. If I want to use something else I have to touch the use case. But the use case is your business logic. And it shouldn't be touched because you change something which is a detail where you store data. Ok? The second one instead, and this is a good example I hope of dependency injection is when you create something outside and then you pass an instance of it. The instance has been instantiated outside, so part of the code that is coupled with the type the Postgres repo is outside in this case is the web framework. Your use case just receives an instance something that can accept a certain set of messages. Does it make sense? I hope so. This is what happens in a clean architecture, simple structures inside interfaces outside. Cool. I want to tell you about the advantages of the clean architecture. Why should I go through all this pain? And there are two specific things I want to mention. The first one, probably the most important one for me is testability. A clean architecture, a software designed with a clean architecture can be tested very well. What do I mean by that? Look at the use case. I can easily isolate the use case from the web framework and from the database interface. It's just an object that receives a repo and some parameters and returns some results. So what I can do is to pass a dictionary of parameters a mock database interface so something that pretends to be the database interface that is connected with any database. It's just a mock. It returns a fixed set of data. And check that my business logic works, given that input gives some output. This allows me to test my business logic in isolation. I don't need the database to test my business logic. I don't need the web framework because these are details and my business logic is not about details. At the same time I can test the details because, yeah, details but they are part of the implementation. So I have to test that my web framework works and the web framework can be detached from the use case because the web framework, the only task is not a simple task again but the only task of the web framework is to accept HTTP requests convert them into calls. Get the result of this call and convert it back to an HTTP response. As I said, it's not simple. I have to test that this works and I can do it in isolation. And last I have to test, I can test my repository interface. This requires the database because this is an integration test. I'm testing that my the facade of the database works so I need the database running. This might be a slow test that you might run just sometimes. Again I want to stress this I see it too many times when it comes to testing in particular with web frameworks we end up testing the database. So we store a model then we retrieve the model and we say, yeah, it works. Thank you very much. This means that Django or whatever framework you are using that Postgres works but this is not what you are supposed to test. These are provided by third party. This is not part of your code business. The second advantage is about customization I would say. Look at this. In this case I have two different use cases. One is to list items and one is to list users. A phone for some reason for example for performances reasons I store the users in a MongoDB which is not relational. So I can't use it with a SQL alchemy for example because it's not SQL. But this is not a problem in a clean architecture because my use case is customized. It just has to receive a different object that is instantiated by the web framework. Pay attention that this might happen inside the same use case. So those use cases those two use cases might be the same. You might have some logic inside might be part of your business logic that says well in this case I go and fetch things from repo A in this case I go and fetch things from repo B performances for example. But these repos are something that you get from outside as you see here I'm instantiated them in the web framework not in the use case. And the other sign of this is that the web framework is just one of the possible front ends. And with front end now I don't mean reactors, similar things I mean the way you present your results to the client it might be a command line interface it might be a web protocol or something else. Because I just need to call the use case and translate the output of the use case into something that is meaningful for my front end. HTTP request for a web framework something else for example text for a command line interface. Ok, at this point I want to draw a comparison with an architecture that we or at least many of you probably know which is the Django architecture. Django is amazing web framework well known in the python community it has a different architecture it's not the clean architecture this doesn't mean it's unclean maybe well yes it's unclean given the definition it's unclean. What I mean is I don't want to say it's bad I'm coming back to this later I just want to draw the comparison for now. Well Django has models these are similar to entities superficially speaking they just represent part of my business I have items, I have books films, something that I'm marketing. I have business logic obviously otherwise why should you use Django you have something to market something to sell. Business logic in Django is usually implemented in views but it can be implemented in functions that are called in views so this is similar if you want to what I did before with the clean architecture. Ok, the first big difference Django has an ORM an object relational mapper which is if you want a gateway it's an interface because if you use MySQL if you use Postgres your views don't change so you are using an interface you are using something that masks the details of the underlying database however, the object relational mapper the name says it all it is an interface to relational databases and it's not easy to use Django with no relational database or with something else a web API because of the ORM is customized for relational databases and this is different in a clean architecture because the gateways is a more generic definition of interface last, two components the database which is an external system which is also tightly connected with models because models in Django can be saved and retrieved from the database natively so the models are connected with the database they are aware of the database what is the drawback of this that when you test your Django application you need the database it is possible to test it without the database but you are sort of fighting against the framework you are doing something that the framework doesn't want you to do so again it might not be bad but it's different so there is a big connection between two layers one is the inner layer and one is outside and the same happens for the web framework itself as in the part of the framework that deals with HTTP request and responses because that is connected with the business logic as I said before you usually implement your business logic in views and views are specific things provided by the web framework they are connected with URLs so far this is the Django architecture just to show you that there are different approaches to the things and as I said this might be a good approach it's not bad, it's just different but as you assume I convinced you in 40 minutes you are like yes the clean architecture is the way to go so I want to go back home and convert everything to the clean architecture well, don't do it so if you want to do it do it the right way so I always recommend to remember what happens to what happened to Netscape when they decided to rewrite the whole thing from scratch just everything, have you heard of Netscape lately? no it resurrected at a certain point but you know it's a sad destiny that of Netscape and it's for a bad choice so don't do the same choice migrations happen one step at a time so my recommendation if you want to try these concepts is to isolate part of your system something tiny in your system and reimplement it maybe with a clean architecture something that doesn't affect the rest of the architecture remember that when it comes to web applications you have load balancers they are your best friends you can always root requests to another system and you can go back quickly if it doesn't work final slides is this the definitive architecture so done perfect architecture we don't have to do anything else go and implement everything with clean architecture thank you very much so the answer to this question is in my opinion the answer to any computer science question ever and it is it depends it depends on many things it depends on your requirements for example when it comes to the clean architecture vs something else for example the jungle architecture I tend to show this slide you are the crossroads between these two options Lego vs Playmobil on the right you have something that works out of the box and it's very nice you can play with it, it's amazing I don't play with it nowadays but I remember you want a farm you get a farm it's customizable up to a certain point you can move things around on the other side on the left you can build whatever you want but you are on your own so it depends what are your constraints what do you want to achieve can you mix and match the two yes you can so this is my recommendation to design a system always stop and think look at the requirements don't go for a solution out of the box it might be the right solution but you have to be clear that why it is the right solution really last two slides I wrote a book about these concepts clean architecture in python it's a free book, it's available there the example I showed you today it comes from the book there I implemented it properly with TDD a lot of error checking so the whole book is about that example I implemented it with Postgres and MongoDB just to show that it's possible to use different databases for the Europe items for this week and next week I teamed up with some friends and they gave me the book and other books for free it's a bundle worth $60 so you are free to follow us on twitter and you can check the URL only in pub to get the bundle for free with that I'm done I hope it was useful, thank you thank you very much Leonardo for that very inspiring talk we have a few minutes available for questions so if anybody has a question we have a microphone here just quickly go to that microphone and ask a question I'll be around for the next two hours so feel free to get in touch ok, hello thank you for the really nice presentation and while I try to follow the layered architecture, the one thing that I always struggle this with so if you want to really follow these then it seems like you have a lot of duplication so you have to have the models in the core of the business that your business or your cases are using and then you want to persist also those models into the database or somewhere else you then need to have some kind of definition of how this happens with some bookkeeping data and potentially the duplicated definition of the original data so it seems that there is a lot of duplication that is painful to implement the clean architecture I don't think there will be duplication we might talk about this later there is definitely a lot of message passing so if that is what you mean by duplication yes, the same data is going around a lot which is part of the drawbacks of the clean architecture there are a lot of layers that is my impact performances like you don't have direct access to the database in terms of duplication I'm not really sure what you mean so if you want to expand on that for example, in the example that you show for the jungle you define the model once and then that's also the definition of how the table would look like majority of ORMs work the same way so you have a single source of truth that defines basically the layout of the data in the database as well as the layout of the model that you're working with so if you don't have the application that's really convenient and very simple to work with and define your system so if you don't want to use that then you need to have I definitely see what you mean thank you, now I understand yes, it's true that for example the model I use in entities correct me if I understood the wrong way is duplicated in the database interface because this is what I'm storing there is no way to avoid it because this is a feature as in I am splitting the model the entity if you want as in a business entity and the entity as something that is stored in the database I agree this is more work and there is no way to avoid it because it's considered a good thing again it's part of the it depends on the requirements in your business logic this separation is not needed or it's overkill and you're free to go with a different architecture but the idea if you want the extreme idea is to split these two things because they might exist in the same space but they are not the same thing one thing is the business logic one thing is how the business entity one thing is how I store it thank you very quick final question hi hi Leonardo, thank you you're welcome I really appreciate your emphasis on beauty and art in terms of software with clean architecture I can see the benefits of say durability utility by making architecture clean do I get beauty out of the box or is there something more elusive making something beautiful maybe a bit more elusive beauty beauty is to be defined to be honest when I was working on the book and I came up with the example and I was looking at the projects where components were how they were interacting between them at a certain point my feeling and this is pretty personal was like this is really beautiful it clicks, it works and this is what I meant as in beauty for me it might be subjective definitely doesn't shine doesn't come in colors but the beauty of that system for me is that it's tidy I know where things are I'm confident that when I'm touching something and touching just the little universe around that component and not other things this works for me and this is the beauty in that architecture for me