Обновить

Почему проекты превращаются в спагетти даже у хороших программистов

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели8.6K
Всего голосов 9: ↑7 и ↓2+7
Комментарии16

Комментарии 16

Вообще всё гораздо проще. Если кодер не архитектор, то он джун, хотя может притворяться кем угодно.

Это если есть внятные ТТ и ТЗ. А без них архитектура ХЗ как и всё остальное. Надо быть опытней менеджеров, чтобы предсказать, во что может превратиться система в итоге. Мидлам это обычно не под силу.

Вот, допустим, пишет такой человек для себя. Пет-проект. Есть у него в одиночку шанс написать приличное количество кода, чтобы это был не говнокод? Нет. Так о чем речь?

Речь о том, что требования к архитектуре разные в зависимости от размеров проекта. То, что начинается как проект на месяц причём делающийся одним человеком в сумасшедшей спешке, в итоге нередко вырастает в проект на 10 лет и 50 человек, которые участвуют в него в разное время. И за эти 10 лет успевает несколько раз радикально смениться аппаратная база и фреймворк. С пет-проектами ситуация иная - спешки нет, и автор изначально примерно представляет перспективы. А так приходится глубоко рефакторить, в том числе и архитектуру. Но полностью рефакторить проект удаётся очень редко, так что в итоге легаси хватает.

Ну предположим архитектура важна. А дальше то что? На этом вся статья? Ну я не знаю, ну написали бы как делать хорошо и не делать плохо. Можно с тем же успехом написать статьи что хорошая аналитика важна и хорошее тестирование, только положение дел это не особо изменит.

Ну если вы захотите я могу конкретные кейсы разложить...к сожалению...или может быть к счастью, опыта и реальных примеров хватает...если интерересно предложите тему или какой нибудь случай...вполне возможно он у меня на практике был...все таки более 26 лет в разработке

если интересно предложите тему или какой-нибудь случай…вполне возможно он у меня на практике был…все таки более 26 лет в разработке

Я могу рассказать о своём случае, но не уверен, что он вписывается в ваши интересы, поскольку, предпочитаю вею-программированию – десктопное.

У меня опубликована, здесь, первая версия обучающей, иностранным языкам, программы «L’école». Там, я слегка накосячил:

Структура первой версии обучающей программы «L'école»
Структура первой версии обучающей программы «L'école»

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

На первое место, в этом случае, выходит роль модулей либо автономных классов в С++. А также организация их в «правильную» иерархию. Затем выбор концепции программы и ее программной логики. Потом, разработка алгоритмов и их техническая реализация. Ну и плюс расширение возможностей программы по сравнению с первой версией.

Оказывается, что даже в этом простейшем случае, с архитектурой не все ясно. Ну, допустим, стал я «архитектором» и дали мне команду из нескольких программистов (нет, несколько – это мало, пусть их будет в два раза больше!). Какие указания я им должен раздать, чтобы «процесс пошёл»?

Понятно, что задача должна быть максимально «распараллелена», Но, для модульного программирования на С++ нет общепринятой методологии. У меня была здесь статья на эту тему, где я использовал динамические и статические плагины для параллельной разработки, однако, народ её воспринял в штыки. Наверное, если я напишу новую статью об архитектуре второй версии своей программы, реакция будет такой же. Ибо, как я понял, народ привык воспринимать модули на С++, примерно, как пакеты в Питоне. Но, ведь, вторую версию мне писать надо? – Надо! Оригинальность проявлять надо? – Надо, не надо, но вынужден, ибо другого пути построения новой версии программы – не вижу. Кстати, при создании её первого варианта, я себе чуть мозги не сломал, пока не добился её более-менее рабочего состояния.

Вот и размышляю, как «правильно» избежать превращения второй версии в очередные «макароны»? :)

Не расстраивайтесь...на С++ можно даже писать микросервисы...я 10 лет писал на С++ :) и ооп там вполне рулит.
На самом деле я бы на вашем месте сейчас не пытался сразу «изобрести идеальную архитектуру». Это ловушка, в которую очень легко попасть при написании второй версии :)

Судя по диаграмме, главная проблема у вас даже не в количестве файлов, а в плотности связей между ними. И это абсолютно типичная история

Поэтому я бы начал не с «идеальной иерархии», а с разделения системы на логические блоки с понятными границами.

Например:

  • UI

  • обучение/уроки

  • тестирование

  • мультимедиа

  • работа с БД

  • настройки

  • общие сервисы/утилиты

И даже если внутри блока пока останется своё маленькое «спагетти» — это уже будет гораздо лучше, чем одна большая общая кастрюля :)

Потому что хорошая архитектура — это не отсутствие хаоса. Это ограничение радиуса его распространения.

А дальше уже можно постепенно:

  • уменьшать связанность

  • вводить интерфейсы

  • убирать прямые зависимости

  • выносить общую логику

  • и приводить систему в порядок без тотального переписывания.

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

Не расстраивайтесь…на С++ можно даже писать микросервисы…

Вопрос только, нужно ли? Модули, в программе для ПК – я понимаю, сервисы – нет. Локальные сервисы в Windows – это те же (системные) службы, т.е., просто фоновые процессы. Или вы имеете в виду многопоточное программирование?

я 10 лет писал на С++ :) и ооп там вполне рулит.

Я в этом ни разу не сомневался, особенно, используя WTL.

Судя по диаграмме, главная проблема у вас даже не в количестве файлов, а в плотности связей между ними. И это абсолютно типичная история

Да, файлов там не много, проблема, действительно, в сильных связях. Я это объясняю наличием связей «многие ко многим». А, как мы знаем, из теории БД, их можно заменить связями: «многие к одному» и «один ко многим». Может быть, даже, удастся свести их, только, ко второй части данных отношений.

Поэтому я бы начал не с «идеальной иерархии», а с разделения системы на логические блоки с понятными границами. Например:

В терминах модулей, это будут:

  • Главный модуль (точка входа)

  • Класс приложения

  • Главное окно приложения

  • Обработчики главного окна приложения

  • Модули автономных классов, используемые в обработчиках

Там уже будет конкретная, иерархическая схема взаимодействия конкретных классов.

Потому что хорошая архитектура – это не отсутствие хаоса. Это ограничение радиуса его распространения.

Я предпочитаю простую вертикальную иерархию, без горизонтальных связей.

Кстати, вот скриншот первой версии программы, о которой мы говорим:

Простые озвученные фразы на английском языке, с переводами
Простые озвученные фразы на английском языке, с переводами

Но тогда зачем Вам мой совет. Вы вполне сами можете разрулить...
О сколько нам открытий чудных
Готовят просвещенья дух,
И опыт, сын ошибок трудных,
И гений, парадоксов друг

Я бы даже сказал больше. Совсем вычищать модули не нужно в принципе. Любая задача имеет некоторый неснижаемый уровень сложности. А это значит, что если вы сделаете идеальные простые маленькие классы, то перенесете сложность в их создание, координацию, передачу сигналов или ещё куда. Проще разбираться не станет. Нужно размазывать сложность равномерно.

Совсем вычищать модули не нужно в принципе. Любая задача имеет некоторый неснижаемый уровень сложности. А это значит, что если вы сделаете идеальные простые маленькие классы, то перенесете сложность в их создание, координацию, передачу сигналов или ещё куда. Проще разбираться не станет. Нужно размазывать сложность равномерно.

Очень спорное утверждение!

Все начинается с архитектуры. Архитектура должна быть простая или, хотя бы, обозримая и понятная. У меня, в первой версии, была ситуация: «бодался телёнок с дубом». В итоге, «телёнок» «дуб» «раздолбал», но ценой, своего «лба», который он чуть себе не расшиб.

Думаю, это не совсем правильный подход в программировании. Поэтому, менять надо всё. По крайней мере, не только переставлять «кровати», но и менять «обслуживающий персонал», в соответствующем «заведении».

Классы вполне могут быть «большими», особенно, если это классы WTL. Сделаны они, на редкость хорошо. И, хотя, их (открытый) код не превышает полутора мегабайт, менять там, что-либо, у меня, ни разу не возникло необходимости. Как по мне, WTL самодостаточен, и не нуждается, особо, в расширении либо модификации. Оставим этот путь для Qt.

Собственные классы, тоже могут быть не маленькими. Главное, чтобы они были максимально локализованы. Возникла проблема? Ага! Это в модуле «Х», начинаем его «шерстить». Смотрим логи, запускаем отладку и т.п… Находим проблему и исправляем ее. Более того, если нужно данный модуль отключить, то, просто заменяем его полную версию – формальной. Вызовы из него, в основной программе, останутся, но они ничего делать не будут.

Соответственно, наоборот. Архитектор делает прототип программы с формальными (пустыми) реализациями базовых функций классов. Задача программистов – исполнителей – заменить пустые реализации публичных функций в классах – их полными аналогами. Затем мы просто делаем подмену формальных модулей – реальными и, вуаля, сразу получаем дополнительный функционал в приложении. При этом, программисты могут, на свое усмотрение добавлять в «свои» модифицируемые классы приватные функции и приватные данные. Главное, они не должны менять интерфейс публичных функций и, может быть, публичных данных, определенный архитектором.

Также, можно менять одну вервию модуля на другую (путем простой подмены его файлов)

Таким образом, модули (автономные классы) в C++ / WTL – должны, как легко подключаться к приложению, так и легко отключаться, без модификации кода вызова их публичных функция в обработчиках приложения. Что также позволит, без проблем, менять одну версию модуля на другую.

Так что, сложность должна быть локальной и уходить вглубь, а не «размазываться равномерно».

На хабре без ллм вообще ни кто не пишет больше? Печалька. Хотя бы причесывали текст после.

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

Да экономическая целесообразность есть - если архитектуру закладывать изначально, опубликовать ее основы и иметь роль которая занимается отстреливанием всех, кто попытается ее нарушить. Иначе через пару лет нужна не оптимизация, а полная переработка ..... а нет даже написание проекта снова с нуля и вероятнее с таким же результатом. А если этот проект за пару лет успел распространится на пару тысяч пользователей, которые к нему привыкло и смирилось - то экономическая целесообразность выражается в необходимости содержания команды поддержки в несколько сотен человек. Честно говоря видел такой проект. Бедствие полное.

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

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации