You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Responsabilité unique - Single Responsibility Principle
Une classe, une fonction ou une méthode doit avoir une et une seule responsabilité.
A class should have only a single responsibility (i.e only one potential change in the software's specification should be able to affect the specification of the class.
The generatePDF method violates the Single Responsibility Principle because if we wanted to change how the PDF is produced we would need to change the class.
Complying with the Single Responsibility Principle
class Document {
protected$title;
protected$content;
publicfunction__construct($title, $content) {
$this->title = $title;
$this->content = $content;
}
}
class Pdf {
protected$pdf;
publicfunction__construct() {}
publicfunctiongenerate(Document$document) {
return"Output the document as pdf: " . $this->title . $this->content;
}
}
//instantiate$document = newDocument('Hello', 'Hello World!');
$pdf = newPdf();
$pdf->generate($document);
In the above example the Document class only knows about the data it handles. The PDF class is responsible for generating the document as a PDF. If we wanted to output the document as HTML we would just create a new class class HTML with a generate method that return the document title and content as html content.
The problem with the above method, if we want to add a new shape the Area Calculator class would need changing and a new shape class added. This is because the area calculator is responsible for calculating the areas of all the different shapes.
Following the open closed principle, the area of each shape should be calculated by the class responsible for that shape.
With the method above when the area of a new shape needs calculating a new class with an area method needs adding and nothing else. If we wanted to calculate the area of a regular pentagon, we could add:
Substitution de Liskov - Liskov Substitution Principle
Une instance de type T doit pouvoir être remplacée par une instance de type G, tel que G sous-type de T, sans que cela ne modifie la cohérence du programme.
The principle defines that objects of a superclass shall be replaceable with objects of its subclasses without breaking the application. That requires the objects of your subclasses to behave in the same way as the objects of your superclass.
In subtypes, method arguments cannot be made narrower and method return types cannot be made wider.
The upgradeAccount method in the StudentAccountManager class violates the Liskov Substitution principle because the argument has been narrowed from CurrentAccount to StudentAccount. The return type has also been widened from Package Account to CurrentAccount. Furthermore as exception is thrown when FixDepositSavingAccount account is passed to the withdrawal method of AccountManager. This could be fixed by amending the withdrawl method to check the account type but this would break the open closed principle:
Now the withdrawal method of AccountManager will only make withdrawals from withdrawal savings accounts that have the withdrawal method.
The upgrade account is taken care of by the account class rather than the manager so the upgrade method on the account just needs to be called.
Préférer plusieurs interfaces spécifiques pour chaque client plutôt qu'une seule interface générale.
A client should never be forced to depend on methods it doesn't use.
Altering one method in a class shouldn't affect classes that don't depend on it.
Replace fat interfaces with many small, specific interfaces
Inversion de dépendance - Dependency Inversion Principle
Il faut dépendre des abstractions, pas des implémentations.
High level modules should not depend on low level modules
Abstractions should not depend on details. Details should depend upon abstactions
Violating the Dependency Inversion Principle
class Article {
publicfunctionall() {
return'Returning all articles from local database';
}
}
class Display {
protected$artical;
publicfunction__construct(Artical$artical) {
$this->artical = $artical;
}
publicfunctionarticles() {
return$this->artical->all();
}
}
The Display class is tightly coupled to the Article class used to retrieve the articles. If the data source for the articles changed the Display class would also have to be changed.
Complying with the Dependency Inversion Principle
interface ArticleInterface {
publicfunctionall();
}
class MysqlArticle implements ArticleInterface {
publicfunctionall() {
return'Returning all articles from local database';
}
}
class ApiArticle implements ArticleInterface {
publicfunctionall() {
return'Returning all articles from api';
}
}
class Display {
protected$article;
publicfunction__construct(ArticleInterface$article) {
$this->article = $article;
}
publicfunctionarticles() {
return$this->article->all();
}
}
By coupling the Display class to the ArticleInterface it easy to change the datasource of the articles from the database to the api.