Моника, имеющая опыт работы в финтех-компании в Берлине, обсуждает причины, по которым программное обеспечение переписывается, и признает, что здесь задействовано множество факторов. Она задает этот вопрос своей аудитории, прежде чем углубиться в свою тему масштабирования интерфейсной архитектуры для растущих и распределенных команд.
Автор рассказывает о своей первой работе в качестве студента-веб-мастера, где ему приходилось писать PHP и MySQL. Он унаследовал код от предыдущего веб-мастера, но не понял его, поэтому решил переписать его по неопытности и потому, что переписывать код - это весело. По его словам, основная причина, по которой программное обеспечение переписывается, - это технический долг.
Технический долг - это термин, используемый в разработке программного обеспечения для описания кода, инструментов или инфраструктуры, которые негативно влияют на скорость и качество доставки. Это может быть вызвано различными факторами, такими как старые библиотеки, неиспользуемые функции или неопытные методы кодирования. Повторяющийся технический долг может возникать, когда разработчики пытаются его исправить, но в конечном итоге откатываются назад из-за продолжающихся проблем.
Второй системный эффект относится к тенденции разработчиков чрезмерно усложнять новую систему при ее переписывании, что приводит к худшему результату, чем исходная. Реальная стоимость программного обеспечения заключается не в первоначальной разработке, а в обслуживании и адаптации с течением времени в связи с меняющимися требованиями и потребностями бизнеса.
Основное внимание следует уделять не тому, почему программное обеспечение нуждается в переписывании, а скорее тому, как мы можем сделать наши системы более устойчивыми к изменениям с помощью хорошей архитектуры. Однако люди могут негативно отреагировать, когда им расскажут об этом решении во времена плохой архитектуры, вызывающей проблемы.
Разработчики программного обеспечения часто рассматривают архитектуру как ругательное слово, потому что ему не хватает общего определения, и люди любят спорить о том, что оно на самом деле означает. Кроме того, большинство разработчиков считают, что обсуждения хорошей архитектуры кажутся оторванными от их повседневных проблем.
Идея архитектуры как разрешающих ограничений означает, что ограничения, накладываемые на код, использование данных и структуру приложения, могут помочь двигаться быстрее и безопаснее с течением времени. Автобан в Германии является примером того, как физические барьеры между автомобилями, движущимися на высокой скорости в разных направлениях, полосы движения и условности, такие как использование сигналов поворота, являются ограничениями, которые обеспечивают безопасное вождение даже без ограничения скорости.
Внедрение объектно-ориентированного программирования (ООП) ввело ограничения с точки зрения структурирования программ по классам, но это позволило отделить структуру от организации кода. Функциональное программирование вводит неизменяемость в качестве основного ограничения, которое устраняет проблемы, вызванные тем, что различные части приложений думают, что они владеют данными и могут их изменять.
Разработка интерфейса продвинулась вперед благодаря использованию "const" вместо "var", подходу React к прямым манипуляциям с DOM и CSS в JS, который заставляет разработчиков не полагаться на побочные эффекты и писать более дисциплинированный код.
Докладчик рассказывает о том, как разработчики часто ограничивают себя в целях безопасности и скорости, но это ограничивает их способность демонстрировать мощную разработку программного обеспечения. Они разделяют три конкретных ограничения, связанных с зависимостями исходного кода, границами компонентов и потоком данных, которые могут привести к созданию более устойчивой архитектуры во внешнем интерфейсе.
Организация внутренних зависимостей в приложении имеет решающее значение для того, чтобы избежать большой запутанной архитектуры, где трудно понять, что может сломаться при внесении изменений. Многоуровневый подход ограничивает площадь поверхности, которая может быть затронута, и уменьшает межкомандные конфликты. Создание новых модулей JavaScript не обязательно делает код модульным; микро-интерфейсы или моно-репозитории являются лучшими примерами модульности.
Ключевое различие между двумя подходами к организации внутренних зависимостей заключается в том, как компоненты приложения изолированы друг от друга. Каждая страница или раздел должны быть разделены и ничем не делиться с другими, чтобы избежать побочных эффектов, что облегчает изоляцию влияния изменений и делает приложение более устойчивым.
Автор подчеркивает важность совместного использования кода разработчиками и предлагает отделить бизнес-логику от систем проектирования. Они также рекомендуют проявлять осторожность при введении зависимостей между фрагментами кода, чтобы избежать потенциальных проблем с его повторным использованием в разных контекстах.
Разработчики любят сухой код и внедряют абстракции, чтобы сделать его более эффективным. Однако иногда во имя сухости фрагменты кода, которые не должны знать друг о друге, связываются вместе, что делает код хрупким и подверженным побочным эффектам. Это происходит, когда компоненты, хранящиеся в общей папке, начинают отклоняться от своего первоначального назначения из-за запросов на новые функции или бизнес-требований.
Цель сохранения кода сухим и несвязанным состоит в том, чтобы избежать ненужного внесения ошибок. Однако, если сухость связывает несвязанный код воедино, это сводит на нет преимущество, которое было достигнуто за счет того, что он был сухим в первую очередь.
Докладчик предлагает критически относиться к повторному использованию кода и избегать объединения кода, который со временем расходится. Они также подчеркивают важность применения архитектурных ограничений в приложениях, чтобы избежать систем, склонных к энтропии, и необходимости переписывать все заново.
Методика запрещенных тестов зависимостей позволяет протестировать структуру приложения с точки зрения зависимостей. Написание правил, которые выполняются как часть CI, может привести к сбою сборки, если кто-либо попытается зависеть от определенного кода, что помогает предотвратить нежелательные зависимости и дублирование в общей бизнес-логике.
Dependency Cruiser - это инструмент, который проверяет наличие зависимостей и циклических зависимостей в экосистеме node и JavaScript. Это позволяет автоматически сохранять архитектуру с течением времени, что приводит к уменьшению конфликтов.
В этой главе кратко излагаются основные идеи, обсуждавшиеся в предыдущих главах, включая необходимость изменений в программном обеспечении и то, как архитектура может обеспечить более быструю разработку. В нем также освещаются небольшие изменения, которые могут быть внесены в проекты, такие как установка правил для зависимостей и более консервативное использование кода повторно. Подчеркивается важность реализации благих намерений с помощью автоматизации, а также идея о том, что даже отдельные разработчики должны принимать архитектурные решения при создании объектов.