Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
В процессе развития даже простое объектно-ориентированное приложение может стать сложным. Каждый новый класс, метод или функция добавляет новые состояния и абстракции, которыми нужно управлять, увеличивает время, необходимое на распутывание ранее написанного кода. Чтобы сохранить кодовую базу простой, нужны конкретные знания и умения. И вы их получите! Изучите практические принципы проектирования, помогающие сохранять простоту объектно-ориентированной кодовой базы по мере ее развития. Написанная в виде сборника практических приемов, которые можно применять в любом объектно-ориентированном языке, книга предлагает советы по организации кода, управлению зависимостями и модулями и проектированию гибких абстракций. Информативные иллюстрации, практические примеры и упражнения помогут вам быстрее запомнить описываемые принципы.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 189
Veröffentlichungsjahr: 2025
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Маурисио Аниче
Простое объектно-ориентированное проектирование: чистый и гибкий код. — СПб.: Питер, 2024.
ISBN 978-5-4461-4199-9
© ООО Издательство "Питер", 2024
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Лауре, Томасу, Боно и Дюку, моей прекрасной семье и команде
Зачем писать еще одну книгу по объектно-ориентированному проектированию (ООП), если их и без того много? Именно на этот вопрос я должен был ответить себе, прежде чем приступить к реализации данного проекта.
Разработчики уже обладают обширными знаниями об ООП, почерпнутыми из ранних работ Дэйва Парнаса, книг Гради Буча по UML и объектно-ориентированному анализу, а также книги Эрика Эванса о предметно-ориентированном проектировании. Но ООП — не просто чисто инженерная задача; оно перерастает в искусство. Никакая заданная последовательность шагов не приведет к оптимальному проекту. Объектно-ориентированное проектирование требует творческого подхода.
В этой книге объектно-ориентированное проектирование рассматривается с двух конкретных точек зрения: как предотвратить резкое увеличение сложности системы и как получить «достаточно хорошую» архитектуру.
Во-первых, бо́льшая часть деятельности разработчика связана с сопровождением и развитием существующих систем. К сожалению, при отсутствии должного внимания каждое изменение, внесенное в информационную систему, приводит к тому, что она усложняется, даже если изначально была хорошо спроектирована. Поэтому в данной книге большое внимание уделяется тому, как бороться с естественным увеличением сложности.
Во-вторых, чаще всего у вас изначально мало знаний о том, что вы разрабатываете. Несмотря на все ваши усилия, ваш первый проект может оказаться неудачным. Однако это вполне допустимо, если вы создадите достаточно хороший проект. Цель данной книги — не научить вас всегда стремиться к идеальному варианту, а дать возможность реализовывать хорошие проекты, которые позволят вам эффективно создавать программное обеспечение.
Если вы знакомы с литературой по объектно-ориентированному проектированию, то узнаете многие из представленных здесь принципов. Мои взгляды на хорошее моделирование сформировались в основном под влиянием существующих работ. Однако я привнес в эти идеи и нечто свое. Я надеюсь, что книга будет полезна даже опытным разработчикам.
Приятного чтения!
Во-первых, я хочу поблагодарить доктора Исмара Франго Сильвейру. В 2004 году я учился на бакалавра, и Исмар был преподавателем моего первого профессионального курса по объектно-ориентированному проектированию. Этот курс стал для меня открытием. С тех пор я неустанно совершенствую свои навыки, но уроки Исмара стали фундаментом. Мы общались в последний раз много лет назад, но я никогда не забывал о его вкладе в мою карьеру.
Я также хотел бы поблагодарить Альберто Соузу. Он один из моих лучших друзей и при этом тоже любит чистый код, как и я. Мы живем на разных берегах одного океана, но все равно находим способы общаться и обсуждать не только жизненные вопросы, но и разработку ПО. Наши беседы всегда поддерживают меня в тонусе, и на многие мои мысли о проектировании классов повлияла его точка зрения.
Хочу выразить свою благодарность Тони Арритоле, редактору отдела развития в Manning. Она была отличным партнером в этом путешествии, предлагая множество ценных идей, внимательно слушая меня и подбадривая всякий раз, когда у меня заканчивались силы. Я также должен поблагодарить Маттиаса Нобака, тренера и консультанта из Noback’s Office, который был научным редактором этой книги. Он сделал много ценных замечаний, которые оказались очень полезными. Кроме того, большое спасибо сотрудникам производственного отдела, которые помогли придать этой книге ее окончательный вид.
Рецензенты этой книги: Адаил Ретамал, Амит Ламба, Брент Хонадель, Колин Хасти, Дейвид Морган, Эмануэле Ориджи, Джордж Онофрей, Гилберт Беверидж, Гетц Хеллер, Харш Раваль, Хелдер да Роша, Яго Санжурхо Альварес, Исмаил Тапаал, Хуану Дурильо, Карл ван Хейстер, Лауд Бентиль, Маркус Гезель, Микаэль Быстрём, Мустафа Озетин, Наджиб Ариф, Нараянан Джаяратчаган, Недим Бамбур, Нгиа То, Нгуен Тран Чау Гианг, Оливер Кортен, Патрис Мальдаг, Питер Сабо, Ранджит Сахай, Роберт Траусмут, Себастьян Пальма, Серхио Гутьеррес и Виктор Дюран. Спасибо вам. Ваши предложения помогли улучшить эту книгу. Особая благодарность Пауло Афонсо Паррейре-младшему, который прислал очень полезный и подробный отзыв о рукописи.
Наконец, я хотел бы поблагодарить Лауру, мою жену. Она всегда поощряет любой проект, который я решаю начать. Без ее поддержки выход этой книги был бы невозможен.
В данной книге изложен набор принципов, которые помогают разработчикам контролировать сложность своих проектов, иными словами, сохранять их простоту. Эти принципы можно объединить в шесть идей:
• небольшие единицы кода;
• согласованные (консистентные) объекты;
• качественное управление зависимостями;
• хорошие абстракции;
• правильно организованная инфраструктура;
• продуманная модульность.
Книга предназначена для разработчиков программного обеспечения, которые хотят улучшить навыки объектно-ориентированного проектирования. В ней подробно обсуждаются следующие темы: сложность кода, согласованность (консистентность) и инкапсуляция, управление зависимостями, проектирование абстракций, работа с инфраструктурой и модульность. Даже если вы опытный разработчик, знакомый с такими понятиями, как чистая архитектура, книга может содержать полезную для вас информацию.
Читатель должен обладать базовыми знаниями об объектно-ориентированных концепциях, таких как классы, полиморфизм и интерфейсы. Примеры кода написаны на псевдо-Java, но могут быть понятны разработчикам, знакомым с любым объектно-ориентированным языком программирования, таким как C#, Python или Ruby.
В книге представлены принципы объектно-ориентированного проектирования, полученные из моего опыта. Они разбиты на шесть групп (сложность, согласованность, управление зависимостями, абстракции, инфраструктура и модульность). Каждой из них посвящена отдельная глава.
Сначала излагается теория, а затем в качестве иллюстрации приводятся примеры кода. В них нет новых идей, поэтому более опытные читатели при желании могут пропустить примеры. Вы также заметите, что в примерах мало строк кода и уровень их сложности невелик. Непрактично иллюстрировать все принципы, изложенные в этой книге, реальными примерами из масштабных информационных систем. Вместо этого я демонстрирую идеи, используя небольшие фрагменты кода, а вам, читателю, предстоит обобщить их.
Я делаю все возможное, чтобы описать контекст, плюсы и минусы, компромиссы, а также рассказать о том, когда не стоит применять тот или иной принцип. Тем не менее, как и в случае с любой рекомендацией, вы должны учитывать свой контекст и не использовать бездумно то, что узнаете из этой книги.
Главы заканчиваются несколькими упражнениями, в которых я прошу вас подумать над вопросами, связанными с темой главы, или обсудить их с коллегой. Эти вопросы намеренно общие и открытые. Я не даю на них ответов, поскольку универсальных ответов не существует.
В главе 1 рассказывается, в чем причины усложнения систем, зачем постоянно бороться с увеличением сложности и почему это занятие не такое тяжелое, как может показаться.
Главы 2–7 погружают читателя в шесть более сложных идей.
В главе 2 говорится о важности сохранения простоты кода и о том, как разбивать большие единицы кода на более мелкие, изолировать новые сложные элементы от существующих единиц кода и эффективно документировать код, чтобы улучшить его понимание.
Глава 3 посвящена постоянному поддержанию консистентности объектов. В ней рассматриваются проблемы, возникающие при переходе объектов в неконстистентное состояние, и способы реализации механизмов валидации, обеспечивающих постоянную согласованность объектов.
Глава 4 посвящена зависимостям и правильному управлению ими, что является основой простого проектирования. В ней рассказывается о том, как уменьшить влияние связанности в проекте, как моделировать устойчивые классы, вероятность изменения которых невелика, и почему внедрение зависимостей играет решающую роль в эффективном управлении зависимостями.
В главе 5 рассматриваются абстракции и способы их проектирования, позволяющие облегчать доработку программных продуктов, не изменяя каждый раз многочисленные классы.
Глава 6 посвящена тому, как работать с инфраструктурным кодом без ущерба для проекта и как отделить код инфраструктуры от предметной области, что позволяет вносить изменения в один код, не затрагивая другой.
В главе 7 рассматривается модульность: в частности, как проектировать модули, реализующие сложные функции с помощью простых интерфейсов, как минимизировать зависимости между модулями и определять правила владения и взаимодействия.
Глава 8 содержит несколько заключительных слов о том, почему важен прагматизм, зачем нужен постоянный рефакторинг и в чем ценность постоянного обучения объектно-ориентированному программированию.
В книге содержится множество примеров исходного кода как в нумерованных листингах, так и в строках с обычным текстом. В обоих случаях код оформляется шрифтомфиксированнойширины, чтобы отделить его от обычного текста.
Во многих случаях исходный код был переформатирован: были добавлены переносы строк и изменены отступы, чтобы код поместился на странице. Кроме того, из листингов часто удалены комментарии, когда код описывается в тексте. Многие листинги сопровождаются аннотациями, в которых поясняются важные понятия.
Если вы хотите читать и другие мои статьи об объектно-ориентированном проектировании и тестировании программного обеспечения, то подпишитесь на мою рассылку: https://effectivesoftwaretesting.substack.com.
Миссия Маурисио Аниче — помогать инженерам-программистам улучшать их навыки и продуктивность. В настоящее время Маурисио является техлидом в компании Adyen и руководит различными инициативами по повышению квалификации инженеров, в том числе Технической академией Adyen — командой, занимающейся дополнительной подготовкой и образованием инженеров. Кроме того, Маурисио — доцент кафедры программной инженерии в Делфтском технологическом университете в Нидерландах. За свою преподавательскую деятельность в области тестирования программного обеспечения получил награду «Преподаватель информатики — 2021» и TU Delft Education Fellowship — престижную стипендию, присуждаемую преподавателям-новаторам. Маурисио — автор книги Effective Software Testing: A Developer’s Guide1 (Manning, 2022).
1 Аниче М. Эффективное тестирование программного обеспечения.
Рисунок на обложке — «Женщина с острова Сцио», или «Женщина с острова Хиос», взятая из коллекции Жака Грассе де Сен-Совера, опубликованной в 1788 году. Каждая иллюстрация нарисована и раскрашена вручную.
В те времена по одежде можно было легко определить, где живет человек, каковы его профессия или общественное положение. Издательство Manning прославляет изобретательность и инициативность ИТ-бизнеса, создавая обложки книг, основанные на богатом разнообразии региональной культуры столетней давности, которые оживают благодаря фотографиям из таких коллекций.
Мы выражаем огромную благодарность компании КРОК за помощь в работе над русскоязычным изданием книги и вклад в повышение качества переводной литературы.
Ваши замечания, предложения, вопросы отправляйте по адресу [email protected] (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На веб-сайте издательства www.piter.com вы найдете подробную информацию о наших книгах.
Валентина Бородина — руководитель проектов оптимизации и автоматизации бизнес-процессов. Обладает экспертизой во внедрении программных продуктов 1С для коммерческого сегмента. Специализируется на управлении ИТ-рисками и процессами ITSM. Опыт работы в ИТ — более 15 лет.
В этой главе
• Почему системы со временем усложняются.
• Проблемы объектно-ориентированного проектирования.
• Почему нужно постоянно совершенствовать архитектуру решения.
В 2010 году я работал в одной замечательной интернет-компании в команде, отвечающей за биллинг (выставление счетов). Основатель компании написал первую версию системы за 10 или 15 лет до моего прихода. Вся логика заключалась в сложных хранимых процедурах SQL Server, каждая из которых состояла из тысяч строк кода. Пришло время выполнить рефакторинг существующей биллинговой инфраструктуры, создав нечто новое, и я не могу сосчитать, сколько часов наш отдел общался с сотрудниками финансовой команды, чтобы создать архитектуру, которая бы соответствовала их текущим и будущим потребностям.
Отличная новость — мы справились. Благодаря новой версии мы могли добавлять новые продукты или финансовые правила за считаные часы. Финансовая команда была очень довольна нами. Запросы на добавление новых функций, на которые раньше уходили недели, теперь занимали пару дней. Существенно улучшилось и качество. Наш код хорошо поддавался тестированию, поэтому мы редко сталкивались с регрессионными ошибками. Даже наш джуниор мог легко ориентироваться в коде и чувствовать себя достаточно уверенно, чтобы вносить важные изменения. Одним словом, наш новый проект был простым.
Я занимаюсь разработкой объектно-ориентированных программных систем уже 20 лет и понял, что в объектно-ориентированной системе без надлежащего проектирования даже простые вещи оказываются слишком сложными. Но так не должно быть.
Объектно-ориентированное программирование — отличный выбор при реализации сложных программных продуктов, где обязательными условиями являются гибкость и удобство сопровождения. Однако просто выбрать объектно-ориентированный язык для своего проекта недостаточно. Необходимо правильно его использовать.
К счастью, нам не нужно изобретать оптимальные приемы работы с объектно-ориентированными системами с нуля, поскольку профессиональное сообщество уже обладает обширными знаниями. Если вы мало что знаете о существующих приемах или хотите освежить их в памяти, то эта книга идеально вам подойдет, и вам стоит прочитать ее от начала до конца, в том числе примеры кода. Если вы уже более опытный инженер и знаете о существующих приемах, то эта книга поможет вам взглянуть на них по-другому, более прагматично и, надеюсь, натолкнет вас на интересные мысли.
Практически у любого разработчика при создании информационной системы на объектно-ориентированном языке возникает несколько общих вопросов.
• Достаточно ли проста эта реализация или мне следует предложить еще более элегантную абстракцию?
• Этот класс проходит через множество состояний в течение своего жизненного цикла. Как мне гарантировать его консистентность?
• Как моделировать взаимодействие моей системы и внешнего веб-приложения?
• Допустимо ли связать классы или это плохая идея?
Эта книга называется «Простое объектно-ориентированное проектирование»,поскольку простые объектно-ориентированные проекты всегда легче сопровождать. Мало разработать простой проект — важно сохранить его в таком виде. За эти годы я многому научился на примере своих удачных и неудачных решений, и в этой книге поделюсь набором паттернов, которые помогают мне создавать объектно-ориентированные информационные системы, которые легко сопровождать и развивать.
«По мере развития информационных систем их сложность возрастает, если не предпринимать усилий по ее удержанию или снижению».
Эту мысль высказал Мэнни Леман (Manny Lehman) в своей работе 1984 года On understanding laws, evolution, and conservation in the large-program life cycle (https://dl.acm.org/doi/10.1016/0164-1212%2879%2990022-0). Доработка систем любого типа — дело непростое. Мы знаем, что код имеет тенденцию засоряться со временем и требует усилий по сопровождению. И несмотря на 40 лет прогресса, сопровождаемость программных продуктов остается сложной задачей.
По сути, степень сопровождаемости — это количество усилий, которые вы прикладываете для выполнения таких задач, как изменение бизнес-правил, добавление функций, выявление ошибок и исправление системы. Программное обеспечение с высокой степенью сопровождаемости позволяет разработчикам выполнять эти задачи, прикладывая разумные усилия, в то время как низкая сопровождаемость все усложняет, отнимает много времени и плодит ошибки.
На удобство сопровождения влияет множество факторов: от чрезмерно сложного кода до управления зависимостями, плохо продуманных абстракций и некачественной модульности. Системы со временем естественным образом усложняются, поэтому постоянное расширение кода без учета последствий для сопровождения может быстро запутать базу.
Последовательная борьба с увеличением сложности очень важна, даже если кажется трудоемкой. И я знаю, что она требует больше усилий, чем просто создание дампа (dumping code). Но поверьте, разработчики чувствуют себя гораздо хуже, когда целый день разбираются с полотнищами спагетти-кода. Наверняка вам приходилось работать с кодовыми базами, которые было сложно сопровождать. Мне — да. Любые действия в таких системах занимают много времени. Вы не можете найти место, в котором надо писать свою часть; весь код, который вы пишете, кажется временным решением; вы не можете написать автоматизированные тесты, поскольку код не поддается тестированию; вы всегда боитесь, что тот или иной элемент не будет работать должным образом, поскольку не уверены в том, какие изменения вообще можно вносить, и т.д.
Что же такое простой объектно-ориентированный проект? Исходя из моего опыта, это проект, который обладает следующими шестью характеристиками (рис. 1.1):
• простой код;
• консистентные объекты;
• качественное управление зависимостями;
• хорошие абстракции;
• правильная работа с внешними зависимостями и инфраструктурой;
• продуманная модульность.
Эти идеи могут показаться вам знакомыми. Все они популярны в объектно-ориентированных системах. Теперь вкратце рассмотрим, что я имею в виду под каждой из них и что происходит, когда мы теряем контроль.
Рис. 1.1. Характеристики простого объектно-ориентированного проекта
Реализация простых методов и классов — отличный способ начать заниматься объектно-ориентированным проектированием. Рассмотрим метод, который начинался с малого количества строк и условных операторов, но со временем разросся и теперь содержит сотни строк и одни операторы if внутри других. Сопровождать такой метод очень сложно.
Интересно, что классы и методы поначалу просты и управляемы. Но если мы не стараемся поддерживать их в таком состоянии, то они становятся сложными для понимания и сопровождения (рис. 1.2). В запутанных реализациях кода сложно разбираться, что неизбежно породит ошибки. Вдобавок сопровождение, рефакторинг и тестирование такого кода требуют больших усилий, поскольку разработчики боятся что-либо сломать и пытаются определить все возможные тестовые сценарии.
Рис. 1.2. Простой код со временем усложняется, и, как следствие, его очень трудно сопровождать
Существует множество способов уменьшить сложность класса или метода. Например, ясные и выразительные имена переменных помогают разработчикам лучше понять их назначение. Однако в этой части книги я утверждаю, что правило № 1 для сохранения простоты классов и методов звучит так: они должны быть небольшими. Метод не должен быть слишком длинным. В классе не должно быть слишком много методов. Мелкие единицы кода всегда легче сопровождать и развивать.
Гораздо проще работать над системой, когда вы можете быть уверены, что объекты консистентны и любая попытка рассогласовать их будет пресечена. Когда согласованность не учитывается при проектировании, объекты могут находиться в недопустимых состояниях, что приводит к ошибкам и проблемам с сопровождением.
Рассмотрим класс Basket в системе электронной торговли, отслеживающий товары, которые покупает человек, и их конечную стоимость. Итоговая стоимость должна обновляться каждый раз, когда мы добавляем товар в корзину или удаляем его из нее. Кроме того, корзина должна отклонять некорректные запросы клиентов, например добавление одного товара несколько раз или удаление товара, которого нет в корзине.
На рис. 1.3 слева показана защищенная корзина: товары можно добавлять или удалять только обращением к корзине. Она полностью контролирует содержимое и обеспечивает его согласованность. Справа — незащищенная корзина, открывающая неограниченный доступ к ее содержимому. Из-за отсутствия контроля эта корзина не всегда может обеспечить согласованность.
Таким образом, хорошая архитектура гарантирует, что объекты никогда не будут находиться в неконсистентном состоянии. Согласованность может быть нарушена вследствие многих действий, например при использовании неправильных сеттеров, которые обходят проверки согласованности, или в случае отсутствия гибких механизмов валидации, подробнее о которых мы поговорим позже.
Рис. 1.3. Две корзины: одна контролирует действия, которые в ней происходят, а другая — нет. Управление состоянием и согласованностью — основополагающий фактор
В крупномасштабных объектно-ориентированных системах управление зависимостями становится критически важным элементом удобства сопровождения. Когда в системе с высокой степенью связанности никого не интересует, как классы связаны между собой, любое простейшее изменение может привести к непредсказуемым последствиям.
На рис. 1.4 показано, как на класс Basket могут повлиять изменения в любом из зависящих от него классов: DiscountRules, Product и Customer. Даже изменение в классе DiscountRepository, транзитивной зависимости, может повлиять на Basket. Например, если класс Product часто меняется, то Basket всегда рискует тоже измениться.
Простые объектно-ориентированные проекты направлены на минимизацию зависимостей между классами. Чем меньше они зависят друг от друга и чем меньше знают друг о друге, тем лучше. Кроме того, правильное управление зависимостями гарантирует, что классы будут максимально зависеть от стабильных компонентов, вероятность изменения которых невелика, как и вероятность спровоцированных ими каскадных изменений.
Рис. 1.4. Управление зависимостями и распространение изменений
Простой код всегда предпочтительнее, но расширяемость может потребовать большего. Расширение класса путем добавления большего количества кода в какой-то момент перестает быть эффективным и превращается в обузу.
Представьте, что в одном классе или методе реализовано 30 или 40 различных бизнес-правил. Я показываю это на рис. 1.5. Обратите внимание, как класс DiscountRules, отвечающий за применение различных скидок в нашей системе электронной торговли, увеличивается по мере появления новых правил скидок, что значительно усложняет его сопровождение. Хорошее архитектурное решение позволяет разработчикам пользоваться абстракциями, которые помогают им развивать систему, не усложняя существующие классы.
Рис. 1.5. Класс, не имеющий абстракций, бесконечно усложняется
Простые объектно-ориентированные проекты отделяют доменный слой, содержащий бизнес-логику, от кода, необходимого для взаимодействия с внешними зависимостями. На рис. 1.6 слева показаны классы домена, а справа — классы, обеспечивающие взаимодействие со сторонними системами и инфраструктурой.
Рис. 1.6. Архитектура информационной системы, в которой инфраструктура отделена от доменного слоя или бизнес-логики
Если детали инфраструктуры проникнут в ваш доменный слой, это может помешать вам вносить изменения в инфраструктуру. Представьте, что весь код для доступа к базе данных разбросан по кодовой базе. Теперь вам нужно добавить слой кэширования, чтобы ускорить время отклика приложения. Возможно, для этого вам придется изменить код повсеместно.
Проблема заключается в том, чтобы абстрагироваться от несущественных или внешних аспектов вашей инфраструктуры и при этом использовать предоставляемые ею ценные возможности. Например, если вы используете реляционную базу данных, такую как Postgres, то можете захотеть скрыть ее присутствие от кода предметной области, но при этом иметь возможность применять ее уникальные функции, которые повышают производительность или быстродействие.
Почему я называю это инфраструктурой?
Я использую термин «инфраструктура» для обозначения любой зависимости от внешних систем и ресурсов, таких как веб-сервисы, базы данных, сторонние API и все, что находится за пределами вашей системы. При возникновении такой зависимости необходимо написать код, соединяющий вашу систему с внешней системой или ресурсом. В главе 6 мы сосредоточимся на гибком написании такого «связующего кода», чтобы он не навредил остальной части вашего проекта.
Информационные системы развиваются, и уместить все в одном компоненте или модуле сложно. В простых объектно-ориентированных проектах большие системы разделяются на независимые компоненты, которые взаимодействуют для достижения общей цели.
Благодаря разделению систем на более мелкие компоненты их легче сопровождать и понимать. Вдобавок это помогает разным командам работать над отдельными компонентами без конфликтов. Управлять мелкими компонентами и тестировать их — тоже более простая задача.
Рассмотрим программный продукт с тремя предметными областями: «Счет» (Invoice), «Выставление счетов» (Billing) и «Доставка» (Delivery). Они должны работать вместе, причем «Счет» и «Доставка» требуют информации от области «Выставление счетов».
На рис. 1.7 слева показана система без модулей, в которой свободно перемешиваются классы из разных доменных областей. По мере увеличения сложности такая система становится неуправляемой. В правой части рисунка показана та же система, разделенная на модули: «Выставление счетов», «Счет» и «Доставка». Модули взаимодействуют через интерфейсы, что позволяет клиентам использовать только необходимые элементы, не разбираясь во всей доменной области.
Рис. 1.7. Две системы с различными подходами к модульному построению
Определить нужный уровень детализации для модуля или то, как должен выглядеть его публичный интерфейс, — непростая задача. Мы поговорим об этом позже.
Как я уже сказал, в создании простой архитектуры обычно нет ничего сложного, в отличие от поддержания простоты по мере развития системы. Мы должны постоянно совершенствовать и упрощать наши проекты по мере того, как узнаем о системе все больше информации. Чтобы это произошло, мы должны превратить проектирование в повседневную деятельность. Для этого необходимо учесть следующие факторы.
• Уменьшение сложности сродни личной гигиене. Постоянную работу над упрощением проекта можно сравнить с чисткой зубов. Хотя это и не особенно увлекательно, но необходимо, чтобы избежать дискомфорта и дорогостоящих проблем в будущем. Точно так же, если ежедневно уделять немного времени обслуживанию кода, это поможет избежать более серьезных проблем в дальнейшем.
• Если сложность сейчас неизбежна, то старайтесь упростить решение в будущем. Сложности иногда нельзя избежать. Можно начать и со сложного решения. Проблема заключается в его сопровождении в течение неопределенного срока. Как только вы нашли более простое решение, пора планировать рефакторинг.
• Последовательное решение сложных задач экономически эффективно. Регулярное решение проблемы сложности позволяет держать в разумных пределах как время, так и связанные с ней затраты. Промедление в управлении сложностью может привести к значительному увеличению расходов и сделать рефакторинг более трудоемким.
Понять это помогает метафора технического долга