Я консультирую серьезные софтверные компании, которые поддерживают большие информационные системы на базе .net с миллионами транзакций в день. Как правило, мой контракт с ними длится от 1 до 2 лет. За это время я успеваю копнуть достаточно глубоко, и при этом я успел поработать с множеством различных компаний. Это позволяет мне делать интересные наблюдения и выводы об их процессах разработки ПО. Я своего рода Николай Дроздов, который наблюдает естественное поведение передовых софтверных компаний в их естественных условиях.
Часто я вижу одну интересную практику, которая называется «универсальная платформа» («the core framework»). Некоторые компании называют это «наша платформа», «наш фреймворк», другие называют это просто «ядром». Но независимо от того как Вы это назовете, практика подобной универсальный платформы, как правило (но не всегда), является злом, которое негативно отражается на конечной продуктивности вашей компании.
Суть явления
Хочу прояснить, в этой статье идет речь об универсальной платформе для разработки ПО, которую какая-либо компания использует для реализации своих различных проектов. Это не то же самое, что ядро приложения.
Ядро приложения обычно представляет собой слой бизнес-логики, который используется различными модулями на слое приложения в одном проекте. Например, ядро приложения SquareHire используется в веб-сайте, веб-приложении, веб-админке, обработчике и API. Все эти различные модули работают с некоторыми общими данными и функционалом бэк-энда. Все вместе они составляют единый проект SquareHire, поэтому выделение для них общего ядра приложения это правильная практика.
Универсальная платформа это нечто совсем другое. Представьте, что у некоторой компании есть несколько проектов, которые не связаны общими данными и функционалом бэк-энда. Возможно, у них вообще нет ничего общего. Тем не менее, компания хочет сделать их программную архитектуру максимально стандартизованной, поэтому принимается решение реализовать каждый проект на основе общей «универсальной платформы». Часто такие платформы называются по имени компании, например, AcmeInc.core. Это приводит к тому, что совершенно не связанные между собой проекты разделяют общую архитектуру и кодовую базу. Именно о такой практике я и хочу рассказать.
Как это происходит?
Представьте, что компания успешно реализовала некоторый проект. Проект продолжается, компания растет и нанимает все больше разработчиков. Появляются и новые возможности, однако их делают разработчики, которые совершенно не знакомы с оригинальным дизайном. Они просто пишут код, который решает конкретную задачу привычным для них способом. И этот код не следует тем шаблонам, которые были выработаны в оригинальном дизайне проекта, он просто решает проблему. И может быть даже, что новый подход лучше старого дизайна.
Проходит время. Компания становится еще более успешной, у проекта становится больше пользователей, и сейчас он поддерживается совершенно новой командой разработчиков, которые вообще ничего не знают о тех, кто изначально создавал проект. Каждая новая волна разработчиков реализует новые фичи в соответствии со своими представлениями о том, как их лучше сделать. Новые фичи порождают дизайн-конфликт и покрывают оригинальный проект как опухоли.
Так проходит еще некоторое время. Компания стала настолько успешной, что разрабатывает уже несколько проектов, или возможно они была куплена и поглощена другой софтверной компанией с множеством своих проектов. Как бы это ни получилось, но сейчас у компании множество проектов и на каждом проекте своя команда. У всех проектов разная архитектура и каждый из них становится все труднее поддерживать, так как каждая новая проектная команда все делает в нем по-своему.
В этот момент кому-то в голову приходит гениальная идея: «Я знаю, как мы можем делать проекты на порядок эффективнее, и все наши программы будут работать гораздо лучше! Нам достаточно разработать одну идеальную стандартную архитектуру, и чтобы все в компании перешли на ее основу. Мы создадим набор базовых библиотек, и каждый новый проект будем делать на них».
Идея универсальной платформы
На первый взгляд, идея универсальной платформы имеет смысл. Можно найти несколько сильных аргументов в пользу разработки подобной стандартной общей платформы. Вот некоторые из них:
1. Разработка с нуля будет быстрее и легче.
Новые проекты будет значительно легче довести до рабочего состояния. Для них не надо будет писать кучу стандартного кода, все, что нужно они получат из платформы.
2. Формирование команд упростится
При наличии общей платформы станет легче перемещать разработчиков между командами. Ведь они будут уже знакомы с архитектурой.
3. Нас направят самые сильные и опытные профессионалы
Так как платформа будет спроектирована опытным архитектором (или архитекторами), она воплотит лучшую из возможных архитектур, а также обяжет реализовывать лучшие приемы разработки всех разработчиков, даже самых слабых, которые в противном случае могли бы уйти не туда.
Возможно, в последнем пункте я немного переборщил с сарказмом, но создание подобной платформы действительно кажется отличной идеей на бумаге.
Универсальная платформа на практике
В теории все звучит классно, но на практике все не так радужно. Я поделюсь реальными наблюдениями, которые сделал в реальных компаниях, которые находились на разных стадиях реализации своей универсальной платформы. Хочу сказать, что архитекторы и разработчики в этих компаниях были одними из самых крутых профессионалов, с которыми я когда-либо работал. Поэтому проблема однозначно заключалась не в нехватке опыта или профессионализма.
1. Разработка с нуля будет быстрее и легче.
Платформа действительно может ускорить реализацию начальной фазы нового проекта, но это ненадолго. Довольно быстро разработчики обнаруживают, что она наряду с преимуществами накладывает и свои ограничения. Вскоре разработчики нового проекта начинают планировать встречи с архитектором и командой платформы для того чтобы понять, как можно ее модифицировать, чтобы приспособить к нуждам своего проекта. Вы понимаете, что происходит? Платформа не только не подходит для нового проекта, новый проект начинает влиять на платформу. И это происходит с каждым проектом, который ее использует. В итоге мы получаем сильную зависимость между всеми проектами. Теперь представьте, что в один прекрасный день Вы в своем проекте обновляете версию платформы до последней и обнаруживаете, что весь проект сломан, потому что другая команда решила, что есть лучший способ управления транзакциями, или они поменяли DI контейнер, или что-то еще. Представили?
2. Формирование команд упростится
Это действительно работает в определенной степени. Различные проекты компании имеют схожую структуру, поэтому разработчикам легче переходить между ними. К сожалению, есть и обратная сторона монеты.
Худшее следствие заключается в том, что разработка становится везде одинаково медленной и сложной. Ведь платформа порождает межпроектную зависимость, когда любое ее изменение одной проектной командой влияет на все остальные команды. Также это значит, что при необходимости внести в нее изменение, это не произойдет быстро. Вы должны будете ждать, когда оно будет согласовано с архитекторами и другими тим-лидами.
Также я заметил, что наличие платформы усложняет для компании процесс найма новых разработчиков. Как правило, при развитии платформы резко растет ее сложность. Менеджеры мне часто жаловались, как трудно найти разработчиков, и даже после нахождения нужно 5 или 6 месяцев, чтобы от них появилась реальная отдача, и все потому что архитектура проекта очень сложна. Должна ли платформа быть такой сложной? Нет, но по некоторым причинам так всегда и происходит… что ведет нас к аргументу номер 3.
3. Нас направят самые сильные и опытные профессионалы
Платформа всегда создается лучшими разработчиками в компании. И это очень хорошо, так ведь? Нет. Здесь две большие проблемы.
Первая проблема заключается в различающейся мотивации. Когда команда разработчиков вместе работают над выпуском какого-то программного продукта, все мотивы их действий ведут к одной цели – выпустить этот продукт. И если выпуск продукта откладывается – это становится общей проблемой для каждого. Но когда Вы забираете из команд Ваших лучших разработчиков и говорите им, что теперь их цель – создать универсальную платформу, на которой будут реализованы все Ваши проекты, их мотивация становится совсем иной. Выпуск какого-то конкретного продукта теперь не является их проблемой. Теперь они озабочены такими вещами, например, как создание классной архитектуры, разработка новых техник моделирования бизнес-логики, исследование новых технологий, обучение других разработчиков тому, как надо пользоваться платформой и т.д. Суть в том, что возникает различающаяся мотивация.
Вторая проблема – это интересный феномен, который я назвал «Синдром крутого разработчика» («Smart Guy Disease»). Я встречался с ним много раз в разных компаниях. Заключается он в том, что самые фатальные ошибки, которые наносят наибольший ущерб компании, почему-то всегда делаются самыми лучшими ее разработчиками, а не посредственными. Если Вам это интересно, здесь я написал об этом целую статью.
Заключение
Создание собственной универсальной платформы может казаться «серебряной пулей» для руководства и архитекторов. Но я вас предупредил. Ведь так появляются монстры. Я ни разу не видел ни одной такой платформы, которая смогла решить больше проблем, чем те, которые уже были решены. Но я видел, как в двух случаях платформа привела свою компанию к очень тяжелому положению. Поэтому подумайте дважды, прежде чем идти в этом направлении.
Могу предложить такую альтернативу: создайте универсальную базу исходного кода. Но вместо того, чтобы наследовать и использовать ее в каждом новом проекте (что приведет к межпроектной зависимости), просто каждый раз делайте ее форк. В таком случае у Вас будет надежная стартовая точка, но при этом Вы свободно вносите изменения, не беспокоясь о том, как они отразятся на других проектах компании.
Комментарии (19)
SgtRiggs91
30.06.2015 21:08+2Опыт работы в одной крупной российской компании говорит, что всё именно так и есть. Зачёт, спасибо за перевод.
an24
30.06.2015 22:38+2Не так все однозначно. Если платформа применяется к узкому кругу задач, а не позиционируется как универсальная, то плюсы от ее применения перевешивают минусы. Другими словами, на платформе 1С можно эффективно решать учетные задачи, но не нужно писать сайты и порталы, писать драйверы устройств и т.д.
dmitry_hidden
01.07.2015 01:23+3Могу предложить такую альтернативу: создайте универсальную базу исходного кода. Но вместо того, чтобы наследовать и использовать ее в каждом новом проекте (что приведет к межпроектной зависимости), просто каждый раз делайте ее форк. В таком случае у Вас будет надежная стартовая точка, но при этом Вы свободно вносите изменения, не беспокоясь о том, как они отразятся на других проектах компании.
Если перенести это на ООП получается вы говорите не пользуйтесь наследованием, делайте копипасту )mapron
01.07.2015 06:29+1Форк я думаю все же позволит «мерджить» удачные изменения, в случае, если они ВСЕ ЖЕ ПОТРЕБУЮТСЯ в каком-то другом проекте.
А так…
Ну я попытаюсь перенести на ООП, то что пытался донести автор.
У нас есть волшебный класс TObject, который управляет деревом детей, сигналами/слотами и, например, логированием (понимаю что странно).
Он используется в двух проектах и все замечательно. Потом компания стартует третий проект с использованием этого же класса, который является веб-сервисом. И для поддержки RPC, класс TObject модифицируется. Сигналы-слоты теперь работают немного по-другому. Прогон тестов не выявил регрессий, но спустя месяцы от клиентов первых двух проектов приходят баги, на которые уходят уйма времени.bigfatbrowncat
01.07.2015 17:15+1А может просто надо в проектную документацию фреймворка включить некоторые принципы расширяемость и ограничения вида «данный фреймворк НЕ РЕШАЕТ задачу вида бла-бла. Эту часть делайте сами»?
По-моему, суть данной статьи сводится к утверждению:
«Если взять трех крутых чуваков и задать им написать универсальный крутой фреймворк, они потратят кучу времени, выдав продукт, из которого потом кучаобезьянпростых разработчиков сделают дрянь, модифицируя его в стиле „кто во что горазд“
И это, конечно, бывает, но выводы в статье феерические:
1. Не пишите крутые фреймворка (потому что их вам испортят эти… другие девелоперы)
2. Крутые фреймворка — зло!
А может быть решение другое? Может быть стоит нормально проектировать фреймворк и не позволять в него вносить изменения, которые сломают основные принципы его функционирования?mapron
03.07.2015 13:40Я в этом и не согласен с автором и согласен с Вами. Так что ничего добавить не могу)
areht
14.07.2015 10:58> А может просто надо в проектную документацию фреймворка включить некоторые принципы расширяемость и ограничения вида «данный фреймворк НЕ РЕШАЕТ задачу вида бла-бла. Эту часть делайте сами»?
То, в лучшем случае, ваш фреймворк прикрутят только для логирования, вынуждая новоприбывших учить его весь.
А в худшем… Вы всё равно не напишите список задачу он НЕ решает, и будет «да у нас почти тоже самое, надо только чуть-чуть допилить»…
> не позволять в него вносить изменения, которые сломают основные принципы его функционирования?
И он в принципе будет не нужен никому, кроме изначальных заказчиков, да и то только первые 3 года. Жизнь не статичная. У вас под каждый проект(если вы не 10 сайтов в неделю лабаете, конечно) будет свой фреймворк, только без копипасты.
Форк — это способ повторного использования кода с низкой связностью. Минусы тут следствие плюсов, баг исправленный в одной копии не чиниться в другой. Но для старого, отлаженного в бою, кода это не так страшно.bigfatbrowncat
14.07.2015 12:29И он в принципе будет не нужен никому, кроме изначальных заказчиков, да и то только первые 3 года
Если некая библиотека не может быть использована повторно в аналогичном проекте или расширена без модификации основного кода для включения дополнительных возможностей, значит она плохо спроектирована.
Большие фреймворки должны писать люди, которые способны их писать. Те, у кого не хватает на это способностей, не должны мнить себя гениями.areht
15.07.2015 03:52+1> Если некая библиотека не может быть использована повторно в аналогичном проекте
Конечно может. Аналогичного проекта не найдёте.
> или расширена без модификации основного кода
Это, кстати, весьма дорогое требование. Впрочем, расширяема она будет всё равно не там, где надо за любые деньги. Водопад — он и есть водопад.
> Большие фреймворки должны писать люди, которые способны их писать. Те, у кого не хватает на это способностей, не должны мнить себя гениями.
Сразу хочется спросить, достаточная ли у вас «способностей» для столь категоричных заявлений? Чем докажете?bigfatbrowncat
15.07.2015 11:41+1Чем докажете?
А кто вам сказал, что лично я претендую на подобное звание? А даже если претендую, с чего вы взяли, что я считаю себя уже достойным его?
Я отношусь с огромным уважением к людям, способным проектировать сложные системы правильно. Стремлюсь у них учиться с тем, чтобы однажды, если удастся, встать рядом с ними. Пока у меня это получается с очень переменным успехом — я стараюсь объективно оцениватьсвои результаты.
Но для того, чтобы утверждать, что «фундаментальное программирование» — удел далеко не каждого кодера, не обязательно быть Никлаусом Виртом. И не всякий, кто говорит «немногим дано» считает себя одним из тех, кому «дано». Вы меня неверно поняли.areht
15.07.2015 17:07> И не всякий, кто говорит «немногим дано» считает себя одним из тех, кому «дано». Вы меня неверно поняли.
Это вы меня неверно поняли. Я спросил какие у вас способности утверждать «немногим дано» и можете ли вы это доказать.
Резать правду-матку в интернетах — удел далеко не каждого.bigfatbrowncat
16.07.2015 00:41+1Вы всерьез полагаете, что утверждение «не всякому человеку дано создавать шедевры» нуждается в доказательстве?
Либо вы слишком оптимист, либо странно шутите.
*Ушел рисовать Джоконду и параллельно доказывать, что P=NP*areht
16.07.2015 10:36-1Ну если вы тукую простую вещь доказать не можете — что кто-то способен фреймворк создать вы тем более не докажете.
Ohar
01.07.2015 01:56создайте универсальную базу исходного кода
Сразу вспомнился Яндекс со своим универсальным БЭМ-набором блоков на все проекты.
darthandrew
01.07.2015 10:23Общий код (а лучше общие проекты сборок .NET с полезными автономными классами, компонентами ) — это правильно. Они должны быть максимально автономными, чтобы крайне нечасто хотелось там что-то править или улучшать. Но если «форк» — кроме защиты от того что «в них ничего не сломали» вы получаете еще и эффект «ошибки живут вечно, пока вы не смержите их исправление».
А вот если один из проектов требует нечто такое, что уже «не лезет» на платформу, то вероятно, это тот случай, когда от платформы именно на этом проекте нужно отказаться.
Юнит-тесты спасут, но у кого есть желание-время-деньги их писать?
bigfatbrowncat
01.07.2015 17:09+6Вторая проблема – это интересный феномен, который я назвал «Синдром крутого разработчика» («Smart Guy Disease»). Я встречался с ним много раз в разных компаниях. Заключается он в том, что самые фатальные ошибки, которые наносят наибольший ущерб компании, почему-то всегда делаются самыми лучшими ее разработчиками, а не посредственными.
Какое удивительное по своей тривиальности наблюдение! А чего вообще мог ожидать автор? Того, что серьезный судьбоносный просчет в архитектуре будет допущен нанятым вчера интерном? Почему специалист-разработчик не понимает, что наиболее серьезные ошибки всегда делают люди, на которых возложена наиболее серьезная ответственность?
Я всегда восхищался статьями вида «X — зло!», потому что их ценность обычно ровно такая же, как у статей «Делайте всё с помощью X». Но почему-то если вторые в сообществе считаются демонстрацией недальновидности автора, то первые активно тиражируются и всерьез обсуждаются.
Мы живем в мире, когда «всё уже написано». Если вы хотите использовать язык программирования C++, то для него есть stl и boost. Что? boost — зло? А может, вы его готовить не умеете? Или, скажем, библиотека (фреймворк) GLEW, которая грузит OpenGL и позволяет с ним взаимодействовать. Она универсальная. Зло? Или может ее заново переписать?
Всё в реальности определяется спектром задач и дизайном фреймворка. И если дизайн плохой, то результат будет плачевный. Также результат будет плачевный если взять инструмент и попытаться с его помощью решать не предусмотренную автором задачу. Я вслед за известным русским мыслителем называю это «проблемой мартышки и очков». Так что главное зло — люди, которые не умеют пользоваться вещами, а не те, кто эти вещи создает.
bratchikov
02.07.2015 09:17В некотором смысле универсальную платформу можно сравнить с языком программирования. Всем понятно, что язык должен проектироваться исходя из каких-то глобальных принципов и не поддаваться на провокации отдельных проектов, реализованных на нём. Тут, конечно, всё дело во внутреннем стержне менеджеров или архитекторов универсальной платформы и их прозорливости. Ведь одним из важных принципов является принцип — сохранения обратной совместимости. Даже если надо исправить ошибку в платформе, но если это исправление приведёт к вот этому эффекту у пользователей платформы:
в один прекрасный день Вы в своем проекте обновляете версию платформы до последней и обнаруживаете, что весь проект сломан
Тут надо трижды подумать что делать с этой ошибкой — быть может есть другой вариант решения, а сломать всё — последнее дело. Ещё один полезный принцип — открытость интерфейсов платформы. Если пользователю не подходит что-то из платформы — пусть напишет сам (возможно, хуже, но своё которое ему понятно как устроено).
capslocky Автор
02.07.2015 09:55Спасибо за комментарии! Тема довольно дискуссионная. Как переводчик, я не могу сказать, что разделяю всю оригинальную риторику автора, но в целом, критика именно «универсальных супер-платформ» обоснованная. Во всем должна быть мера, сами по себе платформы — не являются злом, но если они создаются, они не должны становится слишком универсальными и глобальными.
Alex_At_Net
Как тут не вспомнить «общую шину» :) www.ashmanov.com/pap/bubble#p4.9.2