Что нужно сделать для того, чтобы проект можно было разрабатывать небольшой командой?
В этом моменте я считаю, что у вас уже есть техзадание или представление о том, как должен выглядеть конечный результат.
Первым и важным шагом к командной разработке является сформулированный концепт или дизайн верхнего уровня, если можно так выразиться. Когда работаешь один, ты все время держишь в голове общую картину: какое приложение должно появиться на выходе, из каких модулей оно будет состоять, какие вообще критерии качества и законченности есть у проекта. Когда работаешь в команде, важно, чтобы это представление было консистентно для всех участников разработки. Например, разделение на модули "Логина юзера", "Корзины заказов", "Главного списка товаров", и тд. То есть это должно быть задокументировано и зафиксировано. Этот документ и все следующие можно положить рядом с исходным кодом.
Когда модули определены, важно зафиксировать способы, как они между собой взаимодействуют. Хотя бы в общих чертах. Это нужно для того, чтобы написание модуля было более-менее изолированной задачей. Например, вы раздаете ответственности за эти модули своим коллегам и вдруг один из них не справился - при этом желательно, чтобы фейл одного разработчика оказал минимальное воздействие на остальные модули, ну и зафейленный модуль можно было бы просто переписать заново, не трогая кодовую базу остальных модулей.
Скорее всего, когда вы будете писать модули, вы будете использовать какой то общий код, общую библиотеку, например для логгирования, для обращения к БД, для управления доступом юзеров. Это очень важная часть, я бы рекомендовал это доверить самому опытному разработчику (или разработчикам). Здесь также можно посоветовать заранее подготовить уже программный интерфейс (то есть просто сесть, и, совместно с командой, накидать интерфейсы таких сервисов). Имея заранее подготовленные интерфейсы, обязанности по имплементации этих интерфейсов вы уже можете разделить между разработчиками. Иметь интерфейсы в этом случае очень важно, так как
- Эти сервисы затрагивают все модули, а значит фейл в сервисе означает переделку всех модулей. Имея интерфейс, мы декларируем возможности сервиса, но фейл при имплементации будет локализован, а сама имплементация сервиса может быть заменена.
- Наличие интерфейсов core сервисов позволяет начать разработку модулей немедленно. Нет смысла ждать имплементации, когда есть интерфейс, который, если имплементация не готова, всегда можно закрыть моком/стабом/фейком.
Эта задача также для группы или для самых опытных разработчиков - подготовить примерный концепт или пример реализации модуля. Цель этого - показать шаблон для других разработчиков, как писать ваши модули, из каких частей они должны состоять. Например, если вы планируете 3-уровневую архитектуру, то вы можете продемонстрировать, как её реализовывать в сопряжении описанных выше core сервисов. Кстати говоря, тут вы и делаете выбор по вашей архитектуре, будет ли она состоять из слоев или представлять собой CQRS или что то иное.
Итак, у вас есть интерфейсы основных сервисов, у вас есть высокоуровневая архитектура. Теперь вы можете приступить к списку задач. Список задач нужен для многих вещей, например, чтобы знать примерный объем работы. Формируйте список задач вместе с командой. Важный момент здесь - чтобы каждый член команды понимал для чего так или иная задача. Вы можете ещё не понимать, как конкретно задачи будут выполнены, но вы должны понимать, зачем эти задачи вообще нужны.
-
Здесь постарайтесь избегать технических задач, по крайне мере в самом начале. Пример плохой задачи: "Написать репозиторий для заказа, чтобы его можно было использовать в модуле заказов". Эта задача по сути ничего не говорит о том, какую ценность она несет и как её выполнять. Пример задачи получше: "В модуле личного кабинета юзера добавить возможность видеть список его активных заказов с полями (поля) со ссылкой на переход на страницу конкретного заказа." - То есть формируя список задач я бы советовал в первую очередь отталкиваться от того, как система будет использоваться теми людьми, что с ней работают. Такие user story, если хотите.
-
Избегайте больших задач, делите задачи так, чтобы любую из них можно было бы выполнить за максимум несколько дней. Желательно также при создании задачи примерно указывать время на её реализацию.
-
Разделяйте задачи правильно. Не пишите кросс-модульные задачи - если задача требует вовлечения нескольких модулей - делите её на несколько задач.
-
Старайтесь держать задачи изолированно, если это возможно. Имейте ввиду, что любая задача может быть зафейлена программистом, это должно иметь минимальные последствия для вас и вашей системы, вы просто перепоручаете задачу другому программисту и он её выполняет.
Итак, у вас есть образец модуля, у вас есть задачи, у вас есть core модули. Вы почти готовы. Но вы должны понимать, что помимо четкого разделения на модули / задачи / ответственности, было бы очень хорошо, чтобы были какие то соглашения по коду. Это нужно, так как у каждого программиста своё представление о том, как называть переменные и классы, когда надо перехватывать/создавать исключения, и прочее и прочее. Старайтесь держать проект примерно в одном и том же стиле. Например, у меня были разные случаи и требования, начиная от того, что каждый файл в проекте не должен иметь даже предупреждений от Решарпера, заканчивая многостраничным трактатом об именовании типов. Поскольку вы пишете на C#, могу вам посоветовать начинать отсюда. Модули, написанные в одном и том же стиле, легче понять.
Имея всё перечисленное выше, вы можете приступать к работе. Есть много разных методик, как начинать командную работу и я бы не хотел говорить, что одна методика лучше другой. Я просто опишу, что было в моем опыте и что сработало.
Я в последние годы использую Scrum, но описание этой методологии выходит далеко за пределы ответа.
Поскольку у вас в команде будет всего несколько человек, я просто дам базовые понятия, что стоит делать и как организовать работу. Это будет полезным, даже если вы работаете вдвоём или вообще один.
Начать я рекомендую с определения интервалов работки. Спринтов, если хотите. То есть минимальный период времени, в конце которого вы будете показывать результат работы команды. Это обычно неделя или две недели. То есть в начале спринта вы, с командой и (возможно) вместе с заказчиком берете набор самых важных на текущий момент задач, которые вы выполните за время спринта. Так как каждая задача уже имеет сроки её выполнения, то будет несложно набрать задач на неделю-две. К тому же, я советую брать задач на хотя бы 70% времени, не больше. То есть для 1 недели берите задач на 4 рабочих дня, для 2 недель - на 8 дней для всей команды. Это нужно, чтобы у вас оставалось время на маневры, а если задачи кончатся раньше, то вы всегда сможете взять ещё. В конце спринта вы эти задачи демонстрируете заказчику, подводите итоги спринта, обсуждаете что было хорошо, что можно улучшить в процессе и планируете следующий спринт. По идее, тут все понятно, кроме демонстрации заказчику. Смотрите, планирование спринта вначале и демонстрация работы в конце очень важны, это не только помогает команде увидеть результат, но и также помогает понять, является ли то, что вы делаете, именно той работой, что нужна заказчику. Это нельзя переоценить, я видел слишком много случаев, когда программисты решали задачи, которые заказчику были не нужны или решались не тем способом, который заказчик ожидал. Если вы только начинаете разработку и не уверены в своих силах, вы можете даже приглашать заказчика на ежедневные летучки (о них ниже) и собирать с заказчика обратную связь.
После этого каждый разработчик берет себе задачу и начинает её выполнение. Старайтесь, чтобы сильно связанные задачи выполнял один разработчик, а слабо связанные - разные разработчики. Это необходимо, чтобы разработчики работали над разной кодовой базой и как можно меньше пересекались, чтобы они не ждали друг друга и не работали с одними и теми же классами.
В течении спринта, я бы рекомендовал иметь небольшие летучки каждый день, чтобы иметь информацию о том, кто и что делает, нет ли у кого проблем. Для разработчиков типичные моменты, когда он что то ждет и теряет время, но знает о проблеме только он. Старайтесь такого избегать.
Также необходимо иметь доску задач, которые были взяты в спринт, чтобы любой (в том числе и заказчик) в любой момент времени мог бы поглядеть на эту доску и понять, какие задачи в работе, какие закончены, а какие ещё не начаты.
Разделение на задачи, создание досок с задачами и прочее можно делать на обычной доске в офисе (если вся команда и заказчик находятся рядом), либо есть специальные инструменты для этого в интернете.
Работа с кодом это тоже сложная тема.
В командной разработке обычно подразумевается, что вся команда должна работать с одной и той же кодовой базой. Вы всегда должны иметь возможность скачать самую свежую версию исходников и собрать билд.
Я, после того, как перешел на GIT, уже не вижу дороги назад, хотя у меня есть опыт и с SVN, SourceSafe, TFS-CVS, Mercurial и даже папочками на расшаренном ресурсе.
Говоря о GIT, есть разные инструменты (например, я использую бесплатный SourceTree) и модели, как с ним работать. Я предпочитаю держать отдельно основную ветку (master), отдельно ветку разработки (develop), отдельно ветки для задач (feature/задача), отдельно ветки релизов, хотфиксов и тд. Но для маленькой команды это оверхед. Есть вполне себе простая методика GIT feature branching. Идея тут максимально проста:
- Когда девелопер 1 начинает свою задачу, он создает ветку от текущей мастер ветки
- Когда девелопер 1 заканчивает свою задачу, он создает pull request - это просто намерение добавить изменения в основую ветку из ветки для задачи, он также назначает человека (девелопер 2), который этот pull request будет проверять
- Девелопер 2 проверяет pull request, и если необходимо, просит девелопера 1 внести больше изменений, написать тесты и прочее.
- Девелопер 1 вносит нужные изменения
- Девелопер 2 проверяет снова и либо снова просит внести изменения, либо дает добро на слияние изменений в основную ветку
- Обычно, в моей практике, девелопер 2 выполняет слияние изменений, но бывает что это делает и девелопер 1.
- Изменения тестируются, проверяются, после этого задача либо требует новых изменений (новый pull request), либо задача закрывается.
Конечно, тут неизбежны конфликты, когда несколько программистов работают над одним и тем же файлом. GIT никак не помогает избежать таких конфликтов, он помогает только их разрешать. Что помогает из избегать, так это разделение на независимые модули и несвязанные задачи. Если вы заметили, то выше мы везде старались разделить код на модули, а где этого не было возможности сделать - то хотя бы разделить интерфейс и реализацию. Чем больше ваш код изолирован от остального кода, тем меньше вероятности получения конфликтов, так как в этом случае, чтобы получить конфликт, программисты должны работать на сильно связанными задачами, чего я выше советовал избегать.
Имея общий репозиторий исходного кода, очень важно следить за тем, что код всё ещё компилируется, собираются, что тесты не падают, что в любой момент времени вы можете скачать самый свежий билд, не дожидаясь никого. По сути, это и называется непрерывная интеграция. Каждый раз, когда кто то вносит изменения в общую ветку разработки, сервер непрерывной интеграции должен создать новый билд вашей программы и прогнать все автоматические тесты.
Чтобы иметь представление, работает ваша программа или нет, вам желательно иметь возможность не только собрать билд, но и развернуть ваше приложение на каком-либо тестовом окружении. Например, если вы пишете веб сайт, у вас должен быть тестовый сервер, где вы сможете нажатием одой кнопочки на билд-сервере развернуть ваш код и поглядеть, как ваша система выглядит. В идеале, желательно иметь даже 2 тестовых окружения, одно для вас, второе для заказчика. Чтобы во время каждого демо в конце спринта, вы могли развернуть ваше приложение в тестовом окружении для заказчика и чтобы заказчик мог сам, без вашего ведома, заходить в свое окружение (например, на свой вебсайт) и проверять реализованный функционал.
Я попробовал пробежать по самым азам командной разработки. Большинство тем я не рассматривал в деталях, но я надеюсь, у вас появилось какое то базовое представление о том, как и что должно работать.
Есть уже готовые к работе сервисы, которые содержат в себе уже и списки задач, и доски для планирования спринтов, и возможности по управлению исходным кодом, и билд серверы.
Например,
Если вы не хотите морочиться с собственными серверами (а вы не хотите :)
- Visual Studio Online - это сервис - решение всё в одном.
- Github - это всё, кроме build сервера. Однако, его легко связать с бесплатными build серврами, например с Travis или AppVeyor
- У компании Atlassian есть множество сервисов, например доски задач Jira или Trello, сервис хранения исходных кодов BitBucket, билд сервер Bamboo и многое другое.
- У компании JetBrains есть доска задач YouTrack и билд сервер TeamCity
- GitLab - тут решение просто все в одном.
Есть ещё много-много других инструментов, которые доступны и как сервисы, и как hosted решения. Но, так как вас всего 3 человека, то я бы посоветовал много не выдумывать и создать репозиторий на: