Merge pull request #1 from skyzyx/20150315-solid

Expanded and clarified the language around SOLID principles.
This commit is contained in:
Vladimir Kovpak
2015-10-05 09:12:37 +03:00

View File

@@ -15,47 +15,66 @@ separate from our objects. In terms of Dependency Injection, this means loosenin
instantiating them elsewhere in the system. instantiating them elsewhere in the system.
For years, PHP frameworks have been achieving Inversion of Control, however, the question became, which part of control For years, PHP frameworks have been achieving Inversion of Control, however, the question became, which part of control
are you inverting, and where to? For example, MVC frameworks would generally provide a super object or base controller are we inverting, and where to? For example, MVC frameworks would generally provide a super object or base controller
that other controllers must extend to gain access to its dependencies. This **is** Inversion of Control, however, that other controllers must extend to gain access to its dependencies. This **is** Inversion of Control, however,
instead of loosening dependencies, this method simply moved them. instead of loosening dependencies, this method simply moved them.
Dependency Injection allows us to more elegantly solve this problem by only injecting the dependencies we need, when we Dependency Injection allows us to more elegantly solve this problem by only injecting the dependencies we need, when we
need them, without the need for any hard coded dependencies at all. need them, without the need for any hard coded dependencies at all.
### SOLID ### S.O.L.I.D.
#### Single responsibility principle #### Single Responsibility Principle
It's very helpful principle because it improve code reusability and The Single Responsibility Principle is about actors and high-level architecture. It states that “A class should have
states that every class should have responsibility over a single part of the functionality provided by the software. only one reason to change.” This means that every class should _only_ have responsibility over a single part of the
Your class should do just one thing and no more. And you can use it in any place of program without changing it. functionality provided by the software. The largest benefit of this approach is that it enables improved code
_reusability_. By designing our class to do just one thing, we can use (or re-use) it in any other program without
changing it.
#### Open/closed principle #### Open/Closed Principle
States that classes should be open for extension, but closed for modification. The Open/Closed Principle is about class design and feature extensions. It states that “Software entities (classes,
it's very important and helpful especially in production, modules, functions, etc.) should be open for extension, but closed for modification.” This means that we should design
because it provides ability to change program behaviour without changing source code. our modules, classes and functions in a way that when a new functionality is needed, we should not modify our existing
code but rather write new code that will be used by existing code. Practically speaking, this means that we should write
classes that implement and adhere to _interfaces_, then type-hint against those interfaces instead of specific classes.
#### Liskov substitution principle The largest benefit of this approach is that we can very easily extend our code with support for something new without
having to modify existing code, meaning that we can reduce QA time, and the risk for negative impact to the application
is substantially reduced. We can deploy new code, faster, and with more confidence.
This principle extends previous principle, and states #### Liskov Substitution Principle
if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S
without altering any class of the program.
That's amazing principle provides ability to build very flexible and easily configurable programs
because when you change one object to another you don't need to change anything in your program.
#### Interface segregation principle The Liskov Substitution Principle is about subtyping and inheritance. It states that “Child classes should never break
the parent class type definitions.” Or, in Robert C. Martins words, “Subtypes must be substitutable for their base
types.”
Splits interfaces which are very large into smaller and more specific ones. For example, if we have a `FileInterface` interface which defines an `embed()` method, and we have `Audio` and `Video`
It provides to work in each time only with methods that interesting for client, classes which both implement the `embed()` method, then we can expect that the usage of the `embed()` method will always
and facilitate conceptual explanation of the code. do the thing that we intend. If we later create a `PDF` class or a `Gist` class which implement the `FileInterface`
interface, we will already know and understand what the `embed()` method will do. The largest benefit of this approach
is that we have the ability to build flexible and easily-configurable programs, because when we change one object of a
type (e.g., `FileInterface`) to another we don't need to change anything else in our program.
#### Interface Segregation Principle
The Interface Segregation Principle (ISP) is about _business-logic-to-clients_ communication. It states that “No client
should be forced to depend on methods it does not use.” This means that instead of having a single monolithic interface
that all conforming classes need to implement, we should instead provide a set of smaller, concept-specific interfaces
that a conforming class implements one or more of.
For example, a `Car` or `Bus` class would be interested in a `steeringWheel()` method, but a `Motorcycle` or `Tricycle`
class would not. Conversely, a `Motorcycle` or `Tricycle` class would be interested in a `handlebars()` method, but a
`Car` or `Bus` class would not. There is no need to have all of these types of vehicles implement support for both
`steeringWheel()` as well as `handlebars()`, so we should break-apart the source interface.
#### Dependency Inversion Principle #### Dependency Inversion Principle
Dependency Inversion Principle set of object oriented design principles that states one The Dependency Inversion Principle is about removing hard-links between discrete classes so that new functionality can
should *"Depend on Abstractions. Do not depend on concretions."*. Put simply, this means our dependencies should be be leveraged by passing a different class. It states that one should *"Depend on Abstractions. Do not depend on
interfaces/contracts or abstract classes rather than concrete implementations. We can easily refactor the above example concretions."*. Put simply, this means our dependencies should be interfaces/contracts or abstract classes rather than
to follow this principle. concrete implementations. We can easily refactor the above example to follow this principle.
{% highlight php %} {% highlight php %}
<?php <?php
@@ -78,7 +97,7 @@ class MysqlAdapter implements AdapterInterface {}
There are several benefits to the `Database` class now depending on an interface rather than a concretion. There are several benefits to the `Database` class now depending on an interface rather than a concretion.
Consider that you are working in a team and the adapter is being worked on by a colleague. In our first example, we Consider that we are working in a team and the adapter is being worked on by a colleague. In our first example, we
would have to wait for said colleague to finish the adapter before we could properly mock it for our unit tests. Now would have to wait for said colleague to finish the adapter before we could properly mock it for our unit tests. Now
that the dependency is an interface/contract we can happily mock that interface knowing that our colleague will build that the dependency is an interface/contract we can happily mock that interface knowing that our colleague will build
the adapter based on that contract. the adapter based on that contract.