От переводчика: Фокусом нашей компании всегда была именно разработка корпоративных приложений. В Haulmont мы занимаемся как созданием собственно приложений, так и инструментов, позволяющих разработчикам эффективнее решать задачи, связанные с разработкой таких систем. Например, наш фреймворк Jmix предназначен для корпоративной разработки, мы это заявляем в рекламе и анонсах. И конечно же, пройти мимо статьи с таким названием мы просто не могли. В Jmix есть все, чтобы сделать разработку корпоративных приложений интересной и успешной, кроме одного: он не может повлиять на людей, которые принимают решения о методах и процессах разработки. Почитайте статью, возможно, она заставит вас задуматься, о том, как можно поменять вашу корпоративную разработку, чтобы все участники были довольны.


На эту статью меня вдохновил комментарий на HackerNews, который я больше не могу найти. Суть его была такая: “В то время, как архитектура слишком проработана, код недоработан”. Если кто-то опознает автора, я с радостью проставлю его авторство.


Заранее в свою защиту хочу сказать, что этот текст описывает только мой опыт за последние 10 лет работы консультантом. Возможно, есть методики и фреймворки, которые решают проблемы, описанные ниже, но они либо не применялись, либо применялись неправильно.


Что такое корпоративная разработка?


Термин не стандартизован и часто используется по-разному в разном контексте. На мое понимание того, что такое корпоративное программное обеспечение, сильно повлияло определение Мартина Фаулера из книги “Шаблоны корпоративных приложений” (2002, Addison Wesley).


  • Разработано для внутреннего использования в организации


  • Работает со сложными данными, которые хранятся в разных источниках


  • Работает со сложными бизнес-правилами


  • Обычно — многопользовательское (что означает одновременное использование)


  • Обычно интегрировано в общую корпоративную IT среду



Разработчики в разговорах зачастую преуменьшают значимость работы над корпоративными приложениями. Конечно, эти проекты не приводят к появлению новейших технологий, в них не будет разработан новый кодек потокового вещания и в них не используется блокчейн (а он вообще ещё используется?).


Но, в то время как на поверхности разработка корпоративного ПО выглядит тривиально, по сути, оно включает в себя решение весьма сложных проблем относительно работы с данными. Разработчики вынуждены работать с большим количеством данных из разных источников.


Каждый источник может определять одну и ту же сущность в своем домене, которая совсем чуть-чуть отличается от определения в другом домене. И это делает трансформацию данных между доменами весьма сложной задачей.


Вдобавок к этому, разработчикам необходимо принимать во внимание тонны сложных бизнес-правил, количество которых в системе постоянно растет.


Проблемы с разработкой программного обеспечения


Я принимал участие во многих проектах разработки корпоративного ПО в качестве внешнего разработчика и консультанта и часто видел, как проектные подходы мешали достижению цели создания ПО. По моему мнению, проектный подход — неподходящая среда для создания отличного программного обеспечения. Основные атрибуты проекта:


  • Ограничения по срокам и бюджетам


  • Команда формируется только на ограниченное время



Задача менеджера проекта — убедиться, что проект достиг целей за заданное время и бюджет. Если это как-то достигнуто, то проект считается успешным. Бюджет зачастую фиксирован, равно как и набор целей, которых нужно достичь.


Первый фундаментальный недостаток для меня — это фиксированный срок окончания, что подразумевает, что ПО “готово” в какой-то момент времени. Обычно это “решается” разделением разработки на “фазу проекта” и “фазу поддержки”. Когда проект "завершен", команда разработчиков обычно распускается и ПО передается “команде поддержки” (обычно с большой долей джунов).


Выгода такого подхода в том, что проектная команда должна тщательно задокументировать продукт, перед тем как передать его (В теории. Иногда эта часть проекта пропускается, потому что заканчивается бюджет). И это приводит ко второй проблеме в проектном подходе: в процессе передачи программного обеспечения другой команде теряется большое количество знаний.


Чтобы избавиться от недостатков проектного подхода, многие компании пытаются внедрить гибкие фреймворки, в основном SCRUM. Лично я никогда не видел SCRUM или другую гибкую методологию, которая бы работала при проектном подходе. Хотя я субъективен, потому что компания, которая по-настоящему живет ценностями гибких методологий разработки, никогда не будет делать программное обеспечение в рамках проектного подхода, и уж точно не с внешним консультантом. В таких компаниях понимают, что их ПО — это продукт, который нужно постоянно развивать.


Стандартизация


Принимая во внимание проблемы, описанные выше, одной из главных забот во всем цикле разработки корпоративного ПО становится избегание “сюрпризов” в коде. Если код был передан новой команде проекта или команде поддержки, он должен быть понятным, чтобы новая функциональность или исправление были внесены с наименьшим количеством усилий. Основной инструмент для этого — стандартизация.


В больших корпорациях для этого зачастую существует команда “Корпоративной Архитектуры”, которая сидит выше всех проектных команд и стандартизирует процессы разработки. Какой язык использовать? Какие фреймворки и библиотеки разрешены? Какой технологический стек требуется, какой подход для тестирования? Какие архитектурные правила необходимо соблюдать? Эта макро-архитектура зачастую описана с потрясающим уровнем детализации.


И, до определенной степени, это имеет смысл: если разработчики используют проектный подход, им приходится работать с разными кодовыми базами с течением времени. Команда поддержки может отвечать за несколько разных приложений одновременно. Если разработчики “чувствуют себя как дома” во всех этих приложениях, т.е. они моментально распознают структуру и технологии, то они могут начинать работать над ними значительно быстрее.


Самое сложное — избегать создания слишком большого количества правил. Я работал на клиентов, которые специфицировали конкретную версию Spring Boot, которую надо использовать. Если архитекторы меняли версию, то вся компания принудительно переходила на новую.


Я работал на клиентов, которые предписывали использовать Hibernate только с HQL, обычный SQL был под запретом, равно как и другие фреймворки, использование проекций и POJO.


“За” такой подход было то, что разработчикам не нужно было осваивать SQL, а способ доступа к БД был стандартизирован. Но, конечно же, это приводило к тому, что производительность была не на самом высоком уровне в большинстве приложений. Кроме того, фирменные особенности дорогущей СУБД Oracle Enterprise не могли быть использованы.


Но даже когда эта стандартизация приводила к огромным проблемам в проектах, с архитекторами нельзя было спорить. Нытьё разработчиков — это не повод ломать Архитектуру, не так ли?


Многоуровневая архитектура


“Золотой стандарт” стандартизации — многоуровневая архитектура. Следуя определению Фаулера из книги “Корпоративные шаблоны проектирования”: слои — это техника разбиения сложного программного обеспечения на составные части.


В теории, вынесение работы с данными, бизнес-логики и представления в разные слои упрощает работу с приложением. Каждый из них должен знать только о слоях ниже, т.е. бизнес-логика знает только про слой работы с данными, но не знает, что ее вызывает: REST сервис, веб приложение, графический клиент или утилита командной строки.


Это не только структурирует приложение, делая его простым для понимания, но и затрудняет смешивание различной функциональности. Однако, это также разделяет бизнес-логику на разные поддомены, что может повлиять на производительность, т.к. для перемещения данных между доменами требуются их преобразования.


Почему это все приводит нас к недоработанному коду?


Чем больше зарегулирована среда для разработчика, тем более недоработанным становится код. Для меня, недоработанный код — код, который мог бы выполнить задачу быстрее, с меньшим количеством строк кода или меньшим дублированием.


Из примера выше: если разработчикам запрещено писать SQL, они будут ограничены только HQL. Это выльется в более медленные запросы или большее количество запросов в сравнении с SQL для выполнения одного и того же задания.


Если подробно расписано, какой язык, фреймворк или библиотеку использовать, то разработчики иногда вынуждены изворачиваться, чтобы решить поставленные задачи вместо того, чтобы использовать наиболее подходящий инструмент.


Если до фанатизма следовать многоуровневой архитектуре, то 50% вашего кода будет представлено мапперами данных для передачи между слоями. Если вы всегда будете помнить о том, что рано или поздно наступит "тот самый" ужасный момент передачи кода в другую команду по окончании проекта, то вы будете осторожнее и начнете избегать лучших решений в пользу более понятных.


Последствия для разработчиков


Разработчики, которые работают в такой зарегулированной атмосфере довольно долгое время и каждый день пишут недоработанный код, теряют мотивацию и перестают изучать что-то новое.


Я сам был в этой шкуре: когда получаешь задачу на реализацию новой функциональности, обычно склоняешься к написанию наиболее простого кода, отметая более эффективные пути решения, потому что опасаешься, что более сложный код не будет понят командой поддержки, которая вскоре заберет проект.


Все обсуждения пулл реквестов сводятся к выяснению, действительно ли нужна абстракция для этой функциональности, не был ли слишком экзотическим примененный шаблон или не был ли SQL слишком сложным. Не слишком ли твой код отходит от стандартов.


В конце-концов тебе становится все равно, есть ли лучший способ решения проблемы, ты автоматически выбираешь самый очевидный и простой способ. Ты перестаешь расти и становишься плохим разработчиком, который пишет код “по наименьшему общему кратному” для всех. Ты становишься ленивым.


В этих энтерпрайзных проектах “элегантный” и “умный” код — завуалированное оскорбление, которое я начал использовать, спустя некоторое время. Но ведь нет ничего плохого в написании такого кода. Если он решает проблему как нужно, это нормально, чтобы другие разработчики подумали про этот способ. И можно даже документировать этот код, чтобы немного упростить им задачу ????


Как улучшить ситуацию?


Относитесь к программе, над которой работаете, как к продукту, не как к проекту. Потом вы можете убрать некоторые детали из вашей макро-архитектуры. Если над проектом работает одна и та же команда долгое время, они могут “рискнуть” и специализироваться на своей технологии, выбирая наиболее подходящие под задачи инструменты и архитектурный стиль. Они могут добавить “риска” и написать более сложные алгоритмы, используя менее известные особенности языка. Знание останется в команде, останется и сама команда.


Хотя микросервисы сейчас далеко за пиком кривой хайпа, можно их использовать, чтобы достичь именно этого результата. Это не значит, что одна команда может запускать приложения на Go на Heroku, другая — PHP приложения на своем собственном сервере, а третья — Java приложения в kubernetes. Командам придется договориться о каких-то общих стандартах. Но их нужно не так много, как вам кажется.

Комментарии (16)


  1. Myclass
    16.09.2021 12:31
    +2

    Для менеджеров любого уровня просто не интересно находиться в одной комнате с собственными представителями какой либо корпоративной разработки.

    С представителями других фирм можно красиво посидеть, кофе с печеньками попить, по-болтать о гольфе, инвестициях, к ним командировки тонной напланировать, ещё лучше, если это другая страна итд...


  1. dtfkalalka
    16.09.2021 12:39
    +6

    Заголовок желтушный. Название должно быть - "Большие проекты убили вузовскую романтику". У автора всегда есть выбор - 400к в Амазоне, либо 70к в обычной компании из 20 человек. В линкедыне у автора какие-то полу-лид-консультант на Коболе и Джаве. Очередной разрушитель корпораций, который не смог вписаться в среду. Да, я вижу, что это перевод.


    1. aleksey-stukalov
      16.09.2021 13:11
      +2

      Ну это перевод заголовка... Но ваш однозначно забористей!


  1. CrazyScientist
    16.09.2021 12:44
    +3

    Вообщем то реализация задачи простейшим методом - это лучшее решение почти всегда. Не зачем усложнять, терять надёжность, повышать вероятности ошибок как в процессе написания, так и в процессе поддержки.


    1. Myclass
      16.09.2021 12:51

      Вы правы. Но в теории. А в жизни раскажите это тем, у кого есть свой бюджет, и который надо обязательно освоить…


    1. a_belyaev Автор
      16.09.2021 13:04
      +4

      Не простейшим. Понятным. Или хорошо задокументированным. Утрируя: если быстрая сортировка нам сэкономит вагон денег, готовы ли мы пожертвовать пузырьком? Или таки наймем людей, которые смогут читать и поддерживать быструю сортировку?


      1. ApeCoder
        17.09.2021 08:27
        +1

        Для конкретного продукта пузырька либо достаточно либо недостаточно. Если недостаточно, то наймут квиксортеров и так и будут поддерживать квиксорт. Если достаточно, зачем нанимать квиксортеров.

        А еще я против того, чтобы поддержка фиксила баги. Продуктовую команду надо тыкать носом в их какашки и пусть они учитывают их на будущее.


    1. dtfkalalka
      16.09.2021 13:13

      Но ты же не ответил на вопрос. Ты просто написал "лучше хорошо, чем плохо". И сидишь - собираешь лайки от безработных студентов и реакт-кодерков. У тебя в задаче нужно хранить куча настраиваемых параметров. У тебя 2 выбора - константы в коде иди БД в соседнем репозитории, который тоже нужно покрывать тестами и делать PR's. Потом еще делать PR's в конфиги с заглушками. И только потом твой основной PR. И это всё из-за того, что продукт в 1кк строк кода и нужно много метрик по аналитике и остальному. Ну, студент-пузырёк за вечерок, что будешь делать?


      1. a_belyaev Автор
        16.09.2021 13:19
        +1

        Конфиг сервер же! :-)


    1. tzlom
      17.09.2021 00:23
      +2

      Простейший по каким критериям? Нужно извлечь список пользователей- что проще, ORM или SQL? Что бы вы не выбрали всегда можно добавить требование которое сделает другой вариант простейшим. А это вырождается в зоопарк "тут было быстрее с SQL поэтому переложи свой список доменных объектов в список айдишников" ну и наоборот. Потом приходит архитектор который код уже 10 лет не писал и заявляет что все проблемы от отсутствия единообразия и вообще все объекты теперь храним как JSON потому что их так перекладывать легче.

      Идти по пути наименьшего сопротивления это очень естественный процесс, однако не удивляйтесь что попадете вы только в локальный минимум.


    1. F0iL
      17.09.2021 08:58

      Многие задачи простейшим методом решаются "в лоб" так называемыми наивными алгоритмами. Код действительно будет очень простой, короткий и понятный всем. Вот только вычислительная сложность у таких алгоритмов может оказаться квадратичная или даже еще больше, чем обеспечит вам тормоза на сколь-менее серьезных объемах данных.

      Или, например, простейшим методом часто будет считать все в один поток. Но часто это дико неоптимально и неэффективно. Использование многопоточности сильно отдаляет нас от "простейшего метода". В некоторых случаях наоборот простейшим методом будет создавать отдельный поток на каждый чих (например, на каждое соединение), но, опять же, это может оказаться тоже дико неэффективно, асинхронный код будет гораздо оптимальнее, но в зависимости от языка (например, если async/await не завезли), совсем не простым.

      Простейшим методом обычно оказывается "херак-херак и в продакшн", быстро накидали, что-то вообще захардкодили, прибили все друг к другу гвоздями и полетели. А вот если вам захочется избежать ошибок как в процессе написания, так и в процессе поддержки, вам придется делать более расширяемую архитектуру и писать тесты, а для этого понадобится все сделать уже не "простейшим методом", а по уму -- с интерфейсам, dependency injection, отсутствием жестких связей, упомянутым разделением на слои, меньше захардкоденых вещей, больше гибкости. Хотите надежнее, поддерживаемее и с меньшим количеством ошибок -- простейший метод уже не подойдет.

      В конце концов, сравните классический Си и Rust. Си -- язык максимально приближенный к железу, и он сам по себе очень даже простой. В Rust гораздо больше сущностей, больше правил, нужно понимать больше вещей, чтобы на нем писать, иногда вам придется воевать с borrow checker'ом. Но "простейшим методом" на Си вы весьма вероятно в итоге все-таки где-то выстрелите себе в ногу, а Rust вам наоборот будет изо всех сил не давать наделать ошибок.


  1. lair
    16.09.2021 13:10
    +10

    Энтерпрайзные проекты убили профессию разработчика

    Огляделся вокруг, увидел кучу людей на профессии "разработчик".


    "Слухи о моей смерти преувеличены".


  1. corporaldev
    16.09.2021 19:04
    +1

    Есть противоположное мнение. Стандартизация ничего не убила, а сделала отрасль более доступной для более широкой аудитории.


  1. anonymous
    00.00.0000 00:00


  1. cdmnk
    17.09.2021 12:14
    +5

    Автор противопоставляет стандарты и своё желание доводить код до предельной оптимизации. Результат почти всегда находится где-то раньше по времени, чем максимальная оптимизация, и она попросту не нужна никому кроме разработчика. У каждого свои приоритеты, у меня вообще читаемость кода, а по теме статьи отвечу цитатой:


    Преждевременная оптимизация — корень всех зол. © Дональд Кнут


    1. solver
      26.09.2021 21:40
      +3

      Преждевременная оптимизация — корень всех зол. © Дональд Кнут

      Цитата шикарная, слов нет. Вроде всё по делу сказано.

      Только вот в реальности, люди прикрываясь этой цитатой пишут просто отвратный код. Потом ведь оптимизируем, когда поймём где оптимизировать. Опять всё логично, сначала ведь надо понять, где оптимизировать...

      Проблема только в том, что в подавляющем количестве случаев "потом" не наступает. И никто не разбирается где надо оптимизировать. Не то что не знает как, а просто у него уже другие задачи. Хотя большинство и не знает как) И до оптимизации доходит только когда, условно, "прод падает".

      Так вот и живем с этим уже много лет. 8 ядер по 2.2Ггц + 8Гб памяти в моём свежем андроиде с трудом могут отрисовать плавно скроллинг смс-ок. Странички с обычным контентом на сайте ставят на колени Core i7 и отъедают гигабайты памяти. Приложения жиреют в нехилой прогрессии не добавляя особо функционала... и т.д. и т.п.

      А зачем оптимизировать-то? Вот когда жареный петух клюнет, тогда и займёмся, а пока не надо. Просто докупите памяти, новый мобильник или сервер...