SOLID stands for the 5 principles that make the software more understandable, flexible and maintainable.
In this presentation I would like to help you truly understand all these principles so you can create bulled-proof code.
2. Why SOLID?
• Code MUST BE
• Easy to maintain
• Reusable
• Extensible over time
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
3. Code must be AWESOME!
• SOLID principles make it easy
for a programmer to make
that kind of code.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
4. …but before we
begin with SOLID
two important concepts to acknowledge…
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
5. Cohesion
High Cohesion
• Desirable traits of software:
• Robustness
• Reliability
• Reusability
• Understandability
Low Cohesion
• Undesirable traits:
• Being difficult to maintain
• Difficult to test
• Difficult to reuse
• Difficult to understand
The degree to which the elements inside a module belong together.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
6. Coupling
Tight Coupling
• More interdependency
• More Coordination
• More information flow
Loose Coupling
• Less interdependency
• Less coordination
• Less information flow
The degree of interdependence between two program modules.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
7. Now is time to
make it SOLID!
and create quality software
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
8. Single responsibility principle
A class should have one and only one reason to change, that is, a
class should have only one job
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
9. Let's create
an order
• Calculate the total
price
• Get order data from
the database
• Generate the PDF of
the order
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
10. Let's create
an order (again)
• Calculate the total
price
• Get order data from
the database
• Generate the PDF of
the order
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
11. Open-closed Principle
Software entities… should be open for extension but closed for
modification.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
12. Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
Many types of Customers
13. Solving our dilema
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
14. Liskov substitution principle
Objects in a program should be replaceable with instances of
their subtypes without altering the correctness of that program.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
15. Let's create
a square
• Rectangle: 4-sided
shape with parallel
opposite sides are
parallel and of equal
length.
• A square is a special
type of rectangle.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
16. Doing it the right way
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
17. Interface segregation principle
Many client-specific interfaces are better than one general-
purpose interface.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
18. Do all birds fly?
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
19. Yes they do...
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
20. Or they don't?...
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
21. So, not all birds fly
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
22. But they are still birds
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
23. Dependency Inversion principle
One should "depend upon abstractions, [not] concretions”.
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
24. From high to low...
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
25. Let's try again
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
26. Are you SOLID yet?
There is much more way to go...
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
27. Mastery is not achieved by
knowing but by doing.
Tony Robbins
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
28. References
• https://en.wikipedia.org/wiki/Cohesion_(computer_science)
• https://en.wikipedia.org/wiki/Coupling_(computer_programming)
• https://gizmodo.com/the-new-mantra-of-tech-its-good-enough-5229951
• https://www.thinktocode.com/2017/10/10/solid-principles-in-php/
• https://medium.com/@alonsus91/los-principios-de-desarrollo-solid-en-5-
charlas-3b7d7b014c23
• https://www.mathsisfun.com/definitions/rectangle.html
• https://www.hgtv.com/outdoors/gardens/animals-and-wildlife/can-
chickens-fly
Esta obra está bajo una Licencia Creative Commons Atribución-NonComercial-CompartilIgual 4.0 Internacional
Notas del editor
SOLID stands for the 5 principles that makes software more understandable, flexible and maintainable.
In this presentation I would like to help you truly understand all these principles so you can create bulled-proof code.
The most important thing SOLID solves is "OK" code or "Good Enough" code
If you write code that you think is "OK", yes, exactly these two letters O K, then you are doomed.
You must write awesome code. Code that will always be understandable, flexible and maintainable.
Code that’s written with love and mind.
If you don’t know about this principles then you will unintentional write just OK code that becomes so coupled that any bug you fix, might create more bugs. You will get code that gets its own life.
Before we step into SOLID principles I want to share with you two key concepts of today's programming
I won't go deep here, but I just want you to know that there are many kinds of cohesion.
We must always aim for high cohesion.
Cohesion is a measure of the strength of the relationship between the class's methods and its data.
Coupling is usually contrasted with cohesion.
Low coupling often correlates with high cohesion, and vice versa.
Low coupling is often a sign of a well-structured system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability
For example we have been asked to create an order with these functionalities. Let's assume that you created all those functions in one class.
Can you image any change to one of these functions that will affect the other ones?
When you have multiple reason to change a class, you are set for disaster when your code starts to grow.
To solve the mess generated with our last solution, we will create more classes.
- First we have the Order class. This will change whenever we need to change how the order is calculated.
- Then we create a Data Mapper class which will handle getting data from the database for an order.
- Then we split the Order PDF generation in 2 classes.
+ One for all the calculations for creating the PDF and
+ One for the layout of the PDF.
Because the Order PDF can still have 2 reasons to change.
It’s a good idea to split code to create a layout or output from the code that generates or calculates the data to show.
In simple terms: we should always try to add new code instead of changing existing code.
This is also one of the big reasons code starts to become unmanageable.
Let's imagine we have many types of Customers with their own classes. Since we need to handle each Customer's type different, we may have a switch case to do an specific.
Now imagine we did this on 10 places in the code. If we need to add a new type of Customers we must modify the code in 10 parts risking to break it. I think you can start imagine why this is bad…
How could we solve this?
To solve our dilema we must create an interface which we use to extend each of the Customer types.
If we need to add a third type, then we have no reason to change any existing code. We just add new code to add new functionality.
This means we should only extend classes and use interfaces or abstract classes if it makes sense.
If you extend from a class or interface which have functions that you don’t need. Then you have created an incorrectness.
In some cases you need to realize it's not possible to extend a class from another. You need to realize this and find a solution.
Since by definition, a square is a special type of rectangle, it seems correct to extend a square from a rectangle, right?
The "special thing" about a square is that all 4 sides are equal In length. So if we set height or width we need to change both height and width, because otherwise we don’t have a square anymore.
But, what happens if by error you use a rectangle instead of a square and try to calc the area of the shape?
A solution to this example is to have an Abstract class where both are extended from.
Both will have different setters to calculate the sides and we have one general function which calculates the area.
In each class we will add this function and implement the propper calculation for that shape.
You should not use interfaces that don’t make sense.
You should not use an interface to implement a class that has no need to all the methods in the interface.
You should create multiple interfaces for similar but different class blueprints.
I have a question for you...
Once we all agreed that not all birds fly and using all what we have learned so far, we have created an interface Bird.
What will we do when we implement an Ostrich? Should we throw an exception?
We solve this by creating separate interfaces for flying and running birds.
Then we implement the interfaces we need.
In every software project we have high level modules and low level modules. In simplest terms the high level modules are the ones we call directly and do all the high level business logic. While low level modules are classes that help our high level modules, this can be inserting data to a database or printing a date in the correct format. Even if you have more than two levels, always will be a high level module and a low level module.
Your high level module can be a class that posts comments. The low level module is then inserting the post to the database. But inserting the post to database can be a high level module for another low level module that validate the data to be posted to the database.
The direction is always from high to low level. But the trick here is to inverse this dependency. So the high level module does not depend on the low level one. This way we decouple them so we can use the high level modules without the need of the low level ones.
We can create our own low level modules when we use a high level one. We must define interfaces instead of implementations!
So we pass all our low level modules to the high level modules.
But what if we need to use another type of database?
We will get an exception error because we can only pass an object of the Mysql type. What we should do is define our interface.
Now we can pass whatever implementation we want based to our Adapter interface.
You want to use an PostgreSQL database? Well just a create a new implementation of the Adapter interface and pass it to our controller. You wont need to change any other code. Everyone using this controller can use the database they want.