Skip to content

Instantly share code, notes, and snippets.

@fesor

fesor/README.md Secret

Last active April 24, 2024 10:35
Show Gist options
  • Save fesor/76d39b19b18f7103a7c058301dc6a8fe to your computer and use it in GitHub Desktop.
Save fesor/76d39b19b18f7103a7c058301dc6a8fe to your computer and use it in GitHub Desktop.
Project Structure

Структура проекта

Нагло своровано у angular styleguide и адаптировано под Symfony

LIFT

Структура проекта должны быть интуитивно понятна новому человеку в проекте. Для этого можно воспользоваться принципами LIFT. Согласно им структура проекта должна позволять

  • L - (Locate) легко находить нужный нам код
  • I - (Identify) идентифицировать ответственность с первого взгляда
  • F - (Flat) сохранять плоскую структуру настолько насколько это возможно
  • T - (Try to stay DRY или T-DRY) минимизировать дублирование в системе

Locate

Старайтесь делать систему так, чтобы она помогала искать нужный код.

В целом когда вы реализуете какую-то фичу или просто знакомитесь с новым проектом, вас больше интересует функционал, а не из каких кусков состоит проект. То есть открыв src мы должны примерно видеть о чем проект. Так, например если нам нужно внести изменения в какой-то функционал связанные с заказами мы пойдем в директорию Orders и там будет все что относится к этим самым заказам.

/src
  /Catalog
  /Orders
    /Action
    /Doctrine
    /EventListener
    /Model
      /Exception
        /OrderNotFound.php
      /Order.php
      /OrderLine.php
      /Buyer.php
      /OrderRepository.php
    /Notifications
    /RequestMapper
    /Service
  /Search
  /Users

Cohesion и Coupling

Стандартная структура где все сущности сгружены в одну кучу и, к примеру, все объекты-значения в другую, имеет огромный недостаток с точки зрения связанности и зацепления (cohesion). Для начала стоит принять что "папка" (или неймспейс) это ни что иное как модуль, какая-то целостная единица кода.

К примеру у нас есть сущность Product и вся логика подсчета остатка на складе вынесена в Embeddable объект AvailableQuantity. Если идти по пути расположения кода в соответствии с типом, то мы бы положили сущность Product в нэймспейс App\Entity а AvailableQuantity в App\ValueObject. То есть у модуля Entity появляется зависимость от модуля ValueObject, причем для каждого класса внутри этого модуля свои зависимости.

На картинке выше визуализирована структура модулей. Цветами обозначены разные модули, а пунктиром - границы между модулями. Как мы видим, в нашем случае появляется большое количество пересечений границ. Это является подсказкой о том что границы модулей были выбраны неверно. Достаточно просто перегруппировать файлики по своим неймспейсам и выделить модули Products и Categories:

Теперь между границами модулей у нас только одно пересечение. С этим уже можно жить, и в целом если нам нужно будет поправить что-то связанное с продуктом, мы знаем где это искать.

Identify

Когда вы смотрите на файлы, вы должны относительно легко понимать что там лежит. Профит заключается в том, что мы потратим меньше времени на "охоту за нужным кодом".

В целом для достижения этого стоит использовать PSR-1 (одно что-то на файл) и давать вещам осмысленные именования (PSR-4 далее сделает свое дело).

Если для этого вам придется использовать чуть более длинное имя класса - ну значит надо. Главное чтобы смысл был понятен.

Flat

Старайтесь сохранять плоскую структуру директорий. Никому не хочется лазать по 10-ти уровням вложенности. Вспомните навигацию на сайте, там уже более 2-х уровней вложенности уже считается дурным тоном и сильно уменьшает количество переходов.

Для разделения директории на поддиректории должен быть определенный порог. Скажем если у вас в одной директории появляется 7+ файлов, это уже может послужить поводом для того чтобы задуматься и разделить структуру с использованием поддиректорий.

Словом старайтесь не делать лишней вложенности если только в этом нет явной выгоды.

T-DRY

Старайтесь устранять дублирование кода, но не впадайте в крайности и не жертвуйте читабельностью кода.

В целом желание разработчика поDRYить может быть признаком преждевременной оптимизации. Зачастую благое намерение "убрать дублирование" порождает крайне неудобный в чтении и сопровождении код. Так же на ранних этапах жизни проекта похожие свиду вещи могут перестать быть таковыми в силу того что с этими вещами работают разные люди.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment