← Назад к вопросам
Какие знаешь признаки плохого кода в процедурном стиле?
2.2 Middle🔥 231 комментариев
#Soft Skills#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Признаки плохого кода в процедурном стиле
Процедурный код часто страдает от специфических проблем, которые затрудняют его поддержку, тестирование и модификацию. Разберу основные антипаттерны.
1. God Objects и God Functions
Проблема: Функция делает слишком много
# ❌ Плохо - God Function из 500 строк
def process_user_registration(
email: str,
password: str,
first_name: str,
last_name: str,
phone: str,
address: str
):
# Валидация
if not email or '@' not in email:
return {"error": "Invalid email"}
if len(password) < 8:
return {"error": "Password too short"}
# ... ещё 50 строк валидации
# Проверка в БД
user = db.query(User).filter(User.email == email).first()
if user:
return {"error": "User exists"}
# ... ещё код
# Отправка email
send_email(email, f"Welcome {first_name}")
# Логирование
logger.info(f"User {email} registered")
# Создание в БД
new_user = User(email=email, ...)
db.add(new_user)
db.commit()
# ... ещё 400 строк
# ✅ Хорошо - разделить ответственность
class UserValidator:
def validate(self, email: str, password: str) -> Optional[str]:
if not email or '@' not in email:
return "Invalid email"
if len(password) < 8:
return "Password too short"
return None
class UserRepository:
def get_by_email(self, email: str) -> Optional[User]:
return db.query(User).filter(User.email == email).first()
def create(self, email: str, password: str, ...) -> User:
user = User(email=email, ...)
db.add(user)
db.commit()
return user
class RegistrationService:
def register(self, email: str, password: str, first_name: str, ...) -> dict:
error = self.validator.validate(email, password)
if error:
return {"error": error}
if self.repo.get_by_email(email):
return {"error": "User exists"}
user = self.repo.create(email, password, first_name, ...)
self.email_service.send_welcome(user)
self.logger.info(f"User {email} registered")
return {"success": True, "user_id": user.id}
2. Global State (Глобальное состояние)
Проблема: Скрытые зависимости
# ❌ Плохо - глобальное состояние
DATABASE_URL = "postgres://localhost/db"
db = None
config = {}
def initialize_db():
global db
db = connect(DATABASE_URL)
def get_user(user_id):
# Зависит от глобального db - трудно тестировать!
return db.query(User).filter(User.id == user_id).first()
def process_order(user_id, order_data):
user = get_user(user_id)
# Зависит от глобального config
if config.get('premium_discount') and user.is_premium:
order_data['discount'] = 0.2
# ... ещё код
# ✅ Хорошо - явные зависимости через параметры
class UserRepository:
def __init__(self, db_connection):
self.db = db_connection
def get(self, user_id: int) -> User:
return self.db.query(User).filter(User.id == user_id).first()
class OrderService:
def __init__(self, user_repo: UserRepository, config: dict):
self.user_repo = user_repo
self.config = config
def process(self, user_id: int, order_data: dict):
user = self.user_repo.get(user_id)
if self.config.get('premium_discount') and user.is_premium:
order_data['discount'] = 0.2
return order_data
3. Primitive Obsession (Одержимость примитивными типами)
Проблема: Тонкая логика размазана везде
# ❌ Плохо - Email как строка везде
def register_user(email: str, password: str):
# Валидация email разбросана по коду
if not email or '@' not in email or email.count('@') > 1:
raise ValueError("Invalid email")
# Где-то в другой функции
def send_confirmation_email(email: str):
if '@gmail.com' in email:
# Спам-фильтр Gmail
pass
if email.lower() != email:
email = email.lower()
# ... отправка
# ✅ Хорошо - Email как объект
from dataclasses import dataclass
@dataclass
class Email:
value: str
def __post_init__(self):
self.validate()
def validate(self):
if not self.value or '@' not in self.value:
raise ValueError("Invalid email")
if self.value.count('@') > 1:
raise ValueError("Invalid email")
def normalize(self) -> str:
return self.value.lower()
def get_domain(self) -> str:
return self.value.split('@')[1]
def register_user(email: Email, password: str):
# Email уже валидирован в конструкторе
db.save(email.normalize())
4. Long Parameter Lists (Длинные списки параметров)
Проблема: Трудно использовать и тестировать
# ❌ Плохо - 12 параметров
def create_report(
user_id: int,
start_date: str,
end_date: str,
include_deleted: bool,
include_archived: bool,
sort_by: str,
sort_order: str,
format: str,
send_email: bool,
email_recipients: list,
compress: bool,
password_protect: bool
):
pass
# Использование адского кода
report = create_report(
123, "2024-01-01", "2024-12-31",
False, True, "date", "desc",
"pdf", True, ["admin@example.com"],
True, True
)
# ✅ Хорошо - объекты конфигурации
from dataclasses import dataclass
from typing import Optional
from datetime import date
@dataclass
class ReportDateRange:
start_date: date
end_date: date
@dataclass
class ReportFilters:
include_deleted: bool = False
include_archived: bool = False
@dataclass
class ReportSort:
by: str = "date"
order: str = "desc"
@dataclass
class ReportOutput:
format: str = "pdf"
compress: bool = False
password_protect: bool = False
@dataclass
class ReportEmail:
send: bool = False
recipients: list = None
class ReportBuilder:
def __init__(self, user_id: int):
self.user_id = user_id
self.date_range: Optional[ReportDateRange] = None
self.filters = ReportFilters()
self.sort = ReportSort()
self.output = ReportOutput()
self.email = ReportEmail()
def build(self):
# Логика с явными объектами
pass
# Использование
report = (
ReportBuilder(123)
.set_date_range(date(2024, 1, 1), date(2024, 12, 31))
.set_format("pdf")
.set_sort("date", "desc")
.build()
)
5. Data Clumps (Кучи данных)
Проблема: Одни и те же параметры везде
# ❌ Плохо - address везде по частям
def send_shipping_label(street: str, city: str, zip: str, country: str):
pass
def validate_address(street: str, city: str, zip: str, country: str) -> bool:
pass
def save_customer_address(street: str, city: str, zip: str, country: str):
pass
# ✅ Хорошо - объект Address
from dataclasses import dataclass
@dataclass
class Address:
street: str
city: str
zip: str
country: str
def send_shipping_label(address: Address):
pass
def validate_address(address: Address) -> bool:
pass
def save_customer_address(address: Address):
pass
6. Deeply Nested Code (Глубокая вложенность)
Проблема: Трудно читать
# ❌ Плохо - 5 уровней вложенности
def process_payment(order_id: int, payment_data: dict):
order = db.get_order(order_id)
if order:
if order.status == "pending":
if payment_data.get('amount') > 0:
if validate_card(payment_data['card']):
if charge_card(payment_data['card'], payment_data['amount']):
order.status = "paid"
db.save(order)
return {"success": True}
else:
return {"error": "Charge failed"}
else:
return {"error": "Invalid card"}
else:
return {"error": "Invalid amount"}
else:
return {"error": f"Order status is {order.status}"}
else:
return {"error": "Order not found"}
# ✅ Хорошо - guard clauses (ранний выход)
def process_payment(order_id: int, payment_data: dict):
order = db.get_order(order_id)
if not order:
return {"error": "Order not found"}
if order.status != "pending":
return {"error": f"Order status is {order.status}"}
if payment_data.get('amount') <= 0:
return {"error": "Invalid amount"}
if not validate_card(payment_data['card']):
return {"error": "Invalid card"}
if not charge_card(payment_data['card'], payment_data['amount']):
return {"error": "Charge failed"}
order.status = "paid"
db.save(order)
return {"success": True}
7. Code Duplication (Дублирование кода)
Проблема: Одна ошибка в двух местах
# ❌ Плохо - одинаковый код
def create_user_report(user_id: int) -> dict:
user = db.get_user(user_id)
if not user:
return {"error": "User not found"}
data = {
"id": user.id,
"email": user.email,
"created_at": user.created_at.isoformat(),
"updated_at": user.updated_at.isoformat()
}
return {"success": True, "data": data}
def create_admin_report(user_id: int) -> dict:
user = db.get_user(user_id)
if not user:
return {"error": "User not found"}
data = {
"id": user.id,
"email": user.email,
"created_at": user.created_at.isoformat(),
"updated_at": user.updated_at.isoformat()
}
return {"success": True, "data": data}
# ✅ Хорошо - одна функция
def get_user_report(user_id: int) -> dict:
user = db.get_user(user_id)
if not user:
return {"error": "User not found"}
return {
"success": True,
"data": serialize_user(user)
}
def serialize_user(user: User) -> dict:
return {
"id": user.id,
"email": user.email,
"created_at": user.created_at.isoformat(),
"updated_at": user.updated_at.isoformat()
}
8. Comments That Explain Implementation
Проблема: Комментарии вместо хорошего кода
# ❌ Плохо - комментарий объясняет очевидное
def calculate_discount(user_purchase_history):
# Если пользователь купил больше 10 товаров, дадим ему скидку
discount = 0
if user_purchase_history > 10:
# Скидка 10%
discount = 0.1
return discount
# ✅ Хорошо - говорящее имя функции
def calculate_loyalty_discount(purchase_count: int) -> float:
LOYALTY_DISCOUNT_THRESHOLD = 10
LOYALTY_DISCOUNT_RATE = 0.1
if purchase_count > LOYALTY_DISCOUNT_THRESHOLD:
return LOYALTY_DISCOUNT_RATE
return 0
Чеклист плохого процедурного кода
- Функции длиннее 20-30 строк
- Функции с больше чем 3-4 параметрами
- Глобальные переменные и состояние
- Дублирование логики
- Глубокая вложенность (больше 3 уровней)
- Неясные имена переменных (x, temp, data)
- Нет обработки ошибок
- Трудно писать юнит тесты
- Примитивы вместо объектов
- Комментарии вместо хорошего кода
Переход на OOP и функциональный стиль решает большинство этих проблем!