Никто давно не пытается выводить теорий о том как правильно писать код.
Старые теории и способы об этом думать в общественной дискуссии давно свелись к спору о синтаксическом сахаре да и теории те были попыткой выделения каких-то математических свойств кода. Потом как известно была доказана невозможность этого.
Сейчас всё изменилось - мы должны рассуждать о проекте как о том, что постоянно изменяется большими группами людей, какая-то часть и кода и людей может быть неправильной, никто из модифицирующих не знает проекта целиком, нужны новые идеи и способы рассуждения.
Положение дел сейчас
Многие рассуждают о проектах в терминах ООП, ФП или какой-то другой подобной концепции. Так что нужно начать с разбора этих воззрений.
Как сказано выше, эти теории никогда не пытались описывать современного вида проекты, они просто пытались математически представить программы и если немного приглядеться, все такие теории сводятся одна к другой.
Вкратце и упрощённо:
ООП = объекты обмениваются сигналами, на практике сводится к тому что есть объекты с изменяемым состоянием и методами
ФП = неизменяемые наборы данных, функции принимают наборы таких данных и возвращают наборы таких данных (да, вопреки заблуждениям это не любой код где есть функции, да и функции иногда не функции, а процедуры, но это тема других статей..)
Таким образом ООП это ФП в котором объект с методами представляется как набор данных с функциями, принимающими на вход объект и возвращающие модифицированный объект.
Это конечно утрировано, но в целом оно так и есть - одно сводится к другому, ведь описывают эти модели одно и то же.
А с точки зрения этой статьи - они не дают понимания о чём же действительно нужно думать при разработке, из них не следует прямых практических выводов
А что взамен?
Перед тем как рассуждать как писать программы нужно определится какие программы мы хотим писать
Так как мы обсуждаем архитектуру, сразу надо сказать что она имеет смысл только в достаточно больших, изменяющихся проектах. То есть если у вас 300 строк кода, которые вы никогда после написания менять не собираетесь - можете написать вообще как угодно, никакая архитектура там не нужна.
Отчасти поэтому архитектурные холивары в интернете на примере пары функций или одного типа с 2 методами бессмысленны.
А хотим за приемлемое время писать надёжный, поддерживаемый код в котором легко ориентироваться. Его должно быть легко понимать и менять.
Ну и как всем известно, если не придумать какой-то аббревиатуры, которая складывается в какое-то красивое слово, то подход на считается, так что я назвал это
S.L.O.N
Sustainable (поддерживаемый, устойчивый)
Logical (логичный)
Obvious (интуитивный)
Navigable (помогающий в ориентировании по нему)
аксиомы нашего SLON:
-
меньше сущностей и меньше взаимодействий в коде = легче понимание.
Программист создаёт работу себе сам, каждая новая сущность или связь в коде создаёт требование в будущем это поддерживать.
Зачастую это сводится к меньше кода и зависимостей = лучше. Смысл архитектуры в том, чтобы снизить влияние роста кодовой базы на увеличение затрат на изменения
-
люди ошибаются.
Почти все ошибки чисто логические: либо неверно было требование к коду, либо реализация.
Сегфолт или удалённая база данных это проявление ошибки, а не сама ошибка. Так что инструменты должны давать чётко переложить то что на уме программиста в то, что будет написано в коде. Чем чётче - тем легче будет не создать или обнаружить потом ошибку. А система должна быть не столько устойчива к ошибкам, сколько как можно раньше их обнаруживать.
Выводом из этого является более чёткое формулирование контрактов функций и их проверка по возможности, чтобы обнаружить нарушение
-
код читают другие люди (причём ты в будущем - это другой человек).
Из этого следует такое свойства кода как интуитивность: а интуиция и ход мышления у всех людей разный.
Человеку будет проще понять код, который написан человеком похожим на него, мыслящим похожим образом. Система построена логично (относительно читающего) и потому понятна.
следствие для инструментов разработки: что "больше способов написать одно и то же" это благо, если способы всё же разные, а не один строго лучше другого.
Это и есть выразительность кода, когда разные архитектурные приёмы записываются разными конструкциями и более узнаваемы при чтении кода
По сути это некая стандартизация, общий стиль архитектур. Причём отмечу - для разных задач нужна разная архитектура. И лишь для немногих задач есть устоявшиеся, годами наработанные архитектуры (компиляторы, операционные системы)
-
код можно переиспользовать.
Хорошо написанный инструмент или модуль можно потом использовать неограниченное количество раз. Плохой же каждый раз придётся переделывать под новый проект.
Следствия:
нужно понять какие инструменты будут нужны, хорошо их написать, документировать и потом применять, чтобы потом использовать многократно
нужно писать проект так, чтобы в нём можно было использовать уже написанные инструменты, например зачастую компании нарушают это правило ломая совместимость проекта с git, отладчиками или компиляторами, что выливается в большие затраты
Следствие для инструментов разработки:
Нужно либо давать инструменты под конкретную задачу, либо давать способы написать свои такие инструменты легко и удобно.
Языки общего назначения не могут предоставлять всё сразу, потому что их применяют в слишком разных областях, так что они должны давать способ создавать свои удобные инструменты на самом языке.
Какие вообще бывают проекты?
Есть разные виды проектов:
инструменты для создания инструментов, например сами языки программирования
инструменты для создания прикладных программ, например LLVM
прикладные проекты, в них есть код так называемой "бизнес логики". Пример: clang, компилятор созданный на основе LLVM
И даже clang это всего лишь инструмент для создания других проектов. Без всей этой инфраструктуры никакие прикладные продукты не были бы рентабельны.
Как без дороги было бы бессмысленно строить магазин, так и если для создания нейросети вам нужно написать свой Numpy - вы даже не начнёте.
На основании этого можно например можно учредить международную премию за лучший опенсорс проект или какую-то деталь инфраструктуры, такими деталями можно считать оплату по СБП, telegram или starlink
Для начала нужно хотя бы осознать важность IT инфраструктуры.
Важный факт для ведения проектов: конкретные требования и критерии оценки проекта существуют только для прикладных проектов.
Перед остальными проектами задачи стоят либо никак, либо "сделать хорошо", при этом их качество сильно важнее. Для этих проектов неприменимы обычные практики оценки работы или формулирования требований. А одним из самых распространённых таких направлений является devops, это чистое создание инфраструктуры без конечного продукта и соответственно привычных критериев оценки работы.
Как проекты развиваются?
На основании своего опыта я выделяю всего пару стадий разработки с точки зрения людей и того как меняется ими код
Сначала идёт создание инструментов для создания проекта. На этом этапе контрпродуктивно вводить много разработчиков в проект, потому что им ещё нечем "строить", а мешать они будут. Небольшая группа разработчиков создаёт инструменты и инфраструктуру, подготавливаются требования к проекту (например в виде интеграционных тестов)
Затем, когда инструменты готовы, начинается фаза активного изменения. Тут уже можно добавить много разработчиков и это не будет контрпродуктивно. Неустоявшиеся интерфейсы, бесконечные фиксы багов для соответствия требованиям.
Постепенно изменения стихают и проект переходит в стадию поддержки, когда команда разработчиков поменьше выявляет и чинит баги, поддерживает новые фичи.
Из того как развиваются проекты и первой аксиомы SLON следует всем известное правило, преждевременные оптимизации - зло. На стадии активного развития добавлять оптимизации, которые заставят тратить дополнительные усилия на их поддержку влечёт создание большого числа дополнительной работы
Послесловие
Главное что надо понять - нужная архитектура и используемые инструменты зависят от задачи и людей которые задачу выполняют.
Нет одного решения подходящего всем, но есть совсем немного основополагающих принципов, их я и попытался изложить в этой статье.
Человечеству только предстоит понять как работать в условиях, когда средством производства является человек, но точно не стоит пытаться свести разработку к заводу по производству стандартизованных строк кода, это точно не работает