We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Clean Architectures in Python

00:00

Formal Metadata

Title
Clean Architectures in Python
Title of Series
Number of Parts
112
Author
License
CC Attribution - NonCommercial - ShareAlike 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Architectural considerations are often overlooked by developers or completely delegated to a framework. We should start once again discussing how applications are structured, how components are connected and how to lower coupling between different parts of a system, to avoid creating software that cannot easily be maintained or changed. The ""clean architecture"" model predates Robert Martin, who recently brought it back to the attention of the community, and is a way of structuring applications that leverages layers separation and internal APIs to achieve a very tidy, fully-tested, and loosely coupled system. The talk introduces the main ideas of the architecture, showing how the layers can be implemented in Python, following the content of the book ""Clean Architectures in Python"" edited by Leanpub. The book recently reached 25,000 downloads and many readers found it useful to start learning how to test software and how to structure an application without relying entirely on the framework.
29
GoogolGamma functionEmailSoftware developerUtility softwareBuildingBit rateSoftware engineeringCASE <Informatik>DisintegrationEnterprise architectureSoftwarePublic domainKolmogorov complexityPhysical systemComputer architectureUtility softwareTable (information)View (database)Type theoryArchitectureComputerMechanism designSelf-organizationLatin squareMultiplication signBitWordCloningOperator (mathematics)Derivation (linguistics)INTEGRALEnterprise architectureDataflowComputer scienceMessage passingStress (mechanics)Pattern languageBridging (networking)Position operatorSoftware design patternMereologyComponent-based software engineeringCodeCryptographyBlogBuildingSoftware frameworkSoftware developerSoftwareDifferent (Kate Ryan album)Object (grammar)Formal languageService (economics)InternetworkingArithmetic meanTexture mappingPlanningVirtual machineReal numberInteractive televisionDistributed computingSystem callMachine visionSound effectExecution unitComputer animation
Software engineeringCASE <Informatik>Enterprise architectureDisintegrationGamma functionPublic domainKolmogorov complexitySoftwareBuildingMassCloud computingPhysical systemArchitectureSystem programmingData structureInterface (computing)Business modelCodeComponent-based software engineeringPhysical systemCASE <Informatik>Web 2.0Rule of inferenceBitValidity (statistics)Gateway (telecommunications)Error messageCodeElectronic mailing listComputer architectureSoftwareProper mapData structureInterface (computing)Extreme programmingCharacteristic polynomialWeb applicationMultiplication signException handlingData typeMessage passingGoodness of fitObject (grammar)LogicSoftware frameworkSet (mathematics)Computer hardwareSlide ruleTerm (mathematics)Social classWeightEncapsulation (object-oriented programming)State of matterProjective planeRight angleWater vaporOrbitRepresentation (politics)InjektivitätShape (magazine)1 (number)Condition numberDot productSystems engineeringSoftware developerComputer programTorusCore dumpProcess (computing)Graph coloringHydraulic motorFunctional (mathematics)Computer animationDiagram
System programmingData structureRepository (publishing)Interface (computing)Parameter (computer programming)Electronic mailing listLatent heatDigital filterDatabaseLogicCASE <Informatik>Electronic mailing listPhysical systemCore dumpRepository (publishing)Data structureFormal languageWeb 2.0Different (Kate Ryan album)Interface (computing)Software frameworkCodeSoftware repositoryDirection (geometry)Library (computing)WordRight angleInformation retrievalComputer hardwareType theoryParameter (computer programming)Set (mathematics)Multiplication signObject (grammar)Point (geometry)MereologyImplementationClient (computing)Product (business)Internet service providerMultilaterationInstance (computer science)Gateway (telecommunications)Slide ruleService (economics)AlgorithmSystem callRelational databaseCartesian coordinate systemTranslation (relic)Task (computing)Functional (mathematics)Open sourceTraffic reportingTheory of relativityBus (computing)Data storage deviceFamilyWater vaporData miningSequelFault-tolerant systemRepetitionTelecommunicationTape driveAdditionPosition operatorOptical disc driveSurfaceBasis <Mathematik>Military baseFood energyComputer architectureInjektivität
Latent heatString (computer science)Digital filterElectronic mailing listInterface (computing)Repository (publishing)System programmingCodeData structureBEEPParameter (computer programming)LogicDependent and independent variablesCore dumpSoftware repositorySoftware testingSineDatabaseData dictionaryCellular automatonSuite (music)DisintegrationComputer wormObject (grammar)outputSlide ruleWeb 2.0Task (computing)MereologyDatabaseImplementationPoint (geometry)Interface (computing)Function (mathematics)Software frameworkBusiness modelInstance (computer science)View (database)LogicElectronic mailing listCASE <Informatik>Software repositoryCodeResultantSoftwareMessage passingSet (mathematics)Computer architectureData structureParameter (computer programming)Software testingMultiplication signCore dumpRelational databaseDifferent (Kate Ryan album)Type theoryQuery languageDependent and independent variablesINTEGRALRepository (publishing)Product (business)WebsiteSimilarity (geometry)Arithmetic meanInjektivitätData storage deviceTouch typingBasis <Mathematik>FreewareMilitary baseSubsetPhase transitionSequelPhysical systemSign (mathematics)Traffic reportingHydraulic motorFrequencyCodeRight angleDecision theory
System programmingComputer configurationString (computer science)Arc (geometry)Business modelArchitectureDatabaseHuman migrationFreewareWave packetInterface (computing)Functional (mathematics)Web 2.0DatabaseModal logicSlide ruleRoutingComputer architectureSimilarity (geometry)MultilaterationLogicMereologyPairwise comparisonArithmetic meanGateway (telecommunications)Front and back endsSoftware frameworkFreewareCuboidElectronic mailing listError messageTheory of relativityPoint (geometry)Function (mathematics)Object (grammar)Client (computing)QuicksortConnected spaceCommunications protocolResultantDifferent (Kate Ryan album)Semiconductor memoryImplementationAuditory maskingFiber bundleView (database)CASE <Informatik>Computer scienceHuman migrationLine (geometry)Axiom of choiceDampingLastteilungUniform resource locatorRelational databaseData conversionDependent and independent variablesWeb applicationPhysical systemComponent-based software engineeringGoodness of fitDirection (geometry)Network topologyWritingRight angleComputer configurationHydraulic motorMultiplication signDigital photographySequelBasis <Mathematik>Frame problemTwitterMilitary baseVector potentialDiagram
MereologyTotal S.A.Computer architectureUtility softwareLogicCuboidCASE <Informatik>Multiplication signSoftwareCore dumpMessage passingPosition operatorTable (information)Term (mathematics)DemosceneOpen sourcePlanningDatabaseData storage deviceVarianceBusiness objectAsynchronous Transfer ModeSpacetimeRow (database)AreaHeegaard splittingBusiness modelSingle-precision floating-point formatObject-relational mappingBitComputer virusFlow separationInterface (computing)Physical systemLecture/Conference
Component-based software engineeringPhysical systemProjective planeUniverse (mathematics)Point (geometry)Computer architectureRoundness (object)Confidence intervalGraph coloringTouch typingLecture/Conference
XML
Transcript: English(auto-generated)
Thank you for being here. So the title of my talk today is clean architectures in Python, a tale of durability, utility and beauty. My goal today is, so I'm here because I want to share my views on
system design and give you an example of what I discovered and what I learned and maybe meet people who are interested in system design as well. So this is me, well not a picture of me, but you know, I'm a developer and a blogger.
You are welcome to visit my blog. I usually write about Python, obviously, TDD, object-oriented, cryptography and infrastructure. These are the main things I like to write about. So today it's a talk about the clean architecture and I want to start
with a question, thinking a bit about what architecture is. We mentioned architecture many times, the architecture of a system. What is it? What is the definition? So I found this in a book that has been around for a while, The Architecture. It means about architecture.
It's been written a couple of thousands years ago. Vitruvius, who was a Roman architect and engineer, says that architecture is about firmitas, utilitas, and venustas,
which translated in modern English is durability, utility, and beauty. So Vitruvius says that architecture is about things that are durable, something that has to last, has to be useful, has to be beautiful.
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.
What about durable? We change framework every two years now, right? Every six months, I don't know. So having something that lasts. And beautiful, that's the thing I'm mostly concerned about. It's interesting, let me mention this, that Vitruvius was an engineer and an architect.
And these two professions don't go together that much nowadays. It's interesting to think that engineer, the word comes from engine, but engine comes, when we discuss about engines, we think about something mechanical.
But engine actually comes from ingenuity in Latin. It's from cleverness. So it's less about mechanical things, it's more about solving a problem in a clever way. Anyway, I went on and I checked also on the dictionary, modern English dictionary,
and I found these two interesting definitions of architecture. One is the art and science of designing and making buildings. And the second one is more concerned with computers, and it says the internal organization of computers components, with particularly the reference to the way in which data is transmitted. I like these two definitions.
I wanted to come up with something a bit more compact, so I tried to merge them into this, 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? It's not computer art, not as in, you know, painting something with a computer, but our code is beautiful, or it can be. And the other two interesting words here are organized and integrated because our 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. 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. And one comes from the traditional architecture, and it's
the bridge that is in front of this building, the Samuel Beckett 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, right, something that I could design because I don't know anything about bridge design. But if the requirement is to make your journey better, well, being shaped like a harp in Dublin is a nice thing to have.
So this is food for thought, maybe, you know, like, 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 Unix system, so an operating system, was designed in 71, so 50 years ago, and it was well thought. Not everything in a Unix system is perfect, okay?
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 Mac OS, 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, okay? 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, and I decided for you that we need it,
let me define clean, because this is about a clean architecture. I find 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 is not tidy. Good luck maintaining something like that.
I said, pull the green cable. Yeah, good luck. This is an extreme example, probably, but sometimes our code looks like that. You change something and suddenly everything crashes, 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.
Okay, now that I defined the clean architecture in terms of the words, let's go for the concept and for an 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 engineer, a system designer, a developer. And I'm not here to advertise Robert Martin's work, mostly because Robert Martin is very good at advertising himself. 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 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 with simple structures, outwards through interfaces. 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 external 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. When you call a method on an object, you expect that object to have that method, otherwise you will get an exception.
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 for now.
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? I don't know. You have a social network, and you want to retrieve a list of posts, right? Or you are Amazon, you want to send,
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. In this case, for example, something with a code and a price. Just a simple class that captures data, 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, okay? 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 smarter 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, and 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, right? So 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 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 has to do.
Granted, it's not an easy task, okay? 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 with 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, right? It might be an entity or it might be something that the language defines. All these things exist in Python. So whatever is defined in Python as a core language is available. I'm sending to the use case 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. Okay, then we have to retrieve items and data. Data is stored usually in a repository. We are used to think about a 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 NoSQL, MongoDB, for example. Or it might be something different. For example, a web API. It's a source of data. You code 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. Okay, so let's think about it as a database. I'm going to say database probably a lot of times,
but 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 because they are like, what detail? I mean, configuring Postgres and all these things is 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. Okay, 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 hard 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. In this case we are talking about Python,
it's an object that provides a facade, so 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 can see what's in the gateways. And passes, so it sends the instance of the Postgres repo in this case 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 hard coded 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 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 systems, whatever filtering you want. Eventually, sooner or later, I have to use the database interface to retrieve the data. So 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.
I'm in the database interface now. The database interface is tightly coupled with the database. That is Postgres repo. It has been designed to work with Postgres in the name. The two communicate with a specific language.
In this case, I'm using SQLAlchemy. It's an object-relational mapper, 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. So 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 of the database. The database just sends me values. It's SQL. Just 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. So the database interface can say,
okay, these SQL values that I get become items, as in items that I defined. And these items are sent 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 have to call your repository, you can do it at any time. And your business logic is around that call, is where you augment these results with your algorithm, with your cleverness, your product. At this point, the use case has the results,
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 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 okay 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 inwards 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, first of all, so it's not incorrect from that point of view. But this couples my code, the code of my use case, with the Postgres repo.
It means that I can't use anything else. Or 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 changed something which is a detail, where you store data. 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 the part of the code that is coupled with the type,
the Postgres repo, it's outside. In this case, it's 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, you know, of parameters, a mock database interface, so something that pretends to be the database interface but is not connected with any database.
It's just, you know, 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.
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, it's 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, okay? I'm testing that the facade of the database works, so I need the database running.
This might be a slow test, you know, 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, and we retrieve the model,
and we say, yeah, it works. Thank you very much. This means that Django, or whatever framework you're using, works, that Postgres works, but this is not what you are supposed to test. These are, you know, provided by a third party. It's not part of your core 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. For some reason, for example, for performance reasons,
I store the users in a MongoDB, which is not relational, okay? So I can't use it with a SQLAlchemy, 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, okay, 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, okay? But these repos are something that you get from outside. As you see here, I'm instantiating them in the web framework, not in the use case. And the other side of this is that the web framework
is just one of the possible frontends. And with frontend now, I don't mean React or 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 frontend. HTTP request for a web framework, something else, for example, text for a command line interface. Okay, 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 an 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. Okay, 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, right?
I have items, I have notebooks, films, something that I'm marketing. I have business logic, obviously, otherwise why should you use Django? You have something to market, right? Something to sell. Business logic in Django is usually implemented in views,
but it can be implemented in functions that are called in views, okay? So this is similar, if you want, to what I did before with the clean architecture. Okay, 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, right? 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 a non-relational database, or with something else, okay, 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 modals, because modals in Django can be saved and retrieved from the database natively.
So the modals are connected with the database. They are aware of the database. What is the drawback of this? It is that when you test your Django application, you need the database. It is possible to test it without the database, okay, but you are sort of fighting against the framework.
You're doing something that the framework doesn't want you to do. So again, it might not be bad, but it's different, okay? So there's 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 requests 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, right? Cool.
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. Okay, let's assume I convinced you, okay? 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, you know, to the clean architecture. Well, don't do it. So, oh, if you want to do it, do it the right way. So I always recommend to, you know, remember what happened to Netscape when they decided to rewrite the whole thing from scratch.
They lost everything. Have you heard of Netscape lately? No. You know, well, 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, you know, 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 route requests to another system, okay? And you can go back quickly if it doesn't work. Final slides. Is this the definitive architecture? So done, okay.
It's the 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, okay? It depends on many things. It depends on your requirements, for example. When it comes to the clean architecture versus something else, for example, the Django architecture, I tend to show this slide. You are the crossroads between these two options,
Lego versus 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, you know? I don't play with it nowadays, but I remember. I have fond memories. You want a farm? You get a farm. It's customizable up to a certain point.
You can move things around, okay? 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, okay? So this is my recommendation. Always, whenever you 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 why it is the right solution.
Really, last two slides. I wrote a book about these concepts, Clean Architectures in Python. It's a free book. It's available there. The example I showed you today comes from the book. There, I implemented it properly with TDD all the way. A lot of error checking,
so the whole book is about that example, okay? Just so it's a list of objects. I implemented it with Postgres and MongoDB just to show that it's possible to use different databases. For your Python, so for this week and the next week, I teamed up with some friends, and I'm offering the book
and other books for free. It's a bundle worth of $60, so you are free to follow us on Twitter, and you can check the URL only in public 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 that are 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. Okay. Yes. Hello. Thank you for the really nice presentation. While I try to follow the layered architecture the one thing that I always struggle this with...
So if you want to really follow this, 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 there is a lot of duplication. So do you have a suggestion of how to avoid that or maybe make it less 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 might 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 Django, you define the model once, and then that's also the definition of how the table would look like, and the 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. For the data-heavy 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 and correct me if I understood the wrong way, is duplicated in the database interface because this is what I'm storing. It's true. 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 depends on the requirements. You might think that 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 we 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 the business entity, if you want. 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?
It might be a bit more elusive. You know, 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, okay. Definitely doesn't shine, doesn't come in colors you know, but the beauty of that system for me
is that it's again, it's tidy. I know where things are. I'm confident that when I'm touching something, I'm 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. Thank you very much for the questions.
And let's have another round of applause for Leonardo.