Если ваша команда не знает, где искать элементы для повторного использования, или не умеет работать с ними, то, естественно, она самостоятельно создаст их заново. А платить по счетам придется вам.
«Я» в архитектуре не существует
На самом деле «я» в архитектуре, конечно, существует. Но это не заглавное «Я», привлекающее к себе внимание и доминирующее во всех обсуждениях. Строчной буквы вполне достаточно.
Как это относится к нам — архитекторам программных продуктов? Наше эго подчас оказывается нашим самым опасным врагом. Кто из нас не встречал архитекторов, которые:
• считают, что они понимают требования лучше заказчиков,
• рассматривают разработчиков как ресурс, нанятый для реализации их идей,
• в штыки воспринимают любые сомнения в своих идеях или игнорируют идеи других?
Подозреваю, что любой опытный архитектор когда-нибудь допускал хотя бы одну из этих ошибок. Я допускал их все и извлек болезненные уроки из своих неудач.
Почему это происходит?
Как этого избежать?
Исключение «Я» из архитектуры не гарантирует успеха. Оно всего лишь устраняет распространенный источник ошибок, происходящих только по вашей вине.
Посмотрите с высоты 300 метров
Нам, архитекторам, хочется знать, насколько хороша та программа, над которой мы работаем. Качество программы имеет очевидный внешний аспект — программа должна представлять ценность для пользователей, — но у него есть и более тонкий внутренний аспект, относящийся к ясности дизайна, — к тому, насколько легко нам понимать, сопровождать и расширять программный продукт. Если от нас настойчиво требуют определения качества, обычно мы в конце концов говорим: «Я узнаю это, когда увижу». Но как можно увидеть качество?
Маленькие квадратики на архитектурных диаграммах представляют целые системы, а линии между ними могут обозначать все что угодно: зависимости, потоки данных или совместно используемые ресурсы (например, шину). Такие диаграммы изображают систему с высоты 10 километров, примерно в таком же масштабе, в котором мы видим ландшафт с самолета. Единственной альтернативой, как правило, является исходный код, который можно сравнить с видом на уровне земной поверхности. Оба представления не в силах передать сколько-нибудь существенной информации о качестве программного продукта: одно находится на слишком высоком уровне, а другое настолько перегружено деталями, что за ними не видно структуры. Очевидно, не хватает промежуточного варианта — взгляда с высоты 300 метров.
«Вид с высоты 300 метров» предоставляет информацию на нужном уровне. Он объединяет большие объемы данных и различные метрики (количество методов, количество зависимостей,[13] цикломатическая сложность[14]). То, как это будет представлено на практике, сильно зависит от конкретного аспекта качества. Это может быть визуальное представление графа зависимостей, гистограмма с отображением метрик на уровне классов или сложный полиметрический вид, показывающий связи различных входных значений.
Создавать такие представления вручную и поддерживать их синхронизацию с программой — безнадежное занятие. Нужны инструменты, которые способны создавать такие представления на основе единственного надежного источника информации — исходного кода. Для некоторых представлений, скажем для структурной матрицы решений (design structure matrix), существуют коммерческие инструменты, однако специализированные представления на удивление легко создаются посредством объединения небольших инструментов, извлекающих данные и метрики, с общими пакетами визуализации. Простой пример: вывод Checkstyle (по сути, набор метрик уровня классов и методов) загружается в электронную таблицу для построения диаграмм. Те же метрики могут отображаться и в формате ТгееМар с использованием инструментария InfoViz. Отличным инструментом для отображения графов сложных зависимостей является также GraphViz.
Как только подходящее представление найдено, качество программного продукта начинает восприниматься менее субъективно. Появляется возможность сравнивать разрабатываемый продукт с другими подобными системами. Сравнение разных версий одной системы позволяет выявлять тенденции, а сравнение представлений различных подсистем способно выявить резкие отклонения от нормы. Даже с одной-единственной диаграммой мы можем положиться на свое эстетическое чувство и умение подмечать закономерности. Хорошо сбалансированное дерево, вероятно, отражает удачную иерархию классов; гармоничный набор прямоугольников может изображать код, организованный в виде классов правильного размера. В большинстве случаев работает весьма простой принцип: то, что хорошо выглядит, скорее всего, хорошо устроено.
Пробуйте, прежде чем сделать выбор
В процессе создания приложения приходится принимать много решений. Какие-то из них могут быть связаны с выбором инфраструктуры или библиотеки, другие относятся к использованию конкретных шаблонов проектирования. В любом случае ответственность за принятие решения обычно лежит на плечах архитектора. В расхожем представлении архитектор собирает всю доступную информацию, какое-то время размышляет над ней, а потом изрекает указания, которые должны быть воплощены разработчиками… Вряд ли вас удивит, что существует лучший способ.
В своем труде, посвященном бережливой разработке (lean development), Мэри и Том Поппендик (Магу и Tom Poppendieck) описывают методику принятия решений. Они считают, что принятие окончательного решения следует откладывать до самого ответственного момента — той точки, когда отсутствие у команды решения приведет к тому, что решение будет принято за нее, а бездействие повлечет за собой необратимые (или труднообратимые) последствия. И это разумно: ведь чем позднее принимается решение, тем больше информации для его принятия. Однако во многих случаях «больше информации» не равносильно «достаточно информации», а лучшие решения, как всем хорошо известно, принимаются «задним числом». Что это означает для хорошего архитектора?
Архитектор должен постоянно думать о том, какие решения ему придется принять в ближайшем будущем. Если команда состоит более чем из двух-трех разработчиков и в ней практикуется коллективное владение кодом, то при приближении к точке принятия решения архитектор может предложить нескольким разработчикам выбрать один из вариантов и некоторое время поработать в этом направлении. Когда наступает ответственный момент, команда встречается для обсуждения преимуществ и недостатков разных решений.
Теперь, когда есть возможность оглянуться назад и посмотреть на последствия, лучшее решение задачи обычно для всех очевидно. По сути, архитектору не приходится принимать решение — он просто дирижирует процессом его принятия.
Этот подход применим как к простым, так и к серьезным задачам. С его помощью команда может решить, стоит ли использовать шаблоны Hibernate, предоставляемые инфраструктурой Spring, но с таким же успехом он поможет ответить на вопрос, какую инфраструктуру JavaScript следует выбрать для проекта. Разумеется, время созревания решения очень сильно зависит от сложности задачи.
Чтобы опробовать два и более решения одной задачи, нужно больше усилий, чем на реализацию априорно принятого решения. Однако априорный выбор чаще приводит к таким решениям, которые позднее оказываются неоптимальными, и перед архитектором возникает дилемма: отказываться от текущей реализации или оставлять ее со всеми вытекающими отсюда последствиями; оба варианта приводят к неэффективному расходованию ресурсов. Еще хуже, если никто из команды не осознает неоптимальность выбранного подхода из-за того, что не были изучены альтернативы. Тогда усилия расходуются впустую без каких-либо шансов осознать это. В конечном итоге опробование нескольких решений может оказаться наиболее экономичным вариантом.
Разберитесь в предметной области
Эффективный архитектор программного обеспечения разбирается не только в технологиях, но и в предметной области решаемой задачи. Без этих познаний трудно понять деловой аспект задачи, цели и требования компании, а значит, трудно спроектировать эффективную архитектуру, отвечающую нуждам бизнеса.
Роль архитектора программного обеспечения состоит в том, чтобы понять задачу, стоящую перед бизнесом, бизнес-цели и бизнес-требования и преобразовать их в техническое архитектурное решение, удовлетворяющее им. Знание предметной области помогает архитектору решить, какие шаблоны следует применять, как планировать будущие расширения и как учесть тенденции развития отрасли, чтобы лучше подготовиться к изменениям. Например, для одних предметных областей (скажем, для страхового бизнеса) хорошо подходят сервис-ориентированные архитектурные решения (service-oriented architecture), а для других (например, для финансовых рынков) — архитектурные решения на основе бизнес-правил (workflow-based architecture). Знание предметной области помогает решить, какие архитектурные шаблоны лучше всего отвечают конкретным потребностям организации.
Знание отраслевых тенденций в конкретной области также помогает архитектору спроектировать эффективную архитектуру. Например, в страховом бизнесе набирает силу тенденция к автострахованию «по требованию», когда клиент оплачивает страховку только за время фактического вождения автомобиля. Страховка такого типа очень удобна, если вы оставляете свою машину в аэропорту утром в понедельник, отбываете к месту работы, возвращаетесь в пятницу и едете на машине домой. Знание подобных тенденций позволяет планировать их поддержку в архитектуре, даже если компания, на которую вы работаете, еще не запланировала их в своей бизнес-модели.
Понимание целей бизнеса также помогает спроектировать эффективную архитектуру. Например, входит ли в состав целей той организации, на которую вы работаете, расширение посредством масштабных слияний и поглощений? Ответ на этот вопрос может повлиять на тип проектируемой архитектуры. Если ответ положительный, архитектура, возможно, должна содержать много уровней абстракции, чтобы облегчить слияние компонентов бизнес-логики. Если стратегия бизнеса предусматривает наращивание присутствия компании в Интернете с целью расширения доли рынка, вероятно, очень важным атрибутом будет высокая доступность. Архитектор обязан понимать цели компании, на которую он работает, и постоянно проверять, поддерживает ли архитектура эти цели.
Из всех известных мне архитекторов самыми успешными являются те, кто сочетает широкие практические познания в технической области с хорошим знанием конкретной предметной области. Они могут общаться с руководством и заказчиками на хорошо понятном им языке предметной области. Это, в свою очередь, дает заказчику чувство уверенности в том, что архитектор знает, что делает. Владение предметной областью позволяет архитектору лучше понимать задачи, проблемы, цели, данные и процессы — все те факторы, которые играют ключевую роль в проектировании эффективной архитектуры уровня предприятия.
Программирование — это часть процесса проектирования
Кристен Нигаард (Kristen Nygaard), отец объектно-ориентированного программирования и языка программирования Simula, говорил, что
Откуда же индустрия разработки программного обеспечения может черпать практические идеи для совершенствования своих методик? Как насчет отраслей производства сложных товаров массового производства: автомобилей, лекарств, полупроводников?
Возьмем автомобилестроение. Планирование новой модели начинается с выбора концепции или прототипа. Это в первую очередь механизм архитектурного позиционирования. BMW Х6 — пример новой концепции, объединяющей свойства внедорожника и купе, которую BMW называет
Чему можно научиться на примере этого сценария? Здесь важно то, что производство новой машины состоит из двух процессов. Первый из них — процесс творческого проектирования, включающий в себя установку необходимых сборочных линий. Второй — процесс производства машин в соответствии со спецификациями заказчика. Сходные во многих отношениях процессы присутствуют и в отрасли разработки программного обеспечения. Вопрос в том, какой смысл мы вкладываем в термины.
В своей статье «Как проектировать ПО?»[15] Джек Ривз (Jack Reeves) высказывает мнение, что единственным артефактом разработки ПО, действительно описывающим дизайн (в том смысле, как понимается и используется это понятие в классических инженерных дисциплинах), является исходный код. Собственно производство ПО автоматизировано и обеспечивается сценариями компиляции, сборки и тестирования.
Соглашаясь с тем, что создание исходного кода является частью проектирования, а не производства, мы получаем возможность применить полезные методы управления, работоспособность которых была проверена временем. Это методы управления творческой и непрогнозируемой работой, такой как разработка новой машины, нового лекарственного препарата или новой компьютерной игры. Речь идет о методах гибкого (agile) управления и бережливого (lean) производства (например, SCRUM). Эти методы направлены на то, чтобы максимизировать эффективность вложений с позиций ценности для потребителя.
Чтобы с выгодой использовать эти методы в области разработки ПО, необходимо запомнить: программирование является частью процесса проектирования, а не производства.
Предоставьте разработчикам независимость
Почти все архитекторы начинают свою карьеру как разработчики. У архитектора больше обязанностей, но в то же время он обладает большим влиянием в том, что касается конструкции системы. Возможно, в новой для вас роли архитектора вам будет трудно избавиться от некоторых привычек разработчика. Что еще хуже, у вас может возникнуть чувство, что вы должны постоянно контролировать разработчиков и их деятельность по реализации вашего дизайна. Однако для вашего успеха (и успеха вашей команды) очень важно предоставить всем коллегам достаточную независимость, которая позволит им продемонстрировать свои навыки и проявить творческие способности.
У разработчика редко находится время для того, чтобы откинуться в кресле и подумать над тем, насколько слаженной является работа системы в целом. В то же время все внимание архитектора должно быть сосредоточено именно на этом. Пока разработчики во весь опор создают классы, методы, тесты, интерфейсы и базы данных, вы следите за тем, как эти компоненты работают в сочетании друг с другом. Ищите «узкие места» и пытайтесь устранить их. У ваших людей возникают проблемы с написанием тестов? Улучшите интерфейсы и ограничьте зависимости. Непонятно, где абстракция действительно необходима, а где можно обойтись без нее? Добейтесь лучшего понимания предметной области. Не знаете, в каком порядке создавать компоненты системы? Составьте план проекта. Разработчики повторяют одни и те же ошибки при использовании спроектированного вами API? Сделайте дизайн более понятным. Разработчики плохо понимают ваш дизайн? Пообщайтесь с ними и все подробно разъясните. Вы сами плохо понимаете, где масштабирование уместно, а где нет? Поработайте с заказчиками и разберитесь в их бизнес-модели.
Если вы хорошо справляетесь с должностью архитектора, у вас попросту не останется времени на то, чтобы вмешиваться в дела разработчиков. Конечно, вам придется достаточно внимательно следить за тем, чтобы реализация вашего дизайна соответствовала задуманному. Однако для этого вовсе не обязательно стоять за спиной у других людей. Вы можете предложить свое решение, когда видите, что разработчики столкнулись с трудностями, но еще лучше создать такую среду, чтобы они сами пришли и обратились к вам за советом. Хороший архитектор искусно удерживает равновесие, обеспечивая успешность архитектуры и оставляя коллегам пространство для реализации их творческого и интеллектуального потенциалов.
Время меняет все
Многие годы одним из самых ярких развлечений для меня было наблюдение за тем, что выжило, а что нет. Шаблоны, инфраструктуры, сдвиги парадигм, алгоритмы — их было так много, умные люди так страстно обсуждали их, думали о долгосрочных перспективах, старались сбалансировать все известные аспекты, но в конечном счете они ушли в небытие. Почему? Что история пытается сказать нам?
Для архитектора программного обеспечения это довольно трудно. Ведь задачи и проблемы мы получаем от заказчика, и у нас нет такой роскоши, как выбор, верно? Все не так просто. Прежде всего, мы часто ошибочно считаем, что не можем повлиять на требования заказчика. Однако обычно это возможно, просто для этого нужно выйти из зоны комфорта в пространстве технологий. Неправильный выбор грозит нам встречей с драконами. Время течет, мы усердно работаем над поставленной задачей, но в конечном итоге весь наш труд оказывается напрасным: мы сделали не то, что требовалось, и вся работа идет прахом. Хорошее решение правильно выбранной задачи с большой вероятностью переживет все остальные решения.
Мы часто говорим себе: будь проще.[16] Говорим — но не делаем. А не делаем потому, что это необязательно. Ведь мы такие умные, мы без труда управляемся с возросшей сложностью и легко оправдываем ее — потому что она делает архитектуру более гибкой, потому что такие решения кажутся нам более элегантными, потому что мы считаем, что способны предвидеть будущее. Время идет; на год или больше мы отходим от проекта… А когда возвращаемся, почти всегда недоумеваем, почему было сделано то, что сделано. Если бы сейчас мы делали все заново, то, скорее всего, приняли бы совсем другие решения. Эту шутку сыграло с нами время, представив нас глупцами в наших собственных глазах. Постарайтесь осознать это как можно раньше, преодолейте свою инерцию и попытайтесь понять, что же такое простота, способная выдержать проверку временем.
Архитекторы любят искать «единственный истинный путь» — методологию или философию, способную привнести столь желанную предсказуемость и открыть наконец те ясные ответы, которые, как им кажется, находятся где-то совсем рядом. Проблема в том, что ориентиры, которыми вы руководствуетесь сейчас, вряд ли останутся теми же через пару лет, не говоря уже о десятилетиях. Оглядываясь назад, вы всегда видите результаты, не соответствующие вашему нынешнему уровню притязаний. Научитесь принимать свои прежние достижения и боритесь с искушением попытаться вернуться и «исправить» их. Соответствовало ли решение поставленной задаче? Удовлетворяло ли оно требованиям? Используйте эти вопросы как критерии оценки — и у вас будет радостнее на душе.
«Архитектор программного обеспечения» пишется со строчной буквы
В последнее время в области разработки ПО наметилась одна прискорбная тенденция: стремление присвоить архитектуре ПО профессиональный статус наравне с классической школой архитектуры. Похоже, она обусловлена желанием архитекторов утвердить свои успехи и достижения в глазах более широкой общественности, нежели круг коллег и непосредственных работодателей. Но ведь архитектура обрела профессиональный статус лишь в конце XIX века — спустя тысячелетия после своего зарождения. Некоторые архитекторы программного обеспечения определенно слишком торопятся в своем стремлении к признанию.
Создание архитектуры программного обеспечения — искусство, и для достижения успеха в этой области, бесспорно, необходимы практика и дисциплина. И все же разработка программного обеспечения находится на относительно ранней стадии развития. Мы пока не располагаем достаточной информацией об этой отрасли, чтобы обоснованно придать ей профессиональный статус. Несмотря на молодость индустрии разработки ПО, ее продукция ценится достаточно высоко, и услуги квалифицированных специалистов в этой области (а также тех, кто стремится выглядеть таковыми) оплачиваются на том же уровне, что и в ведущих профессиональных областях, включая медицину, бухгалтерский учет и юриспруденцию.
Специалисты-практики в области разработки ПО получают хорошую оплату за свою творческую, сопряженную с исследованиями работу. Плоды наших трудов использовались для достижения многих значимых результатов, и некоторые из них принесли пользу всему человечеству. Преградами на пути к признанию являются наши действительные достоинства и возможности; в областях, достигших профессиональной зрелости, действуют программы обучения и стажировки, заметно превосходящие аналоги из нашей отрасли. Поразмыслите над этим и поймите, сколько у нас причин довольствоваться текущим положением дел и какой дерзостью будет настаивать на том, что архитектор программного обеспечения должен стоять на одной ступени с Адвокатом, Доктором и Зодчим.
Должность «архитектор программного обеспечения» пишется со строчной буквы «а»; осознайте этот факт и примите его.
Масштаб — враг успеха
Границы проекта характеризуют его масштаб. Сколько времени, усилий и ресурсов необходимо для его реализации? Какую функциональность и с каким уровнем качества требуется получить? Насколько сложно сдать продукт к заданному сроку? Какова степень риска? Какие имеются ограничения? Ответы на эти вопросы определяют границы проекта. Архитекторам программного обеспечения больше нравится тот вызов, который им бросают большие, сложные проекты. Потенциальные выгоды даже искушают людей искусственно раздувать размеры проекта для повышения его кажущейся важности. Однако расширение границ — враг успеха, потому что вероятность неудачи растет быстрее, чем можно ожидать. Увеличение масштаба проекта вдвое часто приводит к тому, что вероятность провала возрастает на порядок.
Почему так происходит? Рассмотрим несколько примеров.
• Интуиция подсказывает нам выделить вдвое больше времени или ресурсов, чтобы удвоить объем работы. Однако история показывает,[17] что связь между ними не такая линейная, как утверждает интуиция. Например, в команде из четырех человек затраты времени на взаимодействия возрастают более чем вдвое по сравнению с командой из двух человек.
• Наши оценки — отнюдь не точная наука. Кто из нас не попадал в ситуацию, когда реализация какой-то функции оказывалась намного сложнее, чем предполагалось вначале.
Конечно, некоторые задачи изначально подразумевают выполнение проекта определенного масштаба и сложности. Написать текстовый редактор без возможности ввода текста несложно, но его вряд ли можно будет назвать текстовым редактором. Какие же стратегии помогают управлять границами в реальных проектах?
Сторонники гибких методологий увещевают нас строить «самое простое, что будет работать».[19] Неудачи проектов со сложной архитектурой происходят намного чаще, чем с простой. Сокращение границ проекта часто приводит к упрощению архитектуры — и это одна из самых эффективных стратегий, позволяющих архитектору повысить шансы успешного завершения проекта.