-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
500 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
@extends('layout') | ||
@section('title', 'SOLID принципы') | ||
@section('description', 'Мы поочередно познакомимся с каждым принципом, чтобы понять, как SOLID может помочь вам стать лучшим разработчиком.') | ||
@section('content') | ||
|
||
<x-header align="align-items-end"> | ||
<x-slot name="sup">Объектно-ориентированные</x-slot> | ||
<x-slot name="title">SOLID принципы</x-slot> | ||
<x-slot name="description"> | ||
Мы поочередно познакомимся с каждым принципом, чтобы понять, как SOLID может помочь вам стать лучшим разработчиком. | ||
</x-slot> | ||
<x-slot name="content"> | ||
<figure class="d-none d-md-block"> | ||
<x-icon path="l.dots" class="text-primary opacity-2 d-block mx-auto" height="300" width="300"/> | ||
</figure> | ||
</x-slot> | ||
</x-header> | ||
|
||
@php | ||
$sections = collect([ | ||
'basics', | ||
'srp', | ||
'ocp', | ||
'lsp', | ||
'lsp', | ||
'dip', | ||
]) | ||
->map(fn ($file) => \Illuminate\Support\Str::of($file)->start('solid/')) | ||
->map(fn ($file) => new \App\Library($file)); | ||
@endphp | ||
|
||
@include('particles.library-section', ['sections' => $sections]) | ||
|
||
@endsection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: "Введение" | ||
description: "<strong>SOLID</strong> - это акроним для первых пяти принципов объектно-ориентированного проектирования от Роберта Мартина." | ||
--- | ||
|
||
*SOLID* - это основа объектно-ориентированного проектирования (ООП), которая помогает создавать гибкие, расширяемые и | ||
поддерживаемые программы. Когда ты понимаешь эти принципы, ты можешь писать код, который легко изменять и дополнять. | ||
|
||
Эти принципы не только полезны для написания качественного кода, но и часто встречаются на собеседованиях на должности | ||
разработчика. Рекрутеры и работодатели ценят знание SOLID, так как это указывает на твою способность создавать | ||
высококачественное программное обеспечение. | ||
|
||
Понимание SOLID помогает избежать типичных проблем, таких как сложная поддержка кода, неожиданные ошибки и сложности в | ||
расширении функциональности. Поэтому освоение этих принципов не только делает тебя лучшим разработчиком, но и помогает | ||
тебе быть востребованным на рынке труда. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--- | ||
title: "Принцип инверсии зависимостей" | ||
description: "Любые более высокие (дочерние) классы всегда должны зависеть от абстракций, а не от деталей." | ||
--- | ||
|
||
Принцип инверсии зависимостей (Dependency Inversion Principle, DIP) гласит, что модули высокого уровня не должны | ||
зависеть от модулей низкого уровня, а оба типа модулей должны зависеть от абстракций. Также он утверждает, что | ||
абстракции не должны зависеть от деталей, а детали должны зависеть от абстракций. | ||
|
||
Давай разберемся, что это означает на примере: | ||
|
||
```php | ||
<?php | ||
// Нарушение принципа инверсии зависимостей | ||
class Mailer | ||
{ | ||
|
||
} | ||
|
||
class SendWelcomeMessage | ||
{ | ||
private $mailer; | ||
|
||
public function __construct(Mailer $mailer) | ||
{ | ||
$this->mailer = $mailer; | ||
} | ||
} | ||
``` | ||
|
||
Здесь класс SendWelcomeMessage зависит от конкретной реализации Mailer, что нарушает принцип инверсии зависимостей. Если | ||
мы захотим изменить способ отправки сообщений, нам придется изменять и класс SendWelcomeMessage. | ||
|
||
Для исправления этой проблемы мы можем использовать абстракцию в виде интерфейса Mailer: | ||
|
||
```php | ||
interface Mailer | ||
{ | ||
public function send(); | ||
} | ||
|
||
class SmtpMailer implements Mailer | ||
{ | ||
public function send() | ||
{ | ||
// Реализация отправки через SMTP | ||
} | ||
} | ||
|
||
class SendGridMailer implements Mailer | ||
{ | ||
public function send() | ||
{ | ||
// Реализация отправки через SendGrid | ||
} | ||
} | ||
|
||
class SendWelcomeMessage | ||
{ | ||
private $mailer; | ||
|
||
public function __construct(Mailer $mailer) | ||
{ | ||
$this->mailer = $mailer; | ||
} | ||
} | ||
``` | ||
|
||
Теперь класс SendWelcomeMessage зависит от абстракции Mailer, а не от конкретной реализации. Мы можем легко изменить | ||
способ отправки сообщений, просто передавая нужную реализацию интерфейса Mailer в конструктор SendWelcomeMessage. Это | ||
соответствует принципу инверсии зависимостей. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
--- | ||
title: "Принцип разделения интерфейса" | ||
description: "Интерфейсов должно быть много." | ||
--- | ||
|
||
Принцип разделения интерфейса (Interface Segregation Principle, ISP) предписывает, что клиенты не должны зависеть от | ||
методов, которые они не используют. Вместо этого интерфейсы должны быть разделены на более мелкие, специализированные | ||
интерфейсы, чтобы клиенты могли реализовывать только те методы, которые им нужны. | ||
|
||
Давай разберем, как это работает на примере: | ||
|
||
```php | ||
// Нарушение принципа разделения интерфейса | ||
interface Workable | ||
{ | ||
public function canCode(); | ||
public function code(); | ||
public function test(); | ||
} | ||
|
||
class Programmer implements Workable | ||
{ | ||
public function canCode() | ||
{ | ||
return true; | ||
} | ||
|
||
public function code() | ||
{ | ||
return 'coding'; | ||
} | ||
|
||
public function test() | ||
{ | ||
return 'testing in localhost'; | ||
} | ||
} | ||
|
||
class Tester implements Workable | ||
{ | ||
public function canCode() | ||
{ | ||
return false; | ||
} | ||
|
||
public function code() | ||
{ | ||
throw new Exception('Opps! I can not code'); | ||
} | ||
|
||
public function test() | ||
{ | ||
return 'testing in test server'; | ||
} | ||
} | ||
|
||
class ProjectManagement | ||
{ | ||
public function processCode(Workable $member) | ||
{ | ||
if ($member->canCode()) { | ||
$member->code(); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
В этом примере интерфейс Workable содержит методы canCode(), code() и test(). Проблема в том, что не все классы, | ||
реализующие этот интерфейс, могут выполнять все эти действия. Например, класс Tester не может кодировать, но он должен | ||
реализовать метод code(), потому что интерфейс Workable требует это. | ||
|
||
Чтобы исправить это, мы можем разделить интерфейс на более мелкие и специализированные интерфейсы: | ||
|
||
```php | ||
// Улучшенный вариант | ||
interface Codeable | ||
{ | ||
public function code(); | ||
} | ||
|
||
interface Testable | ||
{ | ||
public function test(); | ||
} | ||
|
||
class Programmer implements Codeable, Testable | ||
{ | ||
public function code() | ||
{ | ||
return 'coding'; | ||
} | ||
|
||
public function test() | ||
{ | ||
return 'testing in localhost'; | ||
} | ||
} | ||
|
||
class Tester implements Testable | ||
{ | ||
public function test() | ||
{ | ||
return 'testing in test server'; | ||
} | ||
} | ||
|
||
class ProjectManagement | ||
{ | ||
public function processCode(Codeable $member) | ||
{ | ||
$member->code(); | ||
} | ||
} | ||
``` | ||
|
||
Теперь интерфейсы Codeable и Testable более специализированы. Класс Programmer реализует оба интерфейса, потому что он | ||
может кодировать и тестировать. Класс Tester реализует только интерфейс Testable, потому что он может только | ||
тестировать. Таким образом, классы могут реализовывать только те методы, которые им нужны, что соответствует принципу | ||
разделения интерфейса. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
--- | ||
title: "Принцип подстановки Барбары Лисков" | ||
description: "Дочерние классы должны работать так, что бы ими можно было заменить родительские." | ||
--- | ||
|
||
Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP) утверждает, что поведение подклассов должно быть | ||
совместимо с поведением их суперклассов. Другими словами, объекты подтипов должны быть заменяемыми экземплярами своих | ||
супертипов без изменения ожидаемого поведения программы. Давай разберемся с примером, чтобы лучше понять этот принцип: | ||
|
||
```php | ||
<?php | ||
|
||
// Нарушение принципа подстановки Барбары Лисков | ||
// Проблема квадрата и прямоугольника | ||
class Rectangle | ||
{ | ||
protected $width; | ||
protected $height; | ||
|
||
public function setHeight($height) | ||
{ | ||
$this->height = $height; | ||
} | ||
|
||
public function getHeight() | ||
{ | ||
return $this->height; | ||
} | ||
|
||
public function setWidth($width) | ||
{ | ||
$this->width = $width; | ||
} | ||
|
||
public function getWidth() | ||
{ | ||
return $this->width; | ||
} | ||
|
||
public function area() | ||
{ | ||
return $this->height * $this->width; | ||
} | ||
} | ||
|
||
class Square extends Rectangle | ||
{ | ||
public function setHeight($value) | ||
{ | ||
$this->width = $value; | ||
$this->height = $value; | ||
} | ||
|
||
public function setWidth($value) | ||
{ | ||
$this->width = $value; | ||
$this->height = $value; | ||
} | ||
} | ||
|
||
class RectangleTest | ||
{ | ||
private $rectangle; | ||
|
||
public function __construct(Rectangle $rectangle) | ||
{ | ||
$this->rectangle = $rectangle; | ||
} | ||
|
||
public function testArea() | ||
{ | ||
$this->rectangle->setHeight(2); | ||
$this->rectangle->setWidth(3); | ||
// Ожидаем, что площадь прямоугольника будет 6 | ||
} | ||
} | ||
``` | ||
|
||
В данном примере класс Square наследуется от Rectangle, что кажется логичным, так как квадрат является частным случаем | ||
прямоугольника. Однако, нарушается принцип подстановки Барбары Лисков из-за того, что Square переопределяет методы | ||
setHeight() и setWidth() так, чтобы они всегда делали высоту равной ширине. | ||
|
||
Что делает этот пример нарушением LSP? Дело в том, что ожидается, что при вызове setHeight() и setWidth() объекта | ||
Rectangle сначала будет изменяться одно измерение, а потом другое. Однако в случае Square эти методы нарушают это | ||
ожидание, что может привести к непредсказуемому поведению в программах, которые используют Rectangle или его подтипы. | ||
|
||
Как исправить это? Один из способов - пересмотреть архитектуру классов так, чтобы Square не наследовался от Rectangle, | ||
так как это нарушает LSP. Вместо этого, можно использовать композицию или выделить общий интерфейс для обоих классов и | ||
разработать их независимо. |
Oops, something went wrong.