Корпоративные приложения (enterprise)

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

Чем отличаются корпоративные приложения от обычных? Есть несколько параметров, по которым их можно отделить от остальных.

Отличительные черты:

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

Краткая справка по ролям в команде:

  • тимлид (производное от team leader) – руководитель команды разработки, обычно опытный разработчик в прошлом, которому надоело писать код. Он занимается общением с клиентом (часто обсуждает с ним конкретные детали ТЗ), видит всю картину разработки проекта и принимает решения по найму и увольнению членов команды, а также иногда влияет на архитектуру. В небольших командах тимлид, обычно,  берет на себя обязанности техлида.
  • техлид (производное от technical leader) – технический лидер, один из самых опытных разработчиков в команде. Видит и определяет всю техническую сторону разработки. При необходимости, общается с клиентом и доменными экспертами для уточнения ТЗ. Занимается архитектурой проекта, вырабатывает требования к коду и помогает выбрать более подходящее решение для других участников команды.
  • бэкендер (производное от backend developer) – разработчик серверной части приложения со знаниями Java, C#, PHP, Ruby, Python, SQL, инструментов кеширования и т.д.
  • фронтендер (производное от frontend developer) – разработчик клиентской части приложения со знаниями JavaScript, HTML/CSS и смежных языков.
  • тестировщик – собственно тестировщик, его знания зависят от области (модульные, функциональные или приемочные тесты) где он работает и как тестирует. Обычно занимается проверкой функций, созданных фронтендерами и бэкендерами.
  • веб-дизайнер – проектировщик и художник веб-интерфейсов, который не только красиво рисует пользовательские интерфейсы, но и многое знает о юзабилити.
  • верстальщик – в большинстве своём, это фронтендщик, умеющий переводить изображения (например, psd-макеты) от веб-дизайнеров в HTML/CSS код.
  • системный администратор – часто, бородатый дядька с глубокими познаниями в операционных системах семейства Linux и легкой привязанностью к пиву  Занимается настройкой веб-серверов и последующим мониторингом их работы. Если чего-то не хватает на сервере или что-то сломалось, сразу идем к нему.
  • администратор баз данных (DBA) – разработчик специализирующийся на обработке большого количества данных. Имеет глубокие познания о внутренних процессах СУБД, хорошие навыки проектирования структуры баз данных и написания процедур и функций на стороне БД. Большую часть времени занимается мониторингом нагрузки на базы данных и, иногда, указывает бекэндерам на медленные запросы, которые желательно переписать или вообще избавиться от них.
  • доменные эксперты – обычно, действующие сотрудники компании для которой разрабатывается система. Они знают как работает компания сейчас, но в подавляющем большинстве случаев ничего не знают о разработке программ, т.к. это не их область. Без этих людей бывает крайне сложно понять, как должна работать система.

Помимо четырех особенностей проектов выше, есть еще три, которые вытекают из предыдущих:

  • Наличие тестовых серверов. Бизнес не может простаивать из-за технических причин (ошибок в коде, несоответствию функционала техническому заданию и т.д.) и, перед публикацией кода на основные сервера, тестировщики должны тщательно проверить релиз. Причем, чем масштабнее бизнес, тем тщательнее производится проверка, т.к. ошибки могут привести к большим финансовым потерям.
  • Использование систем управления проектами, наподобие Redmine, Trello, Jira, Битрикс24 и так далее. Во множестве больших проектов, в которых я принимал участие использовался Redmine. С его помощью легко уживалась команда разработки численностью около 30 человек.
  • Игнорирование модных трендов в разработке. К примеру, в году 2014 было модно, везде где не попадя, использовать NoSQL базы данных. Такие тренды при разработке крупных проектов следует игнорировать, так как тренды поменяются, а проект с модной ранее технологией останется и доставит множество неприятностей разработчикам.

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

Архитектура

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

У большинства веб-проектов в основе архитектуры лежит составной шаблон проектирования MVC и его модификации. Он подразумевает разделение кода приложения на три части – бизнес-логику (модель), логику работы приложения (контроллер) и отображение результатов работы двух предыдущих компонентов (представление). Задача архитектора веб-приложения, в большинстве случаев, постараться подогнать MVC под конкретный проект (его требования) и, особенно, его главную часть – модель. Полученную архитектуру в текстовом виде желательно поместить в файл с “Дополнительными материалами” для проекта, чтобы каждый разработчик мог ознакомиться с ней. Что поместить в файл под названием Архитектура.md? Если вы никогда не делали этого раньше, то в первый раз это будет довольно сложно. В верхней части документа можно поместить краткое описание системы и её предназначение, например:

CRM для ООО “Супергипермаркет”

Данная CRM обеспечивает работу следующих отделов: продаж, кадров, погрузки, бухгалтерии и обзвона клиентов, а также предоставляет API для товаров и доставок клиентам.

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

Контроллер (controller из model-view-controller) должен заниматься только принятием данных из запроса пользователя (имеется ввиду HTTP-запрос) для передачи в слой модели для обработки и, при необходимости, передачей слою представления для приемлемого отображения пользователю.

Модель (model из model-view-controller) – должна состоять из сущности (в Laravel и Yii они представляют из себя ActiveRecord-класс) с минимальным количеством кода (геттеры и сеттеры + простой функционал, например: $user->isActive()) и из класса-сервиса, хранящего в себе бизнес логику. Причем, класс-сервис может работать сразу со множеством сущностей. Если для проекта нужны модульные тесты, то добавляем: для облегчения написания модульных тестов все зависимости классов-сервисов должны создаваться через DIC с использованием интерфейсов. Если для некоторых сущностей проекта требуется отвязка от конкретного хранилища, то следует использовать шаблон Хранилище.

Представление – html/css файл (возможно с шаблонизатором, зависит от проекта), который пользуется только теми данными, которые передал контроллер. Для подавляющего большинства проектов это правило облегчало жизнь, все данные лучше получать в контроллере и передавать их в представление.

Представление не должно обращаться ник к контроллеру ни к классам модели.…

Что еще можно добавить в файл с описанием архитектуры? Все, что считаете нужным (способы добавления модулей, примеры абстракций, добавление поддоменов, варианты кеширования, способы использования очередей и т.д.). Как вы понимаете, для конкретного фреймворка нужно привести пример, как это лучше сделать. Для разных фреймворков лучшие практики будут отличаться. После нескольких проектов с подобным планированием архитектуры, вы будете все четче и четче формулировать требования к коду проекта, выбирая наиболее подходящее решение и описывая его более понятным языком для других разработчиков.

Множество тимлидов часто игнорирует архитектуру, а зря. Представьте себе, что есть строительная организация в которой работает сто строителей и эта сотня умельцев строит здания без всяких правил, то есть каждый строитель сам выбирает материалы, способ укладки кирпичей и так далее. При строительстве домов такая ситуация кажется дикой, так как это может привести к трагедии (дом обрушится, возможно, кто-то пострадает). Но, почему-то, такая же ситуация становится не очевидной, когда мы переходим в область разработки больших программных продуктов.

Документация и сказки про самодокумендируемый код

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

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

По своему опыту могу сказать наверняка, doc-блоки к каждому своему классу и методу этих классов, сэкономят огромное количество времени вам и вашим коллегам при поддержке проекта. Когда вы создаете большой проект с большим количеством сущностей и десятком модулей, вам кажется, что вы будете понимать как работает система всегда, точно так же как и сейчас, но это обманчивое впечатление. Со временем большинство информации выветрится и появятся проблемы с понимаем происходящего в системе. Час, потраченный на создание документации (просто doc-блоков, которые описывают то, что делает метод), сэкономит десятки, а то и сотни часов в будущем.

Стоит отметить, что большое количество крупных проектов на PHP стали появляться на так давно, лет 10 назад. Поэтому на таких языках как Java или c++ “кровавые энтерпрайзы” намного “кровавее”. По рассказам моих знакомых, на Java и c++ можно встретить код 20-летней давности 

При работе в команде я интересовался тем, почему некоторые разработчики не пишут doc-блоки (классов, методов, констант и т.д.). И, иногда, выяснялось, что некоторые разработчики просто не знают как лучше написать doc-блок к классу или методу и, чтобы не выглядеть глупо, не делают этого. Мне кажется, что наличие неумело написанного комментария гораздо лучше его полного отсутствия.

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

Документирование кода дает еще один плюс – когда вы описываете назначение какого-то класса или метода, вы как бы смотрите на него со стороны и, иногда, понимаете, что нужно бы выделить какой-то метод в отдельный класс или вообще, что писать его не нужно. Попробуйте, в самом начале будет сложновато создавать вразумительные doc-блоки, но, со временем, вы и ваши коллеги получите пользу от этого дела.

Сохранение важных частей переписки

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

Вопросоответник.txt

> РАЗРАБОТЧИК(год.месяц.день.время):

Нужно ли давать менеджеру возможность редактирования анкеты пользователя?

< ЗАКАЗЧИК(год.месяц.день.время):

Нет, ни в коем случае! Мы забыли указать это в ТЗ.

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

Стандарты написания кода

Для обеспечения единого стиля кода удобно использовать общепринятые стандарты, чтобы разработчики не тратили время на придумывание своих. В большинстве своих проектов я ориентируюсь на php-fig.org/psr.

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

Стремление к простоте кода

Простой код писать предпочтительнее сложного. На первый взгляд это очевидно, но на практике часто выходит наоборот. По своему опыту скажу, что этого не понимает или не принимает часть взрослых (30-50 лет) и опытных разработчиков. Отчасти, по этой же причине, они не пишут doc-блоки к классам и методам. Корпоративные проекты будут жить большое количество времени и чем проще будет код, тем лучше.

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

Часть опытных разработчиков редко задумывается о том, что читаемость кода является одной из двух главных характеристик, первая – работоспособность, вторая – читаемость. Причем, иногда читаемость бывает намного важнее работоспособности. Но как так спросите вы? Если код не работает, то он не нужен. Опять же, и да, и нет. Если написано много рабочего кода (пусть будет 100% от текущего ТЗ), но абы как, то скорость последующей доработки проекта будет низкой, да и писать вы будете скрепя зубами. А если проект написан хорошо, но пока не доведен до конца (пусть будет 95% от текущего ТЗ), то его можно быстро доделать и последующая доработка будет идти с приемлемой скоростью для заказчика и с удобством для команды разработки. Повторюсь, читаемость кода – это один из самых важных показателей больших проектов.

Описание всех таблиц, процедур и функций системы в SQL-виде

Это скорее рекомендация, чем правило. Часто при написании запросов, да и при знакомстве с системой в целом, удобно иметь под рукой актуальную структуру базы данных и код всех хранимых функций и процедур. Если в вашем проекте имеется sql-файл со всеми запросами для создания таблиц, то, скорее всего, новые разработчики не будут ломиться к вам в мессенджер для того, чтобы узнать для чего нужно поле xxx в таблице yyy. Пример файла:/** * СПИСОК ВСЕХ ТАБЛИЦ: * — пользователь (user). * … */— Пользователь.CREATETABLEUSER( id INTEGERUNSIGNEDNOTNULLAUTO_INCREMENTPRIMARYKEY, — Идентификатор. city_id INTEGERUNSIGNEDNOTNULL, — Идентификатор города. … created DATETIME NOTNULL, — Дата и время добавления. updated DATETIME NOTNULL— Дата и время обновления. ); …

Сломанные миграции

Миграции – отличный инструмент командной разработки, с помощью этого механизма разработчики меняют БД не только у себя на локальной машине, но и у коллег. Но, иногда, механизм миграций на больших проектах начинает буксовать и становится чисто номинальной вещью, а то и вообще перестает использоваться в ходе разработки. Его заменяют на создание дампов и переброску по тому же телеграмму и скайпу. Такие проекты мне попадались. Почему миграции переставали использовать? Потому что миграции переставали быть самодостаточными, т.е. в них использовались данные из других файлов, например, константы из конфигураций, AR-моделей и так далее, которые в ходе разработки исправлялись или удалялись. Таким образом, миграции приходили в негодность. Поэтому, постарайтесь делать миграции самодостаточными, т.е. они не должны ни коим образом зависеть от внешних файлов. В крайнем случае, если необходимо использовать значение какой-либо константы, то используйте значение константы вместо неё, и напишите в комментарии рядом об этой константе, не забыв указать причину её использования.

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

Тестирование

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

Стандартное лучше нестандартного

В случае корпоративного приложения нужно четко понимать, что это не курсовая и не дипломный проект, в котором нужно себя проявить. Это приложение, которое будет жить очень долго и его код следует делать максимально понятным для упрощения жизни другим разработчикам. Что это значит? Это значит, что для разработки предпочтительнее использовать те практики, которые считаются стандартными для какого-либо фреймворка или библиотеки. Например, недавно мне попался проект на Yii2 в котором использовались env-файлы (как в Laravel) для конфигурации вместо стандартной конфигурации приложения через массив. Так делать не стоит, потому что это может запутать разработчиков в будущем. Представьте ситуацию, лет через 10 фреймворк Yii и библиотека DotEnv выйдут из употребления, а проект останется и его нужно будет поддерживать. Разработчик, не знающий эти инструменты, начнет сначала читать документацию по Yii и увидит там совсем другой способ конфигурирования проекта. Это может усложнить его работу.

Правда лучше молчания

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

«Костыль» – на сленге разработчиков означает, что выбрано явно неудачное решение из-за незнания того, как лучше сделать или по причине отсутствия времени на реализацию хорошего решения.

Желательно оставлять TODO пометки для «костылей», так про них не получится забыть и, возможно, ваши коллеги найдут решение для проблемы, взглянув на неё со своей стороны.

Коммиты

Этот пункт не правило, а скорее совет. Коммиты можно создавать с различными пометками, например:

  • символ [db] в начале коммита означает, что в структуру таблиц внесены изменения;
  • символ [*] означает рефакторинг, т.е. в функционал не было внесено изменений, а была улучшена читаемость и поддерживаемость кода.

Сами коммиты бывает удобно дополнительно помечать номерами найденных ошибок или задач и связывать их с системой управления проектами, например, с Redmine. В этом случае комментарий для коммита будет состоять из номера ошибки или задачи, например: #3892.

Тимлидство

Успех проекта во многом зависим от человека возглавляющего разработку. Тимлид – руководитель команды разработки, на долю которого выпадает не только самая большая зарплата и самостоятельный выбор дел для себя и всех остальных членов команды, но и такая сложная (на мой взгляд) вещь как управление штатом и, в частности, увольнение неподходящих членов команды, которые не в состоянии выполнять требования проекта из-за неопытности или особенностей характера.

Большинство тимлидов, с кем мне приходилось работать – умные и опытные разработчики, да еще и приятные в общении люди, которые любят делиться своим опытом. Часть советов из этой статьи я почерпнул из общения и опыта работы с ними. Выбор тимлида – это первый и, наверное, главный этап в разработке большого проекта.

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

Техлидство

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

Представьте себе, что в вашем проекте 10 больших модулей (личные кабинеты, различные API, подсистемы и т.д.) и 9 из этих модулей писали ваши коллеги.  Один из ваших коллег уезжает в отпуск. Вам нужно залезть в его модуль и добавить новый функционал. Этот функционал срочно нужен для проекта. Есть два основных варианта развития событий, первый – ваш коллега придерживался единого стиля кодирования и архитектуры, второй –  он программировал так, как считал нужным, не считаясь с правилами (размещал бизнес-логику где хотел, вытаскивал статические методы в представление и т.д.). Теперь ответьте на вопрос, с каким кодом вам приятнее будет работать и в какой из двух предложенных ситуаций вы быстрее выполните задачу? На мой взгляд, ответ очевиден, если все разработчики придерживаются единой концепции решения задач – единой архитектуры, то каждый из разработчиков проекта заранее будет знаком со всеми модулями, так как все разработчики пишут по единым правилам. Каждый разработчик будет знать где лежит бизнес-логика, где хранить данные для формы, как производить фильтрацию входящих данных и так далее.

Одними из главных результатов работы техлида должны быть (на мой взгляд) три вещи: 1 – продуманная архитектура проекта основанная на его потребностях, 2 – принятые и исполняемые стили кодирования и 3 – документация.