We discuss application architecture patterns, anti-patterns and try to position django in this canvas. We step back to see how software design evolved since the advent of the web to better understand where do we stand now.
18. Transaction Script
Modeled as procedures
+ Easiest to understand.
+ Obvious transaction boundaries.
- Difficult to de-duplicate.
19. Table Module
Modeled as objects and Record Sets
+ No DB vs. OO impedance mismatch.
- Model is database-centric.
- Objects, but not really OO.
20. Domain Model
Modeled after the business you work with.
+ Real OOP, with all the OO advantages.
- Hardest to comprehend and switch to.
- Code overhead for simple logic.
21. Domain Model
Modeled after the business you work with.
+ Real OOP, with all the OO advantages.
- Hardest to comprehend and switch to.
- Code overhead for simple logic.
27. Anemic Domain Model
- Objects have state, but no behavior
- The Business is somewhere else
Leads to:
- Upside down Transaction Script
- God objects
28. Anemic Domain Model
- Objects have state, but no behavior
- The Business is somewhere else
Leads to:
- Upside down Transaction Script
- God objects
31. Table Driven Domain Model
- The data model is the domain model
- All objects backed up by a table
Leads to:
- High viscosity
- Complex, slow, fragile tests
- CRUD obsession
32. Table Driven Domain Model
- The data model is the domain model
- All objects backed up by a table
Leads to:
- High viscosity
- Complex, slow, fragile tests
- CRUD obsession
37. Connected Domain Model
In a connected system, elements are highly available to each other.
Adding the first feature to a connected system is cheap …
… the cost of all those connections is that subsequent features
are very likely to interact with previous features, driving up the the cost …
In a modular design, connections are deliberately kept to a minimum.
The cost of the first feature is likely to be higher …
Features are less likely to interact in a modular system, though,
leading to a steady stream of features at relatively constant cost.
- Kent Beck
Confession: The title is a bit of trick.
We are going to speak about application architecture.
2013 Norwegian Developers Conference - (and Javier Acero excellent talk in Madrid)
How the web changed the way we write software
In the first “WEB” decade, we forgot a lot about architecture. Smart people retire.
The web is ONE transmission channel, is how you deliver, it's a detail. That's all.
If PostNL changes to UPS - your business keeps running.
Frameworks are tools, they can't be in the center of the architecture.
Architecture is more about DEFERRING decisions than to decide.
Frameworks should too, be a detail.
So Django CAN'T be the center of your application.
Most importantly, architecture-wise: The way we write applications in Django is -NOT- a generally correct way to write an application
WTF does this mean?
What do you mean by application architecture then?
Let's think through this!
I work at the cloakroom as a backend developer, we use python (and even some django)
The classic 3 layers.
Deliberately, not going to try to name all three now
Producing HTML
JSON, An HTTP API, REST
Command Line
Desktop or Mobile UI widgets
Databases and Message Queues
Sending an email
The file system
Validation, Calculation
Calls to external systems (or preferably to abstractions)
IE: Calculate taxes, add invoice lines, etc.
This is the Business logic.
What is it more important?
that a form looks nice, it's usability?
that the persistence is really fast?
or... that taxes to be calculated correctly?
NO WE DON’T!
The Busines Logic layer is more difficult to reuse between different problem domains. It is specific.
Layer 3, ...we generally do not write DB drivers, or SMTP clients, etc.
.
Do these layers change at the same pace?
1: Technology changes, a decade ago no JS on the front.
3: We now have NoSQL stores, many of them.
2: BL: Domain rules change slowly, length of a credit-card or the age of a person.
What is Business Logic anyway?
This influential book from 2003
You wanna read it if you haven’t
Mentions the patterns we are going to discuss
Modeled as procedures (and of course sub-routines),
Easy to understand
Obvious transaction boundaries.
Even extracting subroutines, is difficult to de-duplicate. (in turn more nasty consequences)
Perhaps more exotic now.
One instance for each type object, only one, operates over database rows
NO oo-db impedance mismatch
No polymorphism, no dynamic linking, nada.
Modeling around the database structure
Specifically based in the domain of the business you are working with (Vaughn Vernon IDDD)
Business Logic modeled as object behavior, no DB, no transaction scripts.
Business as object graphs and object clusters. The OOP way of modeling.
...
Real OOP, with all the bells and whistles. + Heuristics like SOLID
Hardest to comprehend. Using a domain model is the essence of the paradigm shift to OOP.
Code overhead for simple BL.
RELATIONAL Data sources get more complex
.
this is in
PATTERNS - ENTERPRISE - APPLICATION - ARCHITECTURE
Complexity bigger than 7.42
Impossible to calculate
Difficult to predict
So... What is django pattern?? HOW MANY - Tx Script, Table Mod, Domain Model
I'd say. Probably a -some sort of- domain model
So assuming that, let's take a look at some ANTIPATTERNS
This is a CLASSIC in many Django apps I’ve seen.
Objects have state but no behavior (and Getters+Setters are not behavior) They are just data structures. This is not OOP.
Business Logic and thus behavior is somewhere ELSE (controllers,"service" layer, “managers”, forms)
Some say call this the "J2EE smell" - NOT TRUE
This is like Transaction Script, old school CGI
Solve it by a "Push it down" refactor, not a design pattern (though it's better)
Not really a Domain model. just a twisted Transaction Script
God objects (User + The most application centric object; Product)
God objects can be solved with mixins
PYTHON has it.
Mixings are inheritance.
Inheritance is the strongest form of coupling, you are just spreading the code.
You are only making things worse
Prefer composition.
Viscosity due to tight coupling, persistence and logic coupled together, you can’t change ANY
Complex tests need database to run or complex sorcery. Test behavior, not implementation.
CRUD obsession >>>>
Difficult to avoid in Django:
The domain model is basically the data model
All objects backed up by a table.
Databases are part of the 3rd Layer, DETAILS
they do not belong to the DM.
They have design requirements
Leads to ...
You may think that it means…
BUT. Actually stands for
C, R, U, D are consequences of the use cases,
not THE use cases.
CRUD APPs are LEGACY
We are not modeling the paper-based office in software anymore
There is an APP for that!
Lastly
This antipattern is Unavoidable in Django (and any other ActiveRecord based framework)
Global state, models are omnipresent (accessible even from the templates through lazy loading).
No real separation, the three layers are connected and tightly coupled.
They can't easily change at different pace.
Active Record is the culprit. AGAIN
The “Django way” is FAST, but consider it is a HUGE trade-off, specially for complex apps.
Are you prepared to pay the price?
BUT it works for me! - Maybe, but at least keep all these things in mind.
So Django vs. OOP is ….
NOT THE DEBATE
Frameworks are tools, and they have a place.
Django is probably good enough if CRUD is good enough for your application - (which rarely is).
Where I say Django, you can say Rails, Spring, and other paternalistic, Active Record based frameworks.