среда, 30 марта 2011 г.

О тяжелых буднях


С каждым днем я становлюсь все старше и все более опытным разработчиком.  Сегодня, оглядываясь назад, на все проекты, в которых я принимал участие, и пытаясь анализировать события, происходившие в то время, я вижу все те проблемы, которые у нас были и понимаю их причины. Верни сейчас меня назад, я бы точно знал что нужно было тогда делать, а что не нужно. Хотя наврядле я бы смог спасти все проваленные проекты, причины их провала в большинстве случаев – это комплексные ошибки, которые в совокупности своей не позволили проекту развиваться дальше. Даже сейчас, я не смог бы повлиять на их развитие таким образом, что бы они не канули в лету, но однозначно смог бы предпринять действия, которые дали бы им хоть какую-то надежду.
Сегодня я хочу поговорить об основных проблемах, которые возникали в проектах с моим участием, объяснить их причины и проанализировать последствия. Возможно это позволить избежать подобных ситуаций в будущем. А раз так, то наверняка у будущих проектов процент успешности будет выше и значит этот мир станет еще лучше.

1. Я начальник ты дурак

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

2. Ваша зарплата два рубля, но поскольку работали вы плохо, мы дадим только рубль

В некоторых проектах заработная плата имеет не фиксированное значение, а может колебаться вокруг какой-то базовой суммы, причем как в большую так и в меньшую сторону.
С первым случаем, когда заработная плата становиться выше базовой суммы – ситуация проще, и меньше способствует возникновению каких-то проблем – поработал хорошо, получи добавку к зарплате. Хотя и здесь есть отрицительные моменты. Напрмер, если подобные премии в команде носят постоянный характер, то есть, скажем, каждый месяц определяется лучший разработчик, которые получает ее, то рано или поздно в команде появится «обиженный» человек, который либо не получает надбавку по каким то причинам, либо получает ее реже остальных. Обиженный человек в команде – это наличие проблем в проекте, а проект с проблемами - это уже серьезно. Если же пытаться подобную ситуацию решать административным спосбом, то есть давать премию разработчику не потому что он был лучшим, а потому что «подошла его очередь» то тут могут возникнуть неприятности в отношениях с более сильными разработчиками, которые больше заслужили премию.
Другой случай более коварный. Он сводится к тому, что существует система не премий, а штрафов. То есть если плохо поработал – то зарботная плата становится меньше базовой суммы. В отличие от ситуации с премиями, когда разработчик считает премию не своей зарплатой, а просто приятным дополнением, урезание зарплаты трактуется им как изъятие кровно заработанного. Штраф - всегда негатив. Он очень редко способствует повышению мотивации и работоспособности разработчика. В подобных случаях следует разобратся в причине, почему сотрудник отработал хуже обычного, и попытаться помочь ему в этой ситуации, а не наказывать его штрафом.
Третий вариант – комбинация первых двух. То есть уменьшается зарплата более слабых разработчиков, и эта сумма в качестве премии поступает более сильным. Несмотря на кажущуюся логичность такой системы – это вариант самый плохой случай из всех рассмотренных, и мой совет – никогда, ни при каких условиях и обстоятельствах не стоит его использовать.

3. Мы будем использовать все самые современные методологии

Суть проблемы сводится к следующему. Команда работает над поддержкой проекта написанного давно, «глупыми» программистами безо всяких методологий, объектно-ориентированного программирования, в старом добром процедрном стиле. И все бы хорошо, если бы не одно но. Система активно используется заказчиком, а тот хочет все и сразу, поэтому она постоянно подвергается различными изменениям и дополнениям. Ввиду того, что используется она уже давно и соответственно изменений и дополнений от заказчика удовлетворено тоже немало, весь исходный код представляет настолько неестественную субстанцию, что назвать его спагетти-кодом, это  как похвалить, ситуация на самом деле еще хуже. А если добавить к исходному коду еще и необходимость работать со старым инструментарием – так и вовсе становится грустно и уныло.
И вот в один прекрасный момент команда получает радостную весть – заказчик дает добро на разработку новой версии системы, на базе старой. Можно использовать новые методологии, новый инструментарий, новую архитектуру. Радости команды нет предела.
Но вот тут начинается самое интересное. Ослепленная возможностью применить на практике все самое «кульное» и современное, команда решает что новая версия будет использовать самую лучшую методологию, а можно и несколько, самые лучшие инструменты и фреймворки, ведь не зря столько умных книжек было прочитано в процессе саппорта старой версии. Команда решает применить TDD, но не просто применить, а обязательно со стопроцентным покрытием кода, то есть писать решено тесты и для публичных методов, и для приватных, и для пропертей, в общем для любого пука системы, даже если смысла в этом тесте немного. Помимо этого решено использовать BDD. Никто толком не знает, каким образом его использование пойдет на пользу проекту, но ведь это нужно для тестирования UI, а значит тоже обязательно должно быть. Дальше больше, код новой версии должен быть читабельным и понятным, поэтому решено, обильно комментировать любой метод, свойство или поле невзирая на то публичное оно или приватное. Все поля, методы и свойства должны быть сгрупированы в отдельные регионы, для того что бы их проще было искать в коде, и внутри региона отсортированы в алфавитном порядке. Но это еще не все. У каждого класса должна быть диаграмма, которая отражает его взаимосвязи с другими классами и проливает свет на все иерархии, в которых данный класс принимает участие. Ну и ясное дело все новомодные фреймворки и инструменты, которые к сожалению на практике мало кто из членов команды использовал.
Резльтат работы команды, я думаю, понятен абсолютному большинству читателей – проект планировалось завершить в двухмесячный период, но даже сейчас, по прошествии полугода, он еще далек от завершения. Спустя три месяца после начала работы над проектом решено было отказаться от использования BDD, так и не начав его использовать, спустя пять месяцев – временно отказаться от юнит-тестов, пока не будет реализована основная функциональность, которая уже давно так нужна заказчику, а уже потом покрывать код юнит-тестами (как вы говорите, TDD? Red-Green-Refactor?). Смягчены требования по оформлению кода. В общем хотели как лучше а получилось как обычно.

4. Все должно быть гибко и дженерик

Проблема описываемая в данном параграфе носит архитектурный характер. Суть ее заключается в том, что еще на этапе проектирования системы отдельные горе-архитекторы ставят перед собой амбициозную задачу – написать настолько качественный код, что бы он смог обработать любые самые разнообразные ситуации. Создаваемый прогаммный продукт должен быть апприори самый качественный, максимально продуманный, решающий все возможные вопросы и позволяющий резолвить все мыслимые и немыслимые ситуации, которые только могут возникнуть в процессе его использования. Все данные должны быть максимально гибкими и взаимозаменяемыми. Пользователя нельзя ограничивать ни в чем, даже если он введет свое имя в поле где должна быть указана сумма, программа должна поступить корректно и изловчится найти способ по введенному имени «придумать» сумму которую потенциально мог подразумевать пользователь. Ну и разумеется, задел на будущее. Все возможные ситуации, которые потеницально могут возникнуть в будущем программный продукт должен учитывать уже сейчас. Все должно быть представлено в виде интефейсов, можно двух, трех и даже четырех, чем больше тем лучше, это все предоставляет дополнительную гибкость, которая в будущем будет козырной картой продукта. Все объекты должны приводиться к одному интерфейсу, даже если между ними нету ничего общего и задачи они выполняют абсолютно разные, общий интерфейс должен быть реализован – это позволит в будущем сделать глобальный индекс или универсальный поиск по всем объектам в системе, даже если сейчас нету никаких идей зачем это может понадобиться.
В общем продолжать так можно до бесконечности. Результат к сожалению не такой радужный, как правило у проекта который развивается по данному сценарию два варианта развития.
Первый – пессимистичный. Он сводиться к тому что разработчики, которые вначале были полны решимости и амбиций, в конце концов оказаваются не в состоянии поддерживать и развивать код, который получился в результате. В итоге проект изза своей чрезмерной сложности и универсальности постепенно перестает вовсе быть управляемый и проект умирает бесславно, так и не дожив до дней своей славы. А разработчики как правило приступают к реализации менее амбициозной версии, которая скучно и прагматично решает поставленные задачи.
Второй – оптимистичный. В какой-то момент разработчики, устав бороться со сложностью проекта, решаются на изменения проекта делая его менее универсальным и дженерик, но более простым и логичным для реализации. Продукт получаемый в результате оказывается достаточно посредственным, ничем не отличающимся ни по гибкости, ни по производительности от продуктов, которые разрабатывались с обычной архитектурой. Главным минусом продукта как правило является тот факт что времени на его разработку было потрачено непозволительно больше, чем потребоавлось бы на реализацию более стандартного решения.

5. Давайте так, а давайте так, а давайте лучше так и вот так

Проблема может возникнуть если команда в проекте не управляется в принципе. Она представляет собой хаотично думающих разработчиков, котоыре на первое место ставят свои идеи и стремления. Ситуация похожа на ту которая описана в басне крылова про лебедя, рака и щуку. Каждый хочет в проекте пользоваться тем, что сам считает наиболее подходящим для данной ситуации. В подобных случаях, всякие дедлайны, планы и тому подобное уходят на второй план. Главное – это удовлетворить свое желание внедрить в проект желаемые инструментарий или фреймворк.
В проекте, в котором я учавствовал, да что там греха таить, учавствую, изначально было решено использовать свзяку ASP.NET WebForms + Silverlight для фронт-енда. О бак-энде речь не идет даже сейчас, поскольку даже спустя почти восемь месяцев с начала разработки даже базовая фуникцональность еще не готова и впринципе далека от завершения. Но обо всем по порядку.
Первые два месяца разработки прошли достаточно продуктивно – процентов 70 базовой фуникцональности было реализовано и все шло к тому что в последующие 2-3 месяца на какую-то какую демо-версию нас хватит и ее можно будет лицезреть и пробовать использовать в реальных условиях. Но не тут то было, появилось в головах наших доблестных разработчиков мысль что сильверлайт это не круто, особенно в свете происходивших тогда аннонсов, и решено было вместо Silverlight использовать html5. Сказано сделано. Но не успели мы свыкнуться с этой мыслью как появилась еще одна  - а давайте перейдем c ASP.NET WebForms на ASP.NET MVC. Посидели подумали: Лучше? Лучше! Единогласно. Прошло еще немного времени, и решили что ASP.NET MVC в чистом виде – это тоже не гуд. Нужно что бы все выполнялось на клиенте а связь с сервером через AJAX – сказано сделано – jquery в помощь и вперед. В итоге, сейчас у нас сделано хорошо если половина того, что уже было готово спустя два месяца после начала разработки, то есть за два первых месяца что-то сделали, а потом за последующие шесть половину того что сделали, поломали.
А я вот сижу смотрю на это все и думаю – а стоило ли оно того? Что мы получили в итоге? Более продвинутое решение? Наврядле, скорее бесполезную головную боль, за которую никто не заплатит. Ага. Так что скорее всего и git, который у нас сейчас используется заменим на subversion, как-то он привычней, глядишь еще месяц пройдет, а там можно и на руби посмотреть или еще на что нибудьJ