Skip to content

Commit c86c7cb

Browse files
committed
grasp
1 parent 8dcad54 commit c86c7cb

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

architecture/grasp.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
## GRASP принципы
2+
3+
Принципы GRASP описывают как разделить правильно код на логические части так, чтоб достичь полиморфизма.
4+
5+
Из GRASP понадобится всего один принцип для объединения(Information Expert) и два принципа для разделения логики (Low Coupling и High Cohesion).
6+
7+
Начнем с разделения логики, так как зачастую в проектах без какого-либо этикета написания кода можно встретить или fat model, или fat controller.
8+
Эти два принципа помогают как в написании нового функционала в новом проекте, так и при рефакторинге старого легаси проекта.
9+
Руководствуясь логикой, что при создании нового функционала разработчик склонен плодить сущности сверх необходимого, а при доработке наоборот старается не создавать лишних сущностей, необходимо постараться выдерживать баланс.
10+
11+
### Low Coupling
12+
13+
Low Coupling (слабое зацепление) - этот принцип гласит чем меньше `use` в классе тем лучше.
14+
Самым ярким примером слабого зацепления является антипаттерн God object.
15+
God object может быть минимально зависим от других объектов при этом содержать в себе реализацию логики не относящуюся к данному объекту, что уменьшает высокую связанность.
16+
17+
### High Cohesion
18+
19+
High Cohesion (высокая связанность) - принцип диктует правило для класса. Класс должен выполнять минимальное количество действий.
20+
К примеру если класс реализует логику рассылки писем, то этот класс не должен отвечать за формирование содержимого этого письма.
21+
22+
```php
23+
class Mail {
24+
protected string $mailTo;
25+
26+
protected string $subject;
27+
28+
protected string $bodyBoilerplate = 'Hi \s';
29+
30+
public function getMailTo(): string
31+
{
32+
return $this->mailTo;
33+
}
34+
35+
public function getSubject(): string
36+
{
37+
return $this->subject;
38+
}
39+
40+
public function getBody()
41+
{
42+
// логика формирования письма
43+
return sprintf($this->bodyBoilerplate, $username);
44+
}
45+
}
46+
47+
class Mailer
48+
{
49+
public function send(Mail $mail)
50+
{
51+
mail($mail->getMailTo(), $mail->getSubject(), $mail->getBody());
52+
}
53+
}
54+
```
55+
56+
При помощи такого разделения `Mailer` отвечает только за отправку, но не отвечает за отправляемое, а `Mail` наоборот.
57+
То есть изменив логику формирования письма это никак не повлияет на его отправку и наоборот, если есть необходимость поменять способ отправки не нужно будет задумываться еще и формировании его содержимого.
58+
59+
### Information Expert
60+
61+
Information Expert - этот принцип говорит нам, что кто владеет данными, тот и должен по логике ими управлять.
62+
63+
```php
64+
class BillProduct {
65+
private int $quantity;
66+
67+
private float $price;
68+
69+
public function getSum(): float
70+
{
71+
return $this->quantity * $this->price;
72+
}
73+
}
74+
75+
class Bill {
76+
private array $billProducts = [];
77+
78+
public function addBillProduct(BillProduct $billProduct): void
79+
{
80+
$this->billProducts[] = $billProduct;
81+
}
82+
83+
public function getSum()
84+
{
85+
$totalSum = 0;
86+
foreach($this->billProducts as $billProduct) {
87+
$totalSum += $billProduct->getSum();
88+
}
89+
...
90+
}
91+
}
92+
93+
```
94+
95+
Из примера видно, что у продукта из счёта есть свойства, которые позволяют рассчитать стоимость одной позиции. Значит она и должна быть рассчитана в `BillProduct`.
96+
А `Bill` оперирует уже всеми продуктами. Значит общая сумма по счету должна быть рассчитана в нем.

architecture/oop.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ class FullBill {
4646
При данной реализации добавить отдельный расчет за табачные изделия не составит труда. Но тут так же играет роль сам бизнес процесс, который и диктует требования к реализации.
4747
Всегда из поставленной задачи необходимо попытаться предположить как может измениться процесс. Так как можно усложнить приложение там, где никогда процесс работы приложения не поменяется.
4848

49-
Наследование является достаточно спорным решением для достижения полиморфизма из-за рисков создания God object.
50-
God object - это огромная проблема для приложения. По возможности не используйте абстрактные классы, если не достигается полиморфизм.
49+
Наследование является достаточно спорным решением для достижения полиморфизма из-за рисков создания God object и/или уход в излишнюю абстракцию, которая приведет к сильной зависимости(связанности) классов между собой вдобавок усложнив читабельность кода.
50+
По возможности не используйте абстрактные классы, если не достигается полиморфизм.
5151

52+
Инкапсуляция помогает же скрыть детали реализации. Зачастую чтоб отрефакторить старый код, понять его логику помогает подход реализуемый в 3 этапа:
53+
- разделить код на логические куски.
54+
- инкапсулировать логику этих кусков кода.
55+
- написав по возможности unit тесты, попутно задокументировав логику работы, внести необходимые изменения.

readme.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Перед внедрением каких-либо процессов необходимо провести экспертный анализ.
1212
Если на проекте код находится на физическом сервере или VPS, код на сервер доставляется пуллом с репозитория актуальной версии проекта или прямой доставкой приложения по SSH.
1313
А архитектура проекта заканчивается на MVC.
14-
В таком случае категорически не рекомендуется пытаться все перевести на микросервисы, которые будут крутиться в kubernetes в облаке.
14+
В таком случае категорически не рекомендуется пытаться все перевести на микросервисы, которые будут крутиться в kubernetes в облаке за одну итерацию.
1515
На проекте работают люди, и при внедрении актуальных инструментов, архитектурных решений и сервисов, есть риск столкнуться с непониманием и не принятием со стороны команды.
1616
Проект должен прожить все этапы развития. Сколько времени займет создание процесса и внедрение новых инструментов зависит только от команды.
1717

@@ -21,8 +21,9 @@
2121

2222
### Оглавление
2323

24-
- Базовые подходы к написанию кода
24+
- Как писать код? Базовые подходы к написанию кода
2525
- [Чистый код](https://github.com/3xter/clean-code-php)
2626
- [Функциональное программирование](./architecture/functional-programming.md)
2727
- [Объектно-ориентированное программирование](./architecture/oop.md)
28-
28+
- Куда писать код? Структуризация проекта
29+
- [GRASP](./architecture/grasp.md)

0 commit comments

Comments
 (0)