Pillole di...
Frameworkless
Mi presento
Christian Nastasi
Lavoro in Facile.it
Ricopro il ruolo di Delivery Manager
Sviluppo cose dal 2000
Suono cose, ne ascolto altre, mi piace la cultura orientale ed il buon vino.
Disclaimer
Questo talk è basato su studi ed esperienze personali raccolte negli anni.
Per questioni di tempo, alcune delle argomentazioni potrebbero essere poco approfondite
Potrebbe contenere tracce di meme
Da qui in poi, sarà scritto in inglese (almost)
Introduction
Introduction
Nowadays, frameworks becomes a necessary "evil".
There's who loves them and who tollerate them.
They speeds up our developing process.
They offers a lot of ready to use functionalities
There often a big and supporting community around them.
They are open-source, so I can personalize them as I like
They give us a lot of power
Yes, that's true, But
They brings also
Architectural choices guided by the framework itself
A lot of pain whenever we want to upgrade the version
The cost of maintaining the entire framework, in case we personalize it
Documentation rarely go deep, it show you the easiest way to use it, not the best way
Programmers hate going out of their confort zone, so they tend to use the screwdriver as a fork
Symfony releases
Laravel RELEASES
Question time
How old is your current framework version?
How old is your project?
How often do you upgraded the framework?
How much it cost to upgrade?
Most of you
The truth is
Never enough time for refactoring
Remove tightly coupled dependencies cost a lot
Upgrading a framework often cost too much
But every day we think about...
Often we choose to keep the current version
No new and shiny features
Security issue
Licenses compliancy issues
To use or not to use (a framework)
That is the question
You can use it but...
Just invert your dependencies
Holliwood Principle
Don't call us, we'll call you
Cool, but how?
Design by contracts
Design by contracts
Created by Bertrand Meyer in the 1980s
Is an aproach to software design that focuses on specifying contracts that define the interactions among components
Design by contracts
Client
Server
Precondition
Pre-condition: This is what the server expects from the client
Post condition
Post-condition: This is what the server promise to do for the client + what happens after
Invariant: Those conditions should be always true inside the server, no matter who the client is
Invariant
Real life Example
Pre-condition:
- You should have enough money
- You should have choosed which pizza take
Post-condition:
- You'll have your pizza
- Some ingredients are consumed
Invariant:
- The pizza will be served hot
- The pizza will be prepared "just in time"
Client: You
Server: Your favourite "pizza dealer"*
* Everybody knows, pizza is a drug
Code EXAMPLE
interface Library {
/**
* Pre-conditions:
* - The book should be in the index
* - There is at least a copy in the library
* - The member exists and its membership is not expired
*
* Post-conditions:
* - The count of the copy decrease by 1
* - The count of the borrowed copy increase by 1
*
* Invariant:
* - The borrowed books + the books in the library = const
*
* @throws BookNotInTheIndex
* @throws MemberNotRegistered
* @throws MembershipExpired
* @throws NoMoreCopyLeft
*/
public function borrowABook(Book $book, Member $member): BorrowedBook;
}
Design by contracts
How to enforce the contracts in PHP?
Libriaries
Unit testing
Language (es. Using class type hinting + value objects)
Comments + annotations
Dependency Inversion Principle
Dependency Inversion Principle
High-level modules should not depend on low-level modules.
Both should depend on abstractions.
Abstractions should not depend on details.
Details should depend on abstractions.
Robert C. Martin
Dependency Inversion Principle
Your code
File Logger
Tightly coupled
Dependency Inversion Principle
Your code
Logger
File Logger
Remote Logger
Null Logger
Tightly coupled
Concrete class
Interface
PSR
PSR
The PHP Framework Interoperability Group, since the 2009, is trying to create standards contracts in order to maximize the reusability of several components.
PSR
Layered Architecture
Different name, same concepts
Hexagonal
Clean (by Uncle Bob)
Onion
...
Different name, same concepts
Main GOALS
Independent of Frameworks
The architecture does not depend on libraries.
Independent of any external agency
In fact your business rules simply don’t know anything at all about the outside world.
Independent of Database
You can swap out MySQL or PostgreSQL, for Mongo, Elastic search, or something else. Your business rules are not bound to the database.
Independent of UI
The UI can change easily, without changing the rest of the system.
Testable
The business rules can be tested without the UI, Database, Web Server, or any other external element.
Dependency Rule
Source code dependencies can only point inwards.
Nothing in an inner circle can know anything at all about something in an outer circle
Domain Driven Design
Domain Driven Design
Is the concept that the structure and language of software code (class names, class methods, class variables) should match the business domain
The technical experts communicate trough a shared language, called
ubiquitous language.
BoundeD Context
Building blocks
Value Object
Self validating
Immutable
Describes values / concepts of your domain
Protect you from the past' yourself
Comparable
Money
Email Address
Entities
Composite by value objects
Identified by an id
With a life cycle
Quote
Customer
Can be mutable
Aggregates
Describes high level concepts of your domain
Composite by one or more entities
Formed by tightly coupled domain concepts
Manage pre/post/invariant conditions internally
Post
Reactions
Content
Comments
Author
Repositories
Treat persistence like a collection of entities / aggregates
It's a persistence abstraction layer
Isolate the source of the persistence from the domain
Use Case / services
Use cases are bounded to a domain context
Where the business logic resides
Services are more generic and could be used in different domain contexts
Follows the single responsability principle
PublishPost
FileUploader
Use Case
Service
Factories
Helps to apply the Inversion of Control principle
Centralize the creation of entities / aggregates
Domain EVENTS
Represent something important that occured in the domain
Immutables
Should named with verbs in the past
Semi pratical example
Normally we have this
But also this
First optimization:
Pull out the business logic
But what if...?
Second optimization:
Pull out the query
Another duplication:
Entity instatiation
Third optimization
Factory
Dependency inversion
#1
Dependency inversion
#2
But what is A?
A is part of our domain
Can be described with Domain Objects like:
Value Objects, Entities, Aggregates, Enums
Why not primitives?
Let's think
What's an age? a number
What's a phone number? a string
NO
NO
Integer
> 18
< 99
Only italian numbers
Prefix + 8 o 9 digits
Start with +
Data safety
JSON
(string)
Primitives
(int, float, bool, string)
Domain Objects
(entities, value objects, aggregates)
Application + Domain
(Safe)
Framework
(Not safe)
Infrastracture
(Unknown)
Decoding | Serialization
Wrapping up
Http Request
Controller
CLI Command
Command Bus
Command
Handler
Infrastructure
Framework
Application
DB
Repository
Implementation
Adapter
Implementation
Use Case
Repository
Interface
Adapter
Interface
Domain
CoNCLUSIONS
Cons
Frameworkless it's not easy to master
Require a lot of discipline
It doesn't fit for every scenario (p.e. Prototypes)
High initial cost
Pros
Keep your technical dept low
Speedup your development process in the mid term
Your domain data are solid and coherent
Focused on business
Easy to maintain, easy to evolve
Frameworkless Movement
https://www.frameworklessmovement.org/
Frameworkless Movement
https://www.frameworklessmovement.org/
Q & A
We Are Hiring
MAIL:
christian.nastasi@gmail.com
LINKEDIN: https://www.linkedin.com/in/cnastasi/
https://github.com/cnastasi/ddd
Let me know if interested
SLACK:
@cnastasi
https://github.com/cnastasi/serializer
https://github.com/cnastasi/ddd
https://github.com/cnastasi/json-api
Rate my repos
Frameworkless
By Nastasi Christian
Frameworkless
- 148