понедельник, 11 апреля 2011 г.

Что общего между футболистом и разработчиком ПО?

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

воскресенье, 15 августа 2010 г.

Стоимость тестирования


О том, что автоматизированное тестирование является важной составляющей процесса разработки программного обеспечения, написано во многих книгах. Вот некоторые свойства тестов, которые помогают нам:

• Скорость выполнения. Автоматизированные тесты выполняются значительно быстрее, чем ручные.
• Быстрое повторное выполнение. Ничто не мешает нам выполнять тесты несколько раз к ряду, если это необходимо.
• Локализация дефектов. Тесты показывают не только наличие дефекта, но и его расположение в коде.
• Тест как документация. Тесты помогают лучше понять код, предоставляя примеры его использования. Новые разработчики могут быстрее втянуться в разработку.
• Тест как страховочная сеть. Мы можем выполнять модификацию кода, без страха сломать работу существующего функционала (быстрое регрессионное тестирование).
• Отсутствие забытых проверок. Однажды добавленный тест не будет забыт, как это часто бывает при ручном тестировании.
• Навязывание дизайна. Внедрение тестов в процесс разработки навязывает нам design for testability, т.е. методы написания кода, который легок не только для тестирования, но и переиспользования, отладки и понимания. Такой код обладает низким связыванием и высоким сцеплением.

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

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

1. Кодирование функционала.
2. Поиск и устранение дефектов.
3. Добавление нового функционала в существующий код (модернизация, в соответствии с новыми требованиями).

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



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



Стадия кодирования будет увеличена, за счет необходимости написания автоматизированных тестов. Время поиска и устранения ошибок серьезно сократится, так же как и время модернизации, хотя последнее требует изменения кода вместе с тестами. Причина тому - более управляемый и легкий в понимании код, навязанный через design for testability.

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

Ну, я вам желаю легкого тестирования и качественного кода!

воскресенье, 6 июня 2010 г.

Что такое хорошо, а что такое плохо

Кроха сын к отцу пришел и спросила кроха: чем же мой код так хорош, ну а что в нем плохо?

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


Что такое плохо.

Характеристики системы, которыми она обладать не должна, принято называть «symptoms of poor design». При разработке системы важно обращать на них внимание и следить за тем, что бы они проявляли себя как можно реже. И так, вот они:

• Жесткость (Rigidity) – сложно вносить изменения с систему; небольшие изменения требуют серьезных модификаций. «Мне нужно всего лишь добавить новое сообщение на страницу, а я должен переписать пол приложения» - так негодуют разработчики, кому приходится модифицировать «жесткую» систему.
• Хрупкость (Fragility) – даже незначительные изменения, внесенные в систему, могут повлечь за собой непредсказуемые последствия. Обычно такое случается, если код программы не покрыт юнит тестами. В этом случае регрессионное тестирование становится настоящим кошмаром, как для тестеров, так и для разработчиков.
• Неподвижность (Immobility) – тяжело выделить отдельные компоненты для их дальнейшего переиспользования в других системах (компоненты слишком сильно зависят друг от друга). Низкое зацепление и высокое связывание являются тому причиной.
• Вязкость (Viscosity) – делать что-либо правильно сложнее, чем делать неправильно. Типичным примером может быть необходимость «копипастить» вместо наследования или модификация тех же скопированных кусков кода в нескольких местах, вместо внесения одного изменения в общую часть.
• Избыточная сложность (Needless Complexity) – система содержит инфраструктуру без явных преимуществ. Примером может быть создание дополнительных слоев, различных оберток объектов для передачи между этими слоями, хотя можно передавать их напрямую и т.д. Про некоторые решения, которые влекут за собой избыточную сложность, часто говорят: «Стрелять из пушки по воробьям».
• Избыточное повторение (Needless Repetition) – повторяющиеся структуры, которые лучше вынести в общие абстракции. То, что техника «скопировал-вставил» является дурным тоном, известно многим, но, не смотря на это, она применяет достаточно. Как результат система становится хрупкой и вязкой.
• Непрозрачность (Opacity) – тяжело понять что делает код. Чрезмерное использование различных трюков, плюс избыточная сложность, несомненно, приведет к тому, что код станет тяжелым для понимания. Возможно, в трюках и бывает необходимость, но такие участки кода должны быть хорошо документированы. Кроме того, отсутствие корпоративного стандарта по форматированию кода, так же ведет к его непрозрачности.


Что такое хорошо.

Обратно характеристикам «бедного дизайна», можно привести те, которые обычно сопровождают дизайн высокого качества:

• Минимальная сложность (Minimal complexity) – отсутствие слишком «умного» дизайна. Его всегда сложнее понимать и поддерживать. «Keep it simple» - один из известных принципов Agile разработки.
• Легкость поддержки (Ease of maintenance) – систему легко поддерживать, т.е. легко понять, как она работает и легко модифицировать её логику.
• Низкое связывание (Loose coupling) – система обладает минимальной зависимостью между её компонентами.
• Склонность к расширению (Extensibility) – вы можете легко расширить функционал системы без внесения изменений в существующий код.
• Склонность к повторному использованию (Reusability) – отсутствие повторяющихся кусков кода, высокое зацепление и низкое связывание её компонентов располагает к их легкому повторному использованию в других программах.
• Высокий уровень входящих связей (High fan-in) – один класс часто используется другими классами – следствие системы обладающей высоким повторным использованием своих компонентов.
• Низкий уровень исходящих связей (Low-to-medium fan-out) – классы должны зависеть от наименьшего количества других классов. Высокий «fan-out» (более 7) означает, что класс слишком зависим от других классов, что зачастую является следствием его чрезмерной сложности.
• Переносимость (Portability) – программа не испытывает проблем с запуском на других машинах, и при этом, не требует сложной предварительной настройки.
• Худоба (Leanness) – отсутствие неиспользуемых классов и модулей сделает систему более легкой в понимании и поддержке. YAGNI – «you ain’t gonna need it», еще один из принципов Agile разработки.
• Расслоение (Stratification) – система, спроектированная по принципу расслоения, легко оценить на каждом уровне без затрат на понимание остальных. Такая фокусировка положительно сказывается как на поиске проблем, так и на способности системы повторному использованию.
• Стандартные подход (Standard techniques) – система полностью написана с использованием единого подхода, таким образом, любой разработчик не испытывает трудностей в понимании частей системы, которые были написаны его коллегами.


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