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

Приведи пример когда осознанно нарушал SOLID

2.0 Middle🔥 111 комментариев
#Паттерны проектирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Нарушение SOLID: пример из практики разработки UI системы для кастомного редактора в Unity

Контекст задачи

В рамках разработки кастомного редактора для визуального редактирования диалогов в игре возникла необходимость создать систему UI-виджетов (ноды диалога, условия, ответы). На старте проекта, под давлением сроков и с фокусом на быстрый прототип, я сознательно пошел на нарушение принципов SOLID, в частности Single Responsibility Principle (SRP) и Open-Closed Principle (OCP), создав "божественный" класс DialogueNodeEditor.

Исходная архитектура (нарушающая SOLID)

Был создан монолитный класс, который отвечал за всё: отрисовку, логику, сериализацию и обработку событий.

// Нарушение SRP и OCP: "Божественный" класс, который делает всё
public class DialogueNodeEditor : EditorWindow
{
    private List<DialogueNode> nodes;
    private DialogueNode selectedNode;
    private SerializedObject serializedObject;

    // 1. Отрисовка UI
    public void OnGUI()
    {
        DrawGrid();
        DrawNodes();
        DrawConnections();
        DrawSelectedNodeInspector();
        DrawToolbar();
    }

    // 2. Логика работы с нодами
    private void ProcessNodeLogic()
    {
        // Обработка drag&drop, создание, удаление, соединение нод
    }

    // 3. Сериализация/десериализация
    private void SaveToAsset()
    {
        // Прямая работа с ScriptableObject и JSON
    }

    // 4. Обработка событий мыши/клавиатуры
    private void HandleEvents(Event e)
    {
        // Огромный switch по типам событий
    }

    // 5. Валидация данных
    private bool ValidateGraph()
    {
        // Проверка ссылок, условий, etc.
    }
}

Сознательные причины нарушения SOLID

  • Скорость прототипирования: На начальном этапе важно было быстро получить работающий инструмент для дизайнеров, чтобы собирать диалоги. Разделение на множество мелких классов с четкими интерфейсами заняло бы в 3-4 раза больше времени.
  • Быстрое изменение требований: Требования к функционалу нод менялись почти ежедневно. Монолитная структура позволяла вносить изменения "в одном месте", не тратя время на рефакторинг зависимостей между несколькими классами.
  • Ограниченная область применения: Система была четко заточена под одну задачу — редактирование диалогов. Не предполагалось её повторное использование для других типов графов (например, AI-деревьев или анимаций) в обозримом будущем.
  • Контроль сложности на малом масштабе: Пока количество типов нод (5-7) и их логика были простыми, один большой класс оставался обозримым (≈500 строк). Все зависимости были "зашиты" внутри, что упрощало ментальную модель для одного разработчика.

Последствия и рефакторинг

Через 2 месяца, когда система разрослась (появилось 15+ типов нод, сложная валидация, история изменений, импорт/экспорт), начали проявляться проблемы:

  • Хрупкость: Любое изменение в отрисовке могло сломать логику сериализации.
  • Невозможность тестирования: Логику нельзя было покрыть юнит-тестами из-за сильной связи с GUI.
  • "Merge Hell": Несколько разработчиков не могли работать параллельно, так как все правки касались одного огромного файла.

Пришлось провести крупный рефакторинг, разделив систему по принципам SOLID:

// 1. Каждый класс теперь имеет одну ответственность
public interface INodeRenderer { void Draw(Node node, Rect rect); }
public class DialogueNodeRenderer : INodeRenderer { /* ... */ }

public interface INodeLogicHandler { void HandleEvent(NodeEvent e); }
public class DefaultNodeLogicHandler : INodeLogicHandler { /* ... */ }

public interface IDataSerializer { string Serialize(Graph graph); }
public class JsonGraphSerializer : IDataSerializer { /* ... */ }

// 2. Система расширяема через новые реализации (OCP)
public class ConditionNodeRenderer : INodeRenderer { /* Специфичная отрисовка */ }

Вывод и уроки

Этот опыт наглядно показал, что SOLID — это не догма, а прагматичный инструмент. Его сознательное нарушение оправдано в строго ограниченных условиях:

  • Жесткие временные рамки для создания прототипа.
  • Четкое понимание, что это временное решение.
  • Ограниченный scope системы, который не будет масштабироваться.
  • План на рефакторинг при достижении определенного порога сложности.

Ключевой навык — не слепое следование принципам, а умение оценить компромисс между скоростью разработки сейчас и поддержкой/масштабированием в будущем. В этом случае нарушение SOLID позволило быстро запустить производство контента, что было критически важно для проекта, а последующий рефакторинг стал плановым этапом, а не "тушением пожара".