Comments 32
Очень интересная статья. Думаю, что стоит потратить время на ее усвоение.
В своем последнем пет-проекте ( https://habr.com/ru/articles/848836/ ) я тоже столкнулся с проблемами хорошего структурирования кода. Как в части организации графического интерфейса, так и на уровне алгоритмов работы с данными. Неимоверными усилиями (в результате чего, пришлось даже полностью бросить пить) я вышел на первую рабочую версию, которая, естественно, не может быть идеальной. Поэтому, при разработке следующих версий, надеюсь, воспользоваться вашими советами по эффективной организации кода, но, сначала, ваши идеи еще надо переварить.
Идеально было бы, если бы вы предоставили тестовый проект на Visual Studio C++, с использованием GUI. Для меня лично, лучший способ усвоения новых идей – работа с самодостаточными прототипами кода. Но я не настаиваю, понимаю, что у вас есть свои планы на использование вашего личного времени.
В любом случае, за статью – спасибо!
Статья отличная.
Есть некоторая проблема воспроизводимости во многих материалах по архитектуре ПО.
Она состоит в том, что многие подходы и знания, являющиеся исходными для общепринятых решений, таких как ООП, паттерны, чистые функции и т.д считаются самоочевидными.
Вместе с тем, они, во первых, неочевидны, а во вторых, это создает разрыв между самими правилами и условиями при которых их нужно применять.
Получается культ-карго, когда нужно применять подход просто потому что нужно.
Жалко, что не очень много пояснений про иерархии и декомпозиции более сложных решений, если наш слой приложения становится слишком сложный, или, к примеру, основная сложность состоит в структурировании объектов слоя обработки. Например игры - приложения с полным стейтом, где сохранять нужно сравнительно немного по сравнению с тем, сколько нужно организовывать объектов для игровой симуляции.
Есть некоторая проблема воспроизводимости во многих материалах по архитектуре ПО.
...
Например игры
Я к геймдеву вообще никакого отношения не имею, поэтому возможно фигню сморожу, но у меня такое мнение - львиная доля информации по архитектуре (включая мой доклад/статью), посвящена архитектуре (бакэндов) информационных систем. А "естество" бакенда сильно отличается от "естества" игры и поэтому эта информация плохо ложится на реалии разработки игр.
Жалко, что не очень много пояснений про иерархии и декомпозиции более сложных решений
Опять же, для бэков у меня есть решение. Актуальную версию пока не расписал, но она базируется на алгоритме декомпозиции на базе эффектов (это тоже статья по мотивам доклада и этот доклад уже есть в публичном доступе на Ютубе).
Именно так, именно поэтому зачастую функциональщики не понимают игрожелов и бездумный перенос опыта оканчивается плачевно.
Ну, мы тоже пишем сервера)
Ещё, кстати, мысль дилетанта - а оно (архитектура) вам вообще надо?:)
Бакендеры заморачиваются, потому что бакэнды живут годами и десятилетиями. И покопавшись в говне мамонта невольно начинаешь задумываться о том, чтобы в следующий раз позаботиться о себе и сделать понятную и поддерживаемую кодовую базу.
А игры, кажется - максимально быстро запилил, зарелизал и ещё до релиза забыл про первую игру и начал пилить вторую.
Раз существует https://en.wikipedia.org/wiki/Entity_component_system, значит иногда приходится поддерживать. Плюс одна игра сама может превратиться в такого мамонта, что до релиза не доживёт
Игры тоже поддерживаются десятилетиями, WoW 20 лет вот недавно встретил.
Плюс многие бывают довольно массивными, их пилят десятки людей.
Многие игры довольно сложны, для сети нужны архитектуры для детерминированных симуляций к примеру.
По сути даже если ты не задумываешься об архитектуре - какая то архитектура все равно есть, сами какие то связи появляются.
В целом если ты один пилишь игру можно действительно почти не париться - плюс многие движки предоставляют мощный фреймворк, который навязывает как минимум какие то основы организации.
Жалко, что не очень много пояснений про иерархии и декомпозиции более сложных решений, если наш слой приложения становится слишком сложный, или, к примеру, основная сложность состоит в структурировании объектов слоя обработки. Например игры - приложения с полным стейтом, где сохранять нужно сравнительно немного по сравнению с тем, сколько нужно организовывать объектов для игровой симуляции.
Я хотя и не программирую игры, но подумал, что ваши проблемы мне ближе, чем у «функциональщиков-бакендеров», наверное, просто потому, что мы больше ориентированы на десктопные программы, чем на веб-сервисы.
Что касается структурных схем автора, то наиболее важные идеи, на мой взгляд, демонстрируются не специфическим кодом, а, именно, принципами. Вроде: «Разделяй и властвуй!», «Хочешь мира – готовься к войне!» и т.п. У автора, главная мысль это: «Идея предельно проста: при разработке код надо разделять на четыре типа — управляющий код, код чтения данных, код трансформации и код записи данных.». Я бы даже сказал «гениально проста».
Однако, если рассмотреть еще более предельный случай, вроде «сферического коня в вакууме», то два варианта из четырех можно смело отбросить, без потери смысла. А именно – ввод и вывод. Тогда останутся «управляющий код» и «код трансформации». Другими словами, мы рассматриваем потенциально сложную программу, но, которая ничего не читает и ничего не записывает.
Вот здесь и «зарыта собака». И вы, и я хотели бы больше «пояснений» по этим моментам. Но, единственное, что я понял из схем автора, так это то, что надо избегать, по максимуму, горизонтальных структурных связей за счет объединения соответствующих блоков кода.
Если рассмотреть «управляющий код», то, в ОС семейства Windows, это обычное управление событиями, которое в С++ очень хорошо реализовано в минималистском фреймворке WTL. Ну, а «код трансформации» реализуется в обработчиках этих событий.
Однако, при этом становиться понятно, что такой уровень пояснений явно недостаточен, для структурирования сложного кода и алгоритмов. В чем я лично убедился при реализации своего пет-проекта ( https://habr.com/ru/articles/848836/ ). Там я вообще столкнулся с новой для себя концепцией, которую условно назвал «матричным алгоритмом», осмысление которого мне еще предстоит.
Таким образом, вопросы «правильного» структурирования сложного кода и алгоритмов остаются открытыми.
надо избегать, по максимуму, горизонтальных структурных связей за счет объединения соответствующих блоков кода
Автор статьи поднял достаточно актуальную тему, от которой трудно отмахнуться.
То, что он говорит о разделении основных сущностей алгоритма, это – бесспорно. Однако он упоминает термин «сбалансированность», который, как кажется, несколько притянут за уши. Похоже, что важна не столько «сбалансированность» ветвей дерева основного алгоритма, сколько отсутствие, либо минимизация в нем горизонтальных связей. Хотя, более точно, сформулировать эту идею можно так:
Количество путей, соединяющих любые два узла оптимального алгоритма, должно быть минимальным.
В рассуждения выше, упоминалось, что отсутствие ввода / вывода в программе, не ограничивает смысл рассуждений по оптимизации алгоритмов, но упрощает их. Более того, можно пойти еще дальше и объединить вместе «управляющий код» и «код трансформации».
Дело в том, что между ними нет принципиальной разницы. Любое управление в программе это реакция на внешнее событие, неважно, вызванное ОС либо пользователем. А эту реакцию реализует обработчик события. Т.е., эти два понятия абсолютно взаимосвязаны, одно не имеет смысла без другого и реализуются всегда вместе.
Так что мы, в итоге, имеем? – Множество обработчиков событий! Поэтому, при оптимизации алгоритмов, нужно вести речь о взаимоотношениях этих обработчиков между собой. Думаю, здесь и кроется вся сложность алгоритмов. Именно, в наличии избыточных связей между этими обработчиками либо объектами, к которым они имеют доступ. Иначе говоря, состояние одного объекта может изменяться разными способами, что нарушает принцип единственной ответственности.
В своих комментариях, я не раз упоминал о сложности одного используемого алгоритма, в своей обучающей программе, и даже условно назвал его «матричным». Так вот, я посмотрел на блок-схемы этого алгоритма другими глазами и, естественно, увидел, что это просто «дерево» с большим количеством горизонтальных связей. Вот она сложность, в чистом виде, с которой пришлось много и долго бороться.
Сейчас я решил взять, для примера, произвольный проект на С++ и попробовать использовать там принцип минимизации горизонтальных связей в ключевом алгоритме. Посмотрим, что из этого получится…
Однако он упоминает термин «сбалансированность», который, как кажется, несколько притянут за уши.
В оригинальных книгах речь не о сбалансированной форме дерева, а о балансе уровня абстракции основных ветвей.

Перевод:
Хилая афферентная или эфферентная часть структурной схемы часто является признаком дисбаланса. Но я должен подчеркнуть, что баланс - это не визуальная характеристика. Система сбалансирована тогда и только тогда, когда она имеет дело с логическими данными, находящимися на ее вершине. Сбалансированные системы могут выглядеть — и часто выглядят — довольно асимметрично. Форма структурной схемы определяется задачей, а не эстетическими соображениями.
Так что мы, в итоге, имеем? – Множество обработчиков событий! Поэтому, при оптимизации алгоритмов, нужно вести речь о взаимоотношениях этих обработчиков между собой. Думаю, здесь и кроется вся сложность алгоритмов. Именно, в наличии избыточных связей между этими обработчиками либо объектами, к которым они имеют доступ. Иначе говоря, состояние одного объекта может изменяться разными способами, что нарушает принцип единственной ответственности.
Тут вам, возможно, будет интересен другой мой доклад - Рациональный подход к декомпозиции систем на модули или микросервисы. Я там как раз рассказываю о своём подходе к декомпозиции системы на минимально сцепленные модули-объекты. Правда я сейчас отказался от него:)
Но я должен подчеркнуть, что баланс - это не визуальная характеристика. Система сбалансирована тогда и только тогда, когда она имеет дело с логическими данными, находящимися на ее вершине.
Здесь я вполне согласен. Только, тогда, «баланс» не слишком удачный термин. Лучше уж говорить об оптимальности алгоритма.
Тут вам, возможно, будет интересен другой мой доклад - Рациональный подход к декомпозиции систем на модули или микросервисы. Я там как раз рассказываю о своём подходе к декомпозиции системы на минимально сцепленные модули-объекты. Правда я сейчас отказался от него:)
Я посмотрел ваше видео. Только его тяжело воспринимать из-за низкого качества звука. Идеальный звук, на мой взгляд в видеоуроках @lhexagoneplus на Ютубе ( https://www.youtube.com/watch?v=_Jf1wBEim2c ).
Я, кстати, тоже занимался декомпозицией кода на независимые модули (см. мою статью «Модульное программирование в C++. Статические и динамические плагины» – https://habr.com/ru/articles/566864/ ). Хотя, вы, конечно, имели в виду «другое». Но, я хотел бы здесь больше акцентировать внимание на форму подачи материала. Думаю, что понять суть предлагаемого метода можно почти мгновенно, благодаря визуальному демо-примеру. Согласиться с ним или нет, уже не так важно, как говорится: «Лучше один раз потрогать, чем сто раз увидеть!», ой, не так: «Один раз увидеть, что сто раз услышать!».
Что касается структурных схем автора, то наиболее важные идеи, на мой взгляд, демонстрируются не специфическим кодом, а, именно, принципами.
Да это так, но тут сильно повлияла специфика Joker - там ПК очень любит "мясцо"
Вот здесь и «зарыта собака». И вы, и я хотели бы больше «пояснений» по этим моментам. Но, единственное, что я понял из схем автора, так это то, что надо избегать, по максимуму, горизонтальных структурных связей за счет объединения соответствующих блоков кода.
Написать гайдлайн по проектированию кода трансформаций я тоже собираюсь. Пока что планирую взять за основу Stratified Design. Он хорошо расписан в книге Grokking Simplicity и есть доклад на эту тему от автора книги (сам не смотрел ещё)
Написать гайдлайн по проектированию кода трансформаций я тоже собираюсь. Пока что планирую взять за основу Stratified Design. Он хорошо расписан в книге Grokking Simplicity и есть доклад на эту тему от автора книги (сам не смотрел ещё)
Это, конечно, хорошо, но, уверен, важную часть своего дела вы уже сделали. Т.е., запустили процесс осмысления структурной оптимизации кода. Этого уже достаточно для самостоятельного развития излагаемых вами идей.
Так, лично я, получил мотивацию вернуться к программированию на С++ (сейчас, в основном, занимался скриптами на Питоне для подготовки данных к своей обучающей программе). Идеи, которые возникли из дискуссий здесь, у меня такие:
Излагаемые методы должны быть достаточно универсальными, т.е., быть шире потребностей рассматриваемых задач. Чтобы они были применимы и в веб-дизайне и в программировании игр на ПК.
«Управляющий код», в парадигме С++, это управляющий класс, основу которого составляют цикл обработки событий и обработчики событий.
«Код трансформации» это, на мой взгляд, не самодостаточный термин. Лучше, думаю, говорить об иерархии классов, моделирующих некий виртуальный мир. Например, игровой мир для разработчиков игр либо другие объекты отображения на устройствах вывода компьютера.
Обработчики событий создают и удаляют объекты классов виртуального мира и вызывают их методы (функции).
Сложность программирования заключается в наличии сильных (иерархических) связей (и, соответственно, трудно устранимых) как между объектами классов виртуального мира, так и внутриклассовых отношений между их структурами данных.
Упрощение связей между объектами классов следует искать в их оптимальной структуре. Но, как это делать – отдельный вопрос.
На первое место в оптимизации кода выходит оптимизация используемых моделей.
Интересно, что мы невольно пришли у себя на проекте к такой же архитектуре, только двигаясь из классического DDD. Мы объявляем агрегат (но это агрегат не в терминологии Эванса, а как раз комбинация сущностей, что-то вроде вашего AssignData
), собираем его за один запрос целиком в слое инфраструктуры, а сам он при этом выполняет свою бизнес-логику независимо от IO. Широко используется сокрытие в рамках одной сборки (модификатор internal
в C#, на котором мы пишем), чтобы слою приложения вообще нельзя было сломать логику.
В вашем случае, например, в примере с Barcoder слой приложения может не проверить единственность одной из коробок, и тогда Domain-слой сработает неправильно. Как мы делали мы. Вообще, паковать одну коробку в несколько и несколько в одну выглядит разными бизнес-операциями. Но если нужно в одной, то:
Domain:
public class BoxesAggregate
{
public IReadOnlyList<Box> Boxes { get; private set; }
public IReadOnlyList<OsgBox> OsgBoxes { get; private set; }
public BoxesAggregate(List<Box> boxes, List<OsgBox> osgBoxes) {
if (boxes == null || osgBoxes == null || (boxes.Count > 1 && osgBoxes.Count > 1))
{
throw new Exception("Перепаковать можно только одну во много или наоборот");
}
Boxes = boxes.AsReadOnly();
OsgBoxes = osgBoxes.AsReadOnly();
}
public void Repack()
{
if (boxes.Count == 1)
{
// код перепаковки 1
}
else
{
// код перепаковки 2
}
}
public (List<BoxId>, List<OsgBoxId>) GetIds()
{
// возвращаем идентификаторы коробок для связывания в слое приложения
}
}
Application:
public interface IAggregateRepo
{
public BoxesAggregate BuildFor(List<BoxId> boxIds, List<OsgBoxId> osgBoxIds);
}
public class RepackBoxesAppService(
IAggregateRepo agRepo,
IBoxRepo boxRepo,
IOsgBoxRepo osgBoxRepo,
ILinkRepo linkRepo
)
{
public void Handle(RepackBoxesRequest request)
{
// разумеется всё это одна транзакция, и никакие данные не сохранятся частично
BoxesAggregate aggregate = agRepo.BuildFor(request.BoxIds, request.OsgBoxIds);
aggregate.Repack();
boxRepo.SaveChanges(aggregate.Boxes);
osgBoxRepo.SaveChanges(aggregate.OsgBoxes);
linkRepo.UpdateLinks(aggregate.GetIds());
}
}
Infrastructure:
public class AggregateRepo : IAggregateRepo
{
// реализация сборки агрегата путём запроса сразу всех коробок и коробов,
// и затем вызова конструктора BoxesAggregate
}
Таким образом, почти никакие манипуляции из слоя приложения не сломают данные и не смогут обойти ограничения в бизнес-логике.
Вообще, паковать одну коробку в несколько и несколько в одну выглядит разными бизнес-операциями
Да, согласен, но когда реально делали проект я этот момент упустил (видимо и правда был с похмелья:) ), а сейчас хотелось оставить код максимально приближенным к реальному.
А за BoxesAggregate - спасибо. Вы, кажется, наконец-то мне объяснили идею "по агрегату на запрос", которую я полгода правильно понять не мог и из-за этого отвергал. Сейчас она заиграла для меня новыми красками, возможно утащу к себе.
Очень помогает в этом подходе то, что API отдельных сущностей может быть более свободным, но закрытым для использования вне домена. Грубо говоря, часто в энтерпрайзе кейсы типа: "отправить письмо можно только тогда, когда к нему приложен документ в статусе Согласовано". Тогда собираем агрегат из письма и документа, в самом письме метод отправки делаем internal (в джаве это package private, вроде как), а публичный метод отправки остается только у агрегата.
Поправьте меня, если я неправ, но похоже в этой секции нарушены границы транзакционности:
boxRepo.SaveChanges(aggregate.Boxes);
osgBoxRepo.SaveChanges(aggregate.OsgBoxes);
linkRepo.UpdateLinks(aggregate.GetIds());
Первое. Что произойдет в случае, если
boxRepo.SaveChanges(aggregate.Boxes);
выполнится успешно, а последующие инструкции провалятся (недоступность сети, системные прерывания и тд)?
Второе. Подход с выделением частичного агрегата или композиция сущностей разных агрегатов в один для проведения бизнес операции небезопасна, т.к. этот подход не учитывает конкуретность записи. Если вы беспокоитесь о целостности агрегата, он должен быть полностью гидрирован, версионирован и должна быть применены принципы оптимистичной конкуренции.
В противном случае вы не можете гарантировать целостность агрегата, что в свою очередь ведет к тому, что вы не можете гарантировать корректность и целостность данных в системе.
Что думаете по этому поводу?
Идея структурного дизайна конечно имеет право на жизнь. Но это всё покрывает только примитивные программы, типа CRUD (хоть с тысячей ручек), где самая главная проблема - это отделить io, чтобы проще писать тесты. Что делать с программами, где появляются очень большая вариативность (тот же пример "Охота на хампуса" из "Чистой архитектуры"), что от чего должно зависеть, чтобы программа была расширяемая - на все эти вопросы этот подход ответа на даёт. DDD и Чистая архитектура, были представлены существенно позже Structured Design и они пытались дать ответы для более масштабных программ. Просто ли применять более сложные подходы - нет, и в этом я соглашусь с автором. Но это совсем не значит, что нужно скатываться в такой примитивизм из 60ых годов вне зависимости от задачи.
Но это всё покрывает только примитивные программы, типа CRUD
Я правильно понимаю, что второй кейс с функцией назначения водителя вы тоже занесли в "примитивные программы, типа CRUD"?
В таком случае да, СД покрывает только их.
Но тогда боже упаси меня писать то, что вы называете сложными программами:)
Что делать с "Охота на хампуса" из "Чистой архитектуры")
Не заниматься ерундой делать оверинжиниринг, как пацаны из третьего кейса:
Не выдумывать, что у вас будет ввод и из консоли, и из смс и вы всё это будете разруливать в одной кодовой базе. Сделайте бэк с игрой, смс-шлюз который дёргает бэк и настольное приложение которое дёргает бэк
Переводы команд на разные языки вынесите в ресурсы. Соответственно, когда приходит команда - идёте в файлик с ресурсами и получаете каноничное имя
Возьмите РСУБД (на такую игру - точно хватит) и храните данные только там. Следите за тем, чтобы это решение не текло через АПИ кода, хранящего состояние игры
Безусловно, бывают случаи, когда есть вариативность в технологиях - тогда вводите интерфейс между кодом управления и кодом реализации io и всё.
Но вообще, см. коммент выше - в докладе и статье я держал в уме разработку бэков информационных систем. Разработка игр, как и фронта, как и АСУТП, как и встроенного софта - имеют свою специфику и не факт, что идея сбалансированной формы там применима.
По-моему, те кто так сильно ратуют за функциональное программирование противопоставляя его объектно-ориентированному подходу, лукавят. ООП никуда из их программ не девается - просто внутри ООП кода вставляются куски кода, написанного функциональным способом. Если попытаться абсолютно всё перенести в функциональную парадигму (то есть, отказаться от всех фишек ООП - объектов, полиморфизма, наследования и т.п.), начиная с гуёв и заканчивая бизнес-логикой и сервисным кодом - создать более-менее управляемое и, при этом, достаточно сложное, приложение будет невозможно... ООП - это же не способ программирования или написания кода. Это способ проектирования, метод борьбы со сложностью задачи.
Сам проект, причины и ход его реинжиниринга, а также методика получения цифр для оценки результатов приведены у меня в отдельных постах — если интересно, то можно покопаться. Здесь же приведу только выжимку.
В этом фрагменте ссылки ведут куда-то на localhost
Спасибо, поправил, на всякий случай продублирую:
3 не открывается, в серии не хватает примера кода на который был заменен sql. Ну и судить о каких то идеях на основе того кода который был до, ошибка. И что такое ПП ?
3 не открывается
Блин, это я уже после правок поворошил блог и опять линку сломал 🤦♂️ снова поправил
в серии не хватает примера кода на который был заменен sql. Ну и судить о каких то идеях на основе того кода который был до, ошибка.
О каких именно sql-е и идеях вы говорите?
И что такое ПП ?
Процедурное программирование. Я так называю подход, когда классы сущностей (данных) изменяемые и имеют только геттеры/сеттеры, а вся логика - в сервисах/юзкейсах
Ну так себе идея. И без этого понятно что энергозатратные операции надо обьединять поэтому сиранно что понядобилось двадцать лет чтобы понять это. Так вы скоро поймете что нехрен пихать в бд бизнес логику. Скажу в стиле гуру: в бд надо держать то что требует агрегации типа count, group и тд , т.е. они для анализа а не оперативной работы. А если вся работа это тысячу заказов обработать то уж можно выделить для этого мегабайт памяти а не дрючить бд. А еще еще эффективнее непрерывно заранее вычислять
Еще мудрая мысль из сис анализа: любой принцип хорош если применяется везде.
То что описано в книге это типичный процесс работы программ в то время в стиле батч заданий: есть данные на бобинах, их надо считать, пред обработать и подать основному обработчику а в конце записать результат.
Имхо, решение всех ваших проблем очень простое - нужно запретить читать и записывать по одной записи. Только пакетом. И сразу всё логика выстроится правильно, и программы будут работать быстро.
Спасибо за статью.
Есть ли у такого подхода (балансировка, 4 категории кода) какие-нибудь преимущества перед более простым "Functional Core, Imperative Shell"?
PS. Не так давно у Кента Бека был доклад с упоминанием книги "Structured Design" https://www.youtube.com/watch?v=yBEcq23OgB4
Есть такая поговорка "Со своим уставом в чужой монастырь не приходят", отсюда полезность любых подходов к кодированию может быть только в разрезе PET-проектов, собственной разработки (в том числе коммерческой) или, если вы себя уже зарекомендовали как определенный специалист и вам платят за реорганизацию проекта. В остальных случаях вы работаете на кого-то, кто вам и скажет как нужно писать код, и поддерживать в голове 38 стандартов и еще искать какой-то лучший из них - ну это такое себе (вы же понимаете что никто не оценит?).
И главное - не ясна сама цель. Красота ради красоты? Ну пишите вы свою часть таким способом, а еще 80% проекта пишется другими людьми, и если проект имеет проблемы не в вашей части кода и вы от неё отвязаны, то как бы и не жалко, а если вы связаны, то будет конфликт и не факт что руководство будет на вашей стороне. А вы уверены что найдутся специалисты могущие поддерживать такой стиль кодирования чтобы у вас сложилась команда? Вот придёте вы ко мне в команду - будьте уверены что я вам не разрешу так писать код и не важно насколько это правильно и согласуется ли с вашим внутренним миром.
Так же не ясно как отразится ваш подход на производительности, я люблю highload задачи и там писать приходится всё самому, без использования библиотечных реализаций и чаще всего в unsafe, что в общем-то логично. Или вы исповедуете принцип - если мой чудесный код просит минимум 64 Гб ОЗУ то их нужно купить? А что мне делать, как руководителю проекта если рядом есть прыщавый мальчик пишущий такое же ПО которому хватает 2 Гб ОЗУ? Ну да, у него всё не по феншую, но кто сказал что для того чтобы что-то продать нужно и писать только определенным образом?
Есть такая поговорка "Со своим уставом в чужой монастырь не приходят", отсюда полезность любых подходов к кодированию может быть только в разрезе PET-проектов, собственной разработки (в том числе коммерческой) или, если вы себя уже зарекомендовали как определенный специалист и вам платят за реорганизацию проекта.
Да, это правда. В моём случае так и есть - последние 4 года я либо делаю проекты с нуля, либо реорганизую их.
В остальных случаях вы работаете на кого-то, кто вам и скажет как нужно писать код, и поддерживать в голове 38 стандартов и еще искать какой-то лучший из них - ну это такое себе (вы же понимаете что никто не оценит?).
В этом случае, имхо, надо держать в голове только два стандарта - тот за который платят прямо сейчас, и тот, за который вы хотите чтобы вам платили:)
И главное - не ясна сама цель. Красота ради красоты?
Цель для меня - психологическое благополучие - у меня низкая стрессоустойчивость, поэтому в условиях горящих сроков и критов на проде мне жить некомфортно. А цель для бизнеса - минимизация суммарной стоимости владения продуктом. Структурный дизайн - это часть моего комплексного подхода к разработке бакендов. И опыт показывает что на горизонте от 6 месяцев работы этот подход позволяет снижать трудозатраты на разработку, в том числе за счёт снижения количества багов.
А вы уверены что найдутся специалисты могущие поддерживать такой стиль кодирования чтобы у вас сложилась команда?
Нет, это действительно проблема и я её решаю описывая свой подход и рассказывая про него. Но опять же опыт показывает, что даже джуны за 2-3 месяца могут понять как писать такой код и потом их надо только на ревью минимально контролировать.
Вот придёте вы ко мне в команду - будьте уверены что я вам не разрешу так писать код и не важно насколько это правильно и согласуется ли с вашим внутренним миром.
Значит у вас всё хорошо со скоростью и качеством разработки:)
Так же не ясно как отразится ваш подход на производительности
Если вы любите хайлоад, то лучше меня знаете, что все оптимизации делаются на основе конкретных цифр, конкретного кода. Поэтому в общем случае и правда не ясно.
Конкретно в моей практике нехайлоада (там где вопрос производительности вообще возникает) производительность только улучшается, так как в 100 случаях из 100 она упирается в неэффективную работу с БД.
ну то есть речь про какие-то узкие кейсы, а не про разработку в целом. Из вашей статьи это не звучит. Например я за >30 лет с БД вообще никогда не работал кроме каких-то собственных мелких проектов, но там и код совсем иначе пишется.
просто подобных статей много, и всегда звучит лозунг о чем-то общем, хорошем (лучшем) и для всего. Но я абсолютно уверен что любоу код зависит от контекста, а значит нет универсального способа "хорошего" кодирования.
Структурный дизайн. Древний секрет простого и быстрого кода