10 ms·
The Clean Architecture (2012)
- adamnemecek 9y agoThese things are always nice in theory but I would really appreciate a small sample app following the architecture.
- BoorishBears 9y agoAndroid devs "(re)discovered" clean architecture around 1-2 years ago so there are plenty of sample apps there you can understand with very little android experience.
- jordanlev 9y agoCan you provide a link to one or two of them you think are good examples?
- yupyup 9y agoAnd as always happen it ends misapplied to mobile apps that only paint on screen the JSON received from the server. Not everything is black or white (no architecture vs clean architecture). You have to think about what you are doing (having fucked up on previous projects help) and don't follow anything you've read blindly. Silver bullets, yadda yadda
- jneal 9y agoMartin is working on a book about Clean Architecture: https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164 https://www.amazon.com/Clean-Architecture-Craftsmans-Softwar... I'm sure the book will have many real world code examples, as is fairly typical of his previous works.
- agentultra 9y agoOne thing I would note is that it's not always necessary to abstract away your database layer. It is if you are developing software for installation into an existing infrastructure at a customer's datacenter. It's not necessary if you're building your own application on your own infrastructure. In my experience I've never seen an enterprise company change databases over night. Uber perhaps being the exception to the rule. If you're choosing the target platform that your software runs on you should exploit that platform for all it's worth to get the best benefit from it. Yet I've seen plenty of software shops that insist on writing/running heaps of code to abstract away the database server on some imagined future point where someone decides they're going to run it on Mongo now instead of MySQL.
- sullenpaladin 9y agoAbstracting the database has another benefit you are neglecting. It is easy to mock the database and test your application use cases if the database layer is abstracted. This is nearly impossible if database access is baked into the app.
- Rickasaurus 9y agoBut do you really need to mock the database when you can just deploy a containerized one for testing?
- mac01021 9y agoWe used a real database for testing. In the short term it was less work than architecting the application in a way that allowed the DB to be mocked. Long term, the result was a 45-minute test suite which spent most of its time setting up records in the DB, and which could not be parallelized except by adding more instances of the real DB (otherwise the tests would interfere with one-another's assertions about the DB state).
- Rickasaurus 9y agobut now with containers you can have a snapshot that's already set up in the right state. A separate build.
- programminggeek 9y agohttp://retromocha.com/obvious/ http://retromocha.com/obvious/ is an implementation of these ideas.
- edelans 9y agoThe title should mention it's a 2012 article.
- luckystarr 9y agoThe thing to follow is that you shouldn't build a tower of babel abstraction stack but a limited number of clearly defined abstractions. It's ok if you go deeper than 4 in some cases but these things should then already be pretty low level. Too deep a stack will lead to code "scavenger hunts" when you want to figure out what something does.
- the_arun 9y agoShouldn't DB be part of Entity - right in the middle? Why it is on the edge of the circle outside gateway?
- UK-AL 9y agoA lot of these architectures assumes DDD. (I'm not sure if clean architecture does) Domain driven design. You model you business problem using plain objects and methods. The domain should do nothing else other than modeling the domain, and solving the business problem you app is designed to solve. It should be persistence ignorant. Then everything else simply has adapters for interfacing with the domain. Including a persistence adapter. This is basically ports & adapters, and a lot of these architectures are basically variations on that.
- the_arun 9y agoThanks. I think I see this reference in the article - http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ http://jeffreypalermo.com/blog/the-onion-architecture-part-1... which explains why DB should be outside. It makes sense in the services and NoSQL world, but i would not put at the edge. Feels like we are doing something wrong & insecure. It could be my mindset issue :)
- UK-AL 9y agoI don't why it would be insecure...
- the_arun 9y agoI mean from block diagram perspective, we are always used to keep data in the center secured by all other layers. But that pattern is changing in the days of AWS & Google Cloud, where data can be anywhere. If data is a service, it doesn't matter where it is located. But if Data is a layer within the application, we need to surround it by protective layers such as app, gateway etc.,
- simplify 9y agoThe article doesn't mention it, but this architecture is good for functional programming as well. If you model those three inner circles as pure functions operating on input and returning results + effects, your app becomes easy to test and easily maintained by a good type system.
- codemac 9y agoHas anyone ever done this in practice before without it mattering: > 4. Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database. MongoDB vs Oracle.. Ok architecture astronaut, you're gonna have a real bad time when you swap those out for each other.
- specialist 9y agoYour business is the database. Models matter. Anyone who wants "database neutrality" (least useful common denominator), vs leveraging the awesomeness of pgsql, mssql, oracle, should just use flat files. Or mysql.
- UK-AL 9y agoYou can leverage whatever database feature you want, just a long as you do it in the database adapter/gateway. I write mine in raw sql normally.
- specialist 9y agoVersus in situ (eg stored procedures)? I currently agree. There was a time when the database engine was the "app server". Before client/server & ODBC. I miss those days. That strategy is overdue for a comeback.
- UK-AL 9y agoMy raw sql can call out to stored procedure if that's the best tool for the job. A database is a perfectly good application core, if you application primary about creating/updating/deleting records. If your application is business workflows, and complicated business logic. Then this is something to be considered.
- pmart123 9y agoGood to see I'm not crazy! I think this can be easier than maintain, and with tools like Datagrip now, seems to make a lot of sense. Coming from the data science side, I observed many talented people spending time on projects like https://github.com/cloudera/ibis https://github.com/cloudera/ibis to abstract SQL into something that I often thought was more verbose, less literal and less portible in reality.
- specialist 9y agoTurgid. Most applications copy a string from here and paste it over there. Input, processing, output. What we used to call data processing. Add some defensive programming for sanity. Validation rules, "schemas", type systems. Favor composition over inheritance, a useful programming language over "dynamic typing" (aka type hostile). Extra credit for logging, monitoring, auditing, alerts, rolling deployments. Life time victory achievement bonus award for setting breakpoints (debuggable) and easy reproduction steps. --- Instafail if you use mappings (eg ORM), observer/listener, factories, singletons.
- computerex 9y ago> Instafail if you use mappings (eg ORM), observer/listener, factories, singletons. Wait, why?
- 0x445442 9y agoWhat I've seen many times with ORM tools is blind interaction with the in-memory object graph abstraction over the data store which results in many un-needed queries. It's like the option of making one DB query which returns a flat result set isn't even on the radar. As far as I can tell Factories have been replaced with DI frameworks or just hand rolled DI. Singletons aren't so bad if you're working with an object oriented language and the singleton is just an instance of a service which holds no state and has methods that operate on a limited number of data types. At that point it's essentially just a namespace for a functional library. Observer/Listeners ... Not sure here unless the commenter is advocating message queues or eventing.
- draw_down 9y ago> The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. You can get pretty far just worrying about this part. I tend not to find these acronym names and the diagrams very helpful in terms of actually creating code. Separating concerns, as we all already know, is crucial, as is being careful about where knowledge is located. But I've found that if you buy in to these architecture patterns, you quickly become confused about which part of the pattern a given class or module or area of responsibility falls under. Like, is my `BazFrobber` a Gateway, or a Presenter, or a Controller... ?
- RubenSandwich 9y agoThis is a very similar idea to Gary Bernhardt's: Functional Core, Functional Core, Imperative Shell: https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell https://www.destroyallsoftware.com/screencasts/catalog/funct.... I prefer Gary's explanation of it because he jumps right into the meat of the problem and shows code that models this architecture. The video doesn't require you to know Ruby to understand what he is saying, just as long as you know some basic testing phrases; Mocking, Stubbing, Etc, you should be able to follow along.
- theptip 9y agoI like Bernhardt's rendition of this concept too. His talk "Boundaries" is my favourite summary: https://www.destroyallsoftware.com/talks/boundaries https://www.destroyallsoftware.com/talks/boundaries Note that the Functional Core architecture makes an additional restriction on top of the Clean/Hexagonal architecture, namely that the core should be functional; the OP doesn't make such prescriptions on how you implement the Entities and business logic (though it doesn't discourage you from doing so either of course).
- RubenSandwich 9y agoYou are right that the above article doesn't specifically mention the core being functional. I merely interpreted that from one of the stated properties of his and the other architectures he showcases: "2. Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element." If that doesn't scream functional, then I don't know what does. :)
- ceronman 9y agoFor the Python programmers, there is also a better explanation of the same concept by Brandon Rhodes: The Clean Architecture in Python. https://www.youtube.com/watch?v=DJtef410XaM https://www.youtube.com/watch?v=DJtef410XaM
- js8 9y agoIt also kinda reminds me these two articles, previously discussed on HN: http://degoes.net/articles/modern-fp http://degoes.net/articles/modern-fp http://degoes.net/articles/modern-fp-part-2 http://degoes.net/articles/modern-fp-part-2
- deleted 9y ago[deleted]
- hasenj 9y agoThis kind of thinking bothers me, but I'm not sure how to put my finger on what exactly it is that bothers me, or how to put it into words. The thing with these abstract architecture principles is they are not always practical if you try to be puristic about enforcing them. I get where these ideals come from. I've seen novice programmers take a stab at writing mildly complicated apps, and the code is a nightmare to read because everything is jumbled up together. This is bad and we can all agree on that. But I've also seen projects where everything is split into a tiny little function or object that don't seem to be doing anything meaningful. Presumably these projects are following the principles of "single responsibility" and "loose coupling", but it's so loose that it's hard to put the pieces together in your mind and nearly impossible to follow the flow of the program. I consider generic rules of the form: "<X> related objects should not be doing <Y> related stuff" to be harmful. (An example of such "bad rules" can be found in the article under the heading "Use Cases") Instead I prefer practical rules that make the code easy to read, understand, and updated, without making it any more complicated that it needs to be. * If a piece of logic can be contained in a function, let it be contained in one function without splitting it across 10 different objects and factories and coordinators. Even if that function is slightly long, there's no need to split it apart just because it's over the arbitrary threshold of say, 25 lines. * Create abstractions around a set of vocabulary that you can use to describe the problem domain and the process of doing things within the application. Make sure to document your vocabulary well and try to keep it as small as possible (but not smaller) A good example of this is git's vocabulary for commits, trees, and blobs. Every operation doesn't need to be a class (or worse, a series of classes and factories). Operations can be functions that operate on the structure's (objects) you've defined. * Keep related files and functions together. If you have a server side module implementing an json API, and an html page designed to display the API, and a javascript module designed to drive the UI on the html file, and a sql file describing the data you're displaying, then let's put all those files together in the same directory, instead of spreading them thin across separate folders app/controllers/api/X/X.py app/templates/X/X.html app/js/views/X/X.js app/css/X/X.css Why not put them all under: app/X/X.py app/X/X.html app/X/X.js app/X/X.css Related material: Object-Oriented Programming is Garbage: 3800 SLOC example https://www.youtube.com/watch?v=V6VP-2aIcSc https://www.youtube.com/watch?v=V6VP-2aIcSc
- 9y ago
- develf 9y agoPrudent to remember that Robert Martin is a consultant and it's lucrative to sell enterprises a story where their domain logic is a billion dollar asset and following his very particular design pattern will enable them to seamlessly evolve this asset with new technology. Here's where the story breaks: - Most app's domain objects and rules are small. You could describe them on a few sheets of notebook paper. The technology implementation (e.g. database or http logic) is a much larger portion of the codebase. - In most teams, especially startups, the domain rapidly evolves. The technology stacks (databases, SQL, etc) are quite stable and have already been heavily abstracted for reuse over the years. Using these proven technologies and excellent existing interfaces is how you go fast. - Technology choice isn't just about code interface. Each comes with its own assumptions of system behavior and theory of operation. Plugging a different implementation into your storage adapter interface is the least piece of work you need to think about unless it's nearly a 1:1 swap like postgres -> mysql. So following a strict clean architecture approach will probably pour concrete around something changing all the time and create friction and extra work in using excellent available technologies. Instead I'd rather follow pragmatic design guidelines: - The concept of each component should be clear - Sensible responsibilities for each component - Abstractions should serve the composability of your existing design; introduce adapter layers if you truly have more than one implementation - Keep it simple; optimize for reading the code end-to-end and easier refactoring These aren't inconsistent with Clean Architecture but probably more productive than adding religious rules.
- dfox 9y agoThe design pattern in question is not that much special in the global sense. It is special in the J2EE/.NET/Enterprise world because it should allow you to automatically generate most of the UI in same way what eg. Flask-Admin does while also taking all the bussiness rules into account. One of the things I'd like to do is implement subset of Apache Isis (which is implementation of essentially this pattern for J2EE) in Python on top of Flask.
- develf 9y agoAutomatically generating a UI from a domain may please a programmer but isn't likely to please a user. That's how you get UIs like the one Salesforce has. That could be the right choice in some situations -- it certainly worked out well for Salesforce and allowing extensibility in their model. However if you want to build an app with consumer usability you'll be putting a lot of unique development effort into your view layer.
- klipt 9y agoThought this was an article about https://en.wikipedia.org/wiki/Clean_(programming_language) https://en.wikipedia.org/wiki/Clean_(programming_language) Disappointing.