Skip to content

Commit 92c0e50

Browse files
authored
Changed layout of sections
1 parent 6f39d0a commit 92c0e50

File tree

1 file changed

+137
-134
lines changed

1 file changed

+137
-134
lines changed

README.md

Lines changed: 137 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77

88
## Содержание
99
- [Основные принципы при написании кода](#основные-принципы-при-написании-кода)
10-
- [Пакетный менеджер](#пакетный-менеджер)
11-
- [Форматирование кода](#форматирование-кода)
12-
- [Типизация](#типизация)
13-
- [Импорты](#импорты)
10+
- [Про код](#про-код)
1411
- [Размеры методов, функций и модулей](#размеры-методов-функций-и-модулей)
12+
- [Импорты](#импорты)
1513
- [Файлы `__init__.py`](#файлы-__init__py)
1614
- [Докстринги](#докстринги)
1715
- [Документация к REST API](#документация-к-rest-api)
18-
- [Про код](#про-код)
1916
- [Про Pull Request](#про-pull-request)
2017
- [Размер Pull Request](#размер-pull-request)
18+
- [Пакетный менеджер](#пакетный-менеджер)
19+
- [Форматирование кода](#форматирование-кода)
20+
- [Типизация](#типизация)
2121

2222

2323
## Основные принципы при написании кода
@@ -26,6 +26,138 @@
2626
- **Очевидность** (представьте, когда подключится новый программист, насколько ему будет понятно, почему именно **так** написан этот код)
2727

2828

29+
## Про код
30+
**1 действие ~ 1 строка**
31+
32+
На каждой строке надо постараться делать ровно одно действие.
33+
34+
Плохо ❌:
35+
```python
36+
# 1. 3 действия на одной строке - 3 вызова функции
37+
foo_result = foo(bar(spam(x)))
38+
39+
# 2. 3 действия на одной строке - вызов функции foo, get_c, from_b
40+
foo_result = foo(a=a, b=b, c=get_c(from_b())
41+
42+
# 3. 3 действия на одной строке - фильтрация по аргументам, условное получение элементов (через or), вызов метода .value
43+
result = [(a.value() or A, b or B) for a, b in iterator if a < b]
44+
45+
# 4. 4 действия на одной строке - из библиотеки / переменной foo идет получение атрибута bar, получение атрибута spam, получение атрибута hello и вызов calculate_weather
46+
result = calculate_weather(foo.bar.spam.hello)
47+
```
48+
49+
Хорошо ✅:
50+
```python
51+
# 1. делаем поочередный вызов каждой функции
52+
spam_result = spam(x)
53+
bar_result = bar(spam_result)
54+
foo_result = foo(bar_result)
55+
56+
# 2. поочередно вызываем функции, результат пишем в переменную и используем ее при вызове foo
57+
from_b_result = from_b()
58+
c = get_c(from_b_result)
59+
foo_result = foo(a=a, b=b, c=c)
60+
61+
# 3. последовательно проводим действия над списком - вначале фильтруем, вызываем метод .value у a, выбираем между элементами (or)
62+
filtered_result = ((a, b) for a, b in iterator if a < b)
63+
intermediate_result = ((a.value(), b) for a, b in filtered_result)
64+
result = [(a or A, b or B) for a, b in intermediate_result]
65+
66+
# 4 . последовательно читаем атрибуты bar, spam, hello и вызываем функцию calculate_weather
67+
bar = foo.bar
68+
spam = bar.spam
69+
hello = spam.hello
70+
result = calculate_weather(hello)
71+
```
72+
73+
74+
**Почему?** Потому что код становится более читабельным, не нужно исполнять несколько выражений в голове во время чтения кода. Разбитый до простых атомных операций код воспринимается гораздо лучше, чем сложный уан-лайнер. Постарайтесь упростить свой код настолько, насколько это возможно - код чаще читается, чем пишется.
75+
76+
77+
## Размеры методов, функций и модулей
78+
79+
Предельный размер метода или функции - **50** строк.
80+
Достижение предельного размера говорит о том, что функция (метод) делает слишком много - декомпозируйте действия внутри функции (метода).
81+
82+
83+
Предельный размер модуля - **300** строк.
84+
Достижение предельного размера говорит о том, что модуль получил слишком много логики - декомпозируйте модуль на несколько.
85+
86+
Длина строки - 100 символов.
87+
88+
89+
## Импорты
90+
91+
Рекомендуемый способ импортирования - абсолютный.
92+
93+
Плохо ❌:
94+
```python
95+
# spam.py
96+
from . import foo, bar
97+
```
98+
99+
Хорошо ✅:
100+
```python
101+
102+
# spam.py
103+
from some.absolute.path import foo, bar
104+
```
105+
106+
**Почему?** Потому что абсолютный импорт явно определяет локацию (путь) модуля, который импортируется. При релативном
107+
импорте всегда нужно помнить путь и вычислять в уме локацию модулей `foo.py`, `bar.py` относительно `spam.py`
108+
109+
110+
## Файлы `__init__.py`
111+
112+
В `__init__.py` файлах пишем только импорты.
113+
114+
**Почему?** Потому что `__init__.py` - последнее место, в которое посмотрит программист, который будет читать код в будущем.
115+
116+
117+
## Докстринги
118+
Рекомендуем добавлять докстринги в функции, методы и классы.
119+
120+
**Почему?** Потому что программист, который впервые увидит ваш код, сможет быстрее понять, что в нем происходит.
121+
Код читается намного больше, чем пишется.
122+
123+
124+
## Документация к REST API
125+
Рекомендуемый формат документации - [OpenAPI](https://www.openapis.org).
126+
Схема для OpenAPI должна генерироваться "на лету", чтобы обеспечивать клиентов API свежими изменениями.
127+
128+
**Почему?** Потому что это один из распространенных форматов для документирования REST API, которая вышла из Swagger. Данный формат документации поддерживается большим количеством клиентов (Swagger, Postman, Insomnia Designer и многие другие). Также, рукописная документация имеет свойство быстро устаревать, а документация, которая генерируется напрямую из кода позволяет не думать о постоянном обновлении документации.
129+
130+
131+
## Про Pull Request
132+
**1 Pull Request = 1 issue**
133+
134+
Один Pull Request должен решать ровно одно issue.
135+
136+
**Почему?** Потому что ревьюверу сложнее держать контекст нескольких задач в голове и переключаться между ними.
137+
138+
139+
## Размер Pull Request
140+
Итоговый дифф PR не должен превышать +/- 600 измененных строк.
141+
142+
Плохо ❌:
143+
144+
![bad](https://user-images.githubusercontent.com/8825727/113953748-6fc7ba80-9853-11eb-9673-827995e54f73.png)
145+
```
146+
Дифф 444 + 333 = 777
147+
```
148+
149+
Хорошо ✅:
150+
151+
![good](https://user-images.githubusercontent.com/8825727/113953831-a30a4980-9853-11eb-854b-d4c4f6559f2c.png)
152+
```
153+
Дифф 222 + 111 = 333
154+
```
155+
156+
157+
**Почему?** Потому что чем больше PR - тем более он становится неконтролируемым и мерж производится "закрыв глаза и заткнув уши".
158+
Также, большинству ревьюверов будет сложно воспринять такой объем изменений за один раз.
159+
160+
29161
## Пакетный менеджер
30162

31163
[poetry](https://python-poetry.org) - менеджер зависимостей и сборщик пакетов
@@ -135,132 +267,3 @@ ignore_errors = True
135267

136268
```
137269

138-
139-
## Импорты
140-
141-
Плохо ❌:
142-
```python
143-
# spam.py
144-
from . import foo, bar
145-
```
146-
147-
Хорошо ✅:
148-
```python
149-
150-
# spam.py
151-
from some.absolute.path import foo, bar
152-
```
153-
154-
**Почему?** Потому что абсолютный импорт явно определяет локацию (путь) модуля, который импортируется. При релативном
155-
импорте всегда нужно помнить путь и вычислять в уме локацию модулей `foo.py`, `bar.py` относительно `spam.py`
156-
157-
158-
## Размеры методов, функций и модулей
159-
160-
Предельный размер метода или функции - **50** строк.
161-
Достижение предельного размера говорит о том, что функция (метод) делает слишком много - декомпозируйте действия внутри функции (метода).
162-
163-
164-
Предельный размер модуля - **300** строк.
165-
Достижение предельного размера говорит о том, что модуль получил слишком много логики - декомпозируйте модуль на несколько.
166-
167-
Длина строки - 100 символов.
168-
169-
170-
## Файлы `__init__.py`
171-
172-
В `__init__.py` файлах пишем только импорты.
173-
174-
**Почему?** Потому что `__init__.py` - последнее место, в которое посмотрит программист, который будет читать код в будущем.
175-
176-
177-
## Докстринги
178-
Рекомендуем добавлять докстринги в функции, методы и классы.
179-
180-
**Почему?** Потому что программист, который впервые увидит ваш код, сможет быстрее понять, что в нем происходит.
181-
Код читается намного больше, чем пишется.
182-
183-
184-
## Документация к REST API
185-
Рекомендуемый формат документации - [OpenAPI](https://www.openapis.org).
186-
Схема для OpenAPI должна генерироваться "на лету", чтобы обеспечивать клиентов API свежими изменениями.
187-
188-
**Почему?** Потому что это один из распространенных форматов для документирования REST API, которая вышла из Swagger. Данный формат документации поддерживается большим количеством клиентов (Swagger, Postman, Insomnia Designer и многие другие). Также, рукописная документация имеет свойство быстро устаревать, а документация, которая генерируется напрямую из кода позволяет не думать о постоянном обновлении документации.
189-
190-
191-
## Про код
192-
**1 действие ~ 1 строка**
193-
194-
На каждой строке надо постараться делать ровно одно действие.
195-
196-
Плохо ❌:
197-
```python
198-
# 1. 3 действия на одной строке - 3 вызова функции
199-
foo_result = foo(bar(spam(x)))
200-
201-
# 2. 3 действия на одной строке - вызов функции foo, get_c, from_b
202-
foo_result = foo(a=a, b=b, c=get_c(from_b())
203-
204-
# 3. 3 действия на одной строке - фильтрация по аргументам, условное получение элементов (через or), вызов метода .value
205-
result = [(a.value() or A, b or B) for a, b in iterator if a < b]
206-
207-
# 4. 4 действия на одной строке - из библиотеки / переменной foo идет получение атрибута bar, получение атрибута spam, получение атрибута hello и вызов calculate_weather
208-
result = calculate_weather(foo.bar.spam.hello)
209-
```
210-
211-
Хорошо ✅:
212-
```python
213-
# 1. делаем поочередный вызов каждой функции
214-
spam_result = spam(x)
215-
bar_result = bar(spam_result)
216-
foo_result = foo(bar_result)
217-
218-
# 2. поочередно вызываем функции, результат пишем в переменную и используем ее при вызове foo
219-
from_b_result = from_b()
220-
c = get_c(from_b_result)
221-
foo_result = foo(a=a, b=b, c=c)
222-
223-
# 3. последовательно проводим действия над списком - вначале фильтруем, вызываем метод .value у a, выбираем между элементами (or)
224-
filtered_result = ((a, b) for a, b in iterator if a < b)
225-
intermediate_result = ((a.value(), b) for a, b in filtered_result)
226-
result = [(a or A, b or B) for a, b in intermediate_result]
227-
228-
# 4 . последовательно читаем атрибуты bar, spam, hello и вызываем функцию calculate_weather
229-
bar = foo.bar
230-
spam = bar.spam
231-
hello = spam.hello
232-
result = calculate_weather(hello)
233-
```
234-
235-
236-
**Почему?** Потому что код становится более читабельным, не нужно исполнять несколько выражений в голове во время чтения кода. Разбитый до простых атомных операций код воспринимается гораздо лучше, чем сложный уан-лайнер. Постарайтесь упростить свой код настолько, насколько это возможно - код чаще читается, чем пишется.
237-
238-
239-
## Про Pull Request
240-
**1 Pull Request = 1 issue**
241-
242-
Один Pull Request должен решать ровно одно issue.
243-
244-
**Почему?** Потому что ревьюверу сложнее держать контекст нескольких задач в голове и переключаться между ними.
245-
246-
247-
## Размер Pull Request
248-
Итоговый дифф PR не должен превышать +/- 600 измененных строк.
249-
250-
Плохо ❌:
251-
252-
![bad](https://user-images.githubusercontent.com/8825727/113953748-6fc7ba80-9853-11eb-9673-827995e54f73.png)
253-
```
254-
Дифф 444 + 333 = 777
255-
```
256-
257-
Хорошо ✅:
258-
259-
![good](https://user-images.githubusercontent.com/8825727/113953831-a30a4980-9853-11eb-854b-d4c4f6559f2c.png)
260-
```
261-
Дифф 222 + 111 = 333
262-
```
263-
264-
265-
**Почему?** Потому что чем больше PR - тем более он становится неконтролируемым и мерж производится "закрыв глаза и заткнув уши".
266-
Также, большинству ревьюверов будет сложно воспринять такой объем изменений за один раз.

0 commit comments

Comments
 (0)