← Назад к вопросам

Какие знаешь признаки плохого кода в процедурном стиле?

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 и функциональный стиль решает большинство этих проблем!