TL;DR: Предметка. Потому что пишем приложение по предметке, а не набрасываем технологию на предметку. Грустно, но факт.

Как разделить сырцы

Данный вопрос поднимается, когда архитектура приложения получается в виде переплетения двух совершенно разных массивов: объектов предметной области и абстракций реализации. К примеру, у меня есть сейчас сущности предметной области:

  • Событие
  • Юзер
  • Участник(он же Юзер)
  • Шаблон события
  • Клуб событий(участие по умолчанию)

С другой стороны, есть технология и ее фишечки:

  • Routes
  • Handlers
  • DB-function
  • Validation

Тут связь получается p2p. Каждому событию/юзеру/etc нужен роут. На каждый роут вешается хандлер, который собственно просто вызывает слой БД. “Просто” в данном случае фальшивое. Надо проверить что входные параметры реально могут быть обработаны: указанное событие есть, юзер тоже числится, баланс у него в достатке и т.д. Все это ведет к тому, что начинают появляться все абстракции технологии для каждой сущности. И сразу встрает вопрос: кто сверху?

+ root
    +-event
        +-route
        +-handler
        +-validator
    +-user
        +-route
        +-handler
        +-validator
    +-club
        +-route
        +-handler
        +-validator

или же

+ root
    +-route
        +-event
        +-user
        +-club
    +-handler
        +-event
        +-user
        +-club
    +-validator
        +-event
        +-user
        +-club

Вроде бы разницы особо нет, по количеству одно и то же.

Как мы правим код

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

Reuse and DRY

Какая часть предметной области может внезапно стать частью нового проекта. Можно возразить, что есть всякие компоненты интерфейса, базовые функции, паттерны взаимодействия. Да, но это уже в некотором роде своя предметка, поэтому их надо выделять особняком в какой-нибудь utils(шутка, здесь тоже надо подходить с умом).


Т.о. лучше держать исходники, разделенные по предметке. Общие же функции/классы(совсем общие) необходимо выделать и прятать в отдельную нишу.