На жаль, цей розділ недоступний у безкоштовному уривку.

Роберт Мартін

ЧИСТИЙ КОДЕР:
Кодекс поведінки для професійних розробників

Видавничий дім «Фабула»
2023

Авторизований переклад з англомовного видання під назвою
The Clean Coder: A Code of Conduct for Professional Programmers, 1-ше видання, автора Роберта С. Мартіна, опубліковано Pearson Education, Inc, що виступає як Addison Wesley Professional, Copyright © 2011 Pearson Education, Inc.

Authorized translation from the English language edition, entitled The Clean Coder: A Code of Conduct for Professional Programmers, 1st Edition by Robert C. Martin, published by Pearson Education, Inc, publishing as Addison Wesley Professional, Copyright © 2011 Pearson Education, Inc.

Copyright © 2011 Pearson Education, Inc.

© Г. Якубовська, пер. з англ., 2023

© ВД «Фабула», 2023

ISBN 978-617-522-110-5 (epub)

Усі права збережено. Жодної частини цієї книжки не може бути відтворено або передано в будь-якій формі або будь-якими засобами, електронними чи механічними, включно з фотокопією, записом чи будь-якою системою зберігання та пошуку інформації, без письмового дозволу Pearson Education, Inc.

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc.

Видання українською мовою опубліковано ТОВ Видавничий дім «Фабула» © 2023

Ukrainian language edition published by Publishing House Fabula LLC, Copyright © 2023

Електронна версія створена за виданням:

Мартін Роберт С.

М29 Чистий кодер: Кодекс поведінки для професійних розробників / пер. з англ. Г. Якубовська. — Харків : ВД Фабула, 2023. — 256 с.

ISBN 978-617-522-082-5

Роберт Мартін, також відомий як Дядечко Боб,— знакова постать у світі розробки ПЗ, блискучий професіонал, міжнародний консультант, один із тих, хто створював 2001 року всесвітньо відомий Agile-маніфест. Кожна його наступна книжка — джерело безцінного досвіду.

У «Чистому кодері» автор викладає свої очікування від професійного розробника у всіх можливих аспектах: із погляду управлінських взаємодій, тайм-менеджменту, зовнішнього тиску, співпраці в команді та вибору відповідних інструментів. Не оминає він і питань трудової етики. Ви також дізнаєтеся, що навіть гуру програмування далеко не завжди є професіоналами. Натомість Роберт Мартін пропонує читачеві шлях до справжнього розробницького професіоналізму — і робить це надзвичайно цікаво й дотепно.

УДК 004.41

Шановний читачу!

Спасибі, що придбали цю книгу.

Кінець безкоштовного уривку. Щоби читати далі, придбайте, будь ласка, повну версію книги.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

На жаль, цей розділ недоступний у безкоштовному уривку.

A
Налаштування

1978 року я працював у Teradyne над телефонною тестовою системою, про яку вже згадував раніше. Система складалася приблизно з 80 тисяч рядків коду асемблера M365. Початковий код зберігався на магнітних стрічках.

Ті стрічки нагадували восьмидоріжечні стерео-касети, що були шалено популярні в 1970-х роках. Кінець і початок стрічки були склеєні, а стрічковий накопичувач міг перемотувати її лише в одному напрямку. Стрічки в касетах мали довжину 10, 25, 50 та 100 футів. Що довша була стрічка, то більше часу забирало перемотування, бо накопичувачу доводилося просто рухатися вперед до «точки завантаження». На перемотування стофутової стрічки до точки завантаження витрачалося близько п’яти хвилин, тому ми дуже обачно підходили до вибору довжини стрічок{51}.

На логічному рівні стрічки поділялися на файли. На одну стрічку можна було записати стільки файлів, скільки вона могла вмістити. Для того щоби знайти потрібний файл, належало завантажити стрічку, а потім послідовно читати файли, поки потрібний не буде знайдений. На дошці в лабораторії завжди висіла роздруківка каталогу з вихідним кодом — за нею ми визначали скільки файлів потрібно пропустити, щоби знайти потрібний.

На полиці в лабораторії також лежала стофутова еталонна копія стрічки з вихідним кодом і позначкою «Майстер». Аби відредагувати файл, ми встановлювали в один накопичувач еталонний екземпляр, а в інший — десятифутову порожню (робочу) стрічку. Еталонна стрічка промотувалася до потрібного файлу, після чого файл копіювався на робочу стрічку. Тоді ми перемотували обидві стрічки на початок, й еталонна стрічка поверталася на полицю.

Окрім цього, на дошці в лабораторії була присутня спеціальна роздруківка еталонної стрічки «Майстер». Коли ми створювали копії файлів, котрі належало відредагувати, то встромляли в роздруківку кольорову кнопку поруч з ім’ям цього файлу. Ось так і здійснювався контроль за внесенням змін!

Редагування проводилося в екранному режимі. Ми користувалися дуже вдалим текстовим редактором ED-402 — близьким аналогом vi. Сторінка читалася зі стрічки, ми редагували її вміст, записували назад і бралися за наступну. Сторінка зазвичай складалася із приблизно 50 рядків коду. Ми не мали можливості зазирнути вперед, аби побачити наступні сторінки, і не могли повернутися назад — до вже відредагованих сторінок. Тому ми використовували лістинги.

У лістингах позначалися всі зміни, після чого файли редагувалися відповідно до позначок. Ніхто не писав і не змінював код спонтанно! Це було би чимось на кшталт самогубства. Після внесення змін до всіх файлів, що потребували редагування, ми поєднували їх із вмістом еталонного екземпляра. Отриману стрічку використовували для здійснення компіляції і тестування.

Завершивши тестування і переконавшись, що зміни працюють, ми дивилися на роздруківку. Якщо на ній не було нових кнопок, робоча стрічка просто перейменовувалась на еталонну, а всі «відпрацьовані» кнопки знімалися з дошки. Якщо ж на дошці з’являлися нові кнопки, ми прибирали всі попередні і передавали робочу стрічку тому, хто їх виставив, для злиття результатів.

У команді було лише троє розробників, і кожен із них мав кнопки відповідного кольору. Тому ми завжди могли визначити, хто взяв на редагування ті чи інші файли. А оскільки всі ми працювали в одній лабораторії і постійно спілкувалися один з одним, поточний стан кодової бази постійно зберігався в наших головах. Найчастіше навіть роздруківка виявлялася зайвою, і ми обходилися без неї.

Інструменти

Сучасним розробникам доступні найрізноманітніші інструменти програмування. Від деяких, на мою думку, варто триматися якнайдалі, але є серед них і такі, якими повинен упевнено володіти будь-який розробник. У цьому розділі описаний мій особистий поточний інструментарій. Я не наводжу повного опису всіх представлених інструментів, тому огляд не є вичерпним, і розповідаю лише про те, що використовую сам.

Управління вихідним кодом

Що стосується управління вихідним кодом, то, як правило, краще використовувати програми з відкритим кодом. Чому? Бо вони пишуться розробниками для розробників. Інакше кажучи, розробники пишуть програми з відкритим кодом для себе, коли їм необхідне працездатне рішення.

Існує багато дорогих комерційних («корпоративних») систем контролю за версіями. На мою думку, ними спокушаються не стільки розробники, скільки керівники, менеджери та «інструментальні групи». Список функцій таких програм завжди виглядає вражаюче. Але, на жаль, у ньому часто не виявляється того, що дійсно потрібне розробникам. До того ж, головною проблемою для користувачів зазвичай стає їх швидкість.

«Корпоративні» системи керування вихідним кодом

Цілком можливо, що ваша компанія вже вклала цілий статок у «корпоративну» систему керування вихідним кодом. У такому разі — прийміть мої співчуття. Звісно, із політичних міркувань ви не зможете просто бовкнути: «Дядечко Боб каже, що цим лайном не треба користуватися». Однак існує простий вихід.

Ви можете реєструвати вихідний код у «корпоративній» системі наприкінці кожної ітерації (кожні два тижні або близько того), а в середині ітерацій використовувати систему з відкритим кодом. Усі будуть задоволені, ви не порушите корпоративних настанов, а ваша продуктивність залишиться високою.

Песимістичне та оптимістичне блокування

У 1980 роках песимістичне блокування здавалося гарною ідеєю. Зрештою, найпростіший шлях до розв’язання проблем паралельного оновлення — «розпаралелювання». Якщо я редагую файл, то вам краще його не чіпати. Система кольорових кнопок, яку ми використовували наприкінці 1970-х, була своєрідним механізмом песимістичного блокування. Якщо файл був позначений певною кнопкою, інші не повинні були його редагувати.

Звісно, песимістичне блокування має свої недоліки. Якщо заблокувати файл і піти у відпустку, то решта користувачів, які забажають працювати із цим файлом, опиняться в безвиході. Навіть якщо файл залишиться заблокованим на день-два, це затримає роботу інших людей.

Сучасні інструменти значно краще справляються зі злиттям паралельно редагованих вихідних файлів. Адже це нетривіальне завдання: програма аналізує два різні файли разом із попередниками цих двох файлів, а потім застосовує відповідні стратегії для визначення способу інтеграції паралельних змін. І мушу сказати, вона робить це добре.

Отже, час песимістичного блокування минув. Тепер нам не потрібно робити блокування файлів під час редагування. Ба більше, нам узагалі не потрібно турбуватися про блокування окремих файлів — ми запитуємо відразу всю систему й редагуємо потрібні файли.

Коли все буде готове до реєстрації змін, виконується операція оновлення. Вона повідомляє нам, чи не було більш ранньої реєстрації змін, здійсненої іншими користувачами, виконує автоматичне злиття більшості змін, знаходить конфлікти і допомагає вирішити їх. Після цього об’єднаний код додається в кодову базу.

Далі я більш докладно висвітлю роль автоматизованих тестів і безперервної інтеграції у цьому процесі. А тут варто підкреслити ось що: код, який не пройшов всіх тестів, за жодних умов не повинен додаватися в кодову базу. Ніколи.

CVS/SVN

Одна із традиційних систем управління вихідним кодом — CVS — була гарною для свого часу, але в сучасних проєктах уже починає відставати. Хоча CVS відмінно працює з окремими файлами і теками, вона не дуже добре справляється з перейменуванням файлів та видаленням тек. Що вже казати про підтеки… І на цьому — завіса. Що менше говорити про це, то краще.

Із іншого боку, система Subversion працює дуже добре. Вона дозволяє отримати доступ до всієї системи за одну операцію. У ній легко виконуються операції оновлення, злиття та закріплення змін. За відсутності розгалужених змін, системи SVN доволі прості в управлінні.

Розгалуження

До 2008 року я уникав будь-яких форм розгалуження (branching), окрім найпростіших. Якщо розробник створює гілку, то ця гілка має бути повернена до основної лінії ще до кінця ітерації. При цьому я так суворо ставився до розгалуження, що воно дуже рідко застосовувалося у тих проєктах, у яких я брав участь.

Якщо ви використовуєте SVN, то я, як і раніше, вважаю, що це вдала політика. Однак останнім часом з’явилися нові інструменти, що цілковито змінили ситуацію. Я маю на увазі розподілені системи управління вихідним кодом. У цій категорії моїм улюбленим інструментом є git. Зараз я розповім про цю систему докладніше.

git

Я почав використовувати git наприкінці 2008 року. Ця система цілковито змінила мій підхід до управління вихідним кодом. Пояснення того, чому ця програма так відчутно змінила правила гри, виходять за межі цієї книжки. Проте порівняння рис. Д.1 із рис. Д.2 набагато красномовніше будь-яких слів.

На рис. Д.1 показаний перебіг розробки проєкту FitNesse за кілька тижнів під керуванням SVN. Ви бачите наслідки моєї жорсткої політики відмови від розгалуження. Ми просто його не використовували. Натомість у головній гілці часто виконувалися операції оновлення, злиття та закріплення.

Рис. Д.1. Проєкт FitNesse під керівництвом subversion

На рис. Д.2 показана структура кількох тижнів розробки того самого проєкту з використанням git. Як бачите, операції розгалуження та злиття відбуваються постійно. І річ не в тім, що я чомусь змінив своє ставлення до розгалуження. Просто такий робочий процес став очевидним та ефективним. Окремі розробники створюють гілки з дуже коротким терміном життя, а потім поєднують їх із результатами колег тоді, коли вважають за потрібне.

Рис. Д.2. Проєкт FitNesse під керівництвом git

Також зауважте, що на рисунку не видно «справжньої» головної гілки. Річ у тім, що її просто немає. Розробники зберігають на своїх локальних комп’ютерах копії всієї історії проєкту. Вони вносять зміни і реєструють їх у своїй локальній копії, а потім синхронізують із копіями колег у разі потреби.

Щоправда, я підтримую спеціальний «золотий репозиторій», у якому зберігаються всі опубліковані версії та внутрішні збірки. Але називати його «головною гілкою» означало би не розуміти суті справи. Насправді це лише зручна «світлина» всієї історії, що зберігається локально кожним розробником.

Якщо ви не зрозуміли щось зі сказаного, це нормально. Спочатку git викликає чимало труднощів. До того, як працює ця система, потрібно звикнути. Але запевняю вас: git та інші подібні системи — це майбутнє керування вихідним кодом.

IDE/Редактор

Ми, розробники, проводимо більшу частину часу за читанням та редагуванням коду. Інструменти, що ми використовуємо для цього, значно змінилися за минулі роки. Деякі з них мають неймовірну міць, а деякі майже не змінилися з 1970-х років.

VI

Здається, що доба використання vi як основного редактора для розробки давно минула. У наші дні з’явилися інструменти, що значно перевершують vi за своїми можливостями, та інші нескладні текстові редактори того самого типу. Однак останнім часом спостерігається помітний сплеск популярності vi. Це пояснюється його простотою, зручністю використання, швидкістю та гнучкістю. Хоча vi й поступається Emacs або Eclipse за широтою можливостей, він залишається швидким та потужним редактором.

Водночас, я вже не досвідчений користувач vi. Колись мене називали «богом» vi, але цей час давно минув. Я використовую vi час від часу, коли потрібно швидко відредагувати текстовий файл. Нещодавно я застосовував його для швидкої зміни вихідного файлу Java у віддаленому режимі. Але обсяг повноцінного коду, написаного мною у vi за останні 10 років, істотно зменшився.

Emacs

Emacs досі залишається одним із найпотужніших редакторів і, ймовірно, залишиться ним ще кілька найближчих десятиліть. Його потужність забезпечується внутрішньою моделлю з урахуванням lisp. У категорії інструментів редагування загального призначення жоден інший редактор навіть віддалено не може з ним конкурувати. З іншого боку, на мою думку, Emacs не може повноцінно конкурувати зі спеціалізованими інтегрованими середовищами розробки (IDE), що зараз займають провідні позиції. Редагування коду не є редагуванням загального призначення.

У 1990 роках я був фанатом Emacs. Я просто не розглядав інших варіантів. Тодішні редактори з керуванням мишею були просто кумедними іграшками, до яких жоден розробник не ставився серйозно. Але на початку 2000-х я познайомився з IntelliJ — моїм фаворитом серед IDE, і вже не озирався назад.

Eclipse/IntelliJ

Я — відданий користувач IntelliJ. Я люблю цю систему й використовую її для написання коду на Java, Ruby, Clojure, Scala, Javascript та багатьох інших мовах. Вона була створена розробниками, які розуміють, що саме потрібно колегам під час написання коду. За минулі роки IntelliJ майже ніколи не підводила мене, а враження від неї завжди залишалися позитивними.

Середовище Eclipse за своєю потужністю і масштабом можна порівняти з IntelliJ. Ці два середовища якісно перевершують Emacs за можливостями редагування Java-коду. У цій категорії існують інші IDE, але я не згадую їх тут, бо в мене немає безпосереднього досвіду їх використання.

Ці інтегровані середовища відрізняються від таких інструментів, як Emacs, насамперед надзвичайно багатими можливостями маніпулювання кодом. Наприклад, IntelliJ дозволяє отримати суперклас із класу всього однією командою. Ви можете перейменовувати змінні, отримувати методи, перетворювати наслідування на композицію — і це далеко не весь перелік.

Із цими інструментами редагування коду переходить від рівня рядків і символів до більш складних маніпуляцій. Розробник при цьому думає не про кілька наступних символів і рядків, що він збирається ввести, а про наступні перетворення. Коротше кажучи, модель програмування у цих нових системах значно змінюється і стає більш продуктивною.

Звісно, за широту можливостей доводиться платити. Освоєння інтегрованих середовищ вимагає багато часу і зусиль, а фаза початкової підготовки проєкту стає досить помітною. Крім того, ці інструменти дуже вимогливі — для їхньої роботи необхідні значні обчислювальні потужності.

TextMate

Редактор TextMate потужний і невимогливий до ресурсів. Щоправда, він не вміє виконувати такі приголомшливі маніпуляції, на які здатні IntelliJ й Eclipse. У нього немає потужного lisp-ядра та бібліотеки Emacs. Він не має швидкості та гнучкості vi. З іншого боку, його можна швидко освоїти, а всі операції є інтуїтивно зрозумілими.

Я використовую TextMate лише іноді, особливо для спонтанного програмування на C++. У великому проєкті я би скористався Emacs, але для невеликих завдань на C++ мені просто ліньки з ним возитися.

Відстеження завдань

Зараз я використовую Pivotal Tracker. Ця система проста і елегантна, вона добре інтегрується з Agile/ітеративними методологіями і дозволяє всім зацікавленим сторонам та розробникам швидко спілкуватися один з одним. Я дуже задоволений.

У дуже маленьких проєктах я іноді використовую Lighthouse. Ця система проста і зручна в налаштуванні та використанні, але за широтою можливостей навіть не наближається до Tracker.

Також у деяких випадках я просто використовую wiki. Таке рішення добре підходить для внутрішніх проєктів. Wiki дозволяє застосувати будь-яку організаційну схему на ваш розсуд. Ніхто не змушує вас використовувати конкретний процес чи жорстку структуру. Цей варіант теж надзвичайно простий для розуміння та використання.

Іноді найкращою системою відстеження завдань стає звичайна настінна дошка з набором карток. Дошка ділиться на стовпці на кшталт «Слід зробити», «У розробці» та «Готово». Розробники просто переносять картки з одного стовпця до іншого під час роботи над завданнями. Мабуть це одна з найпоширеніших систем відстеження завдань у сучасних командах, які використовують Agile-методології.

Я рекомендую своїм клієнтам починати з подібної «ручної» системи, перш ніж купувати спеціалізовані програми. Освоївши «ручне» відстеження, клієнт отримує знання, що дозволяють йому зробити розумний вибір — іноді на користь тієї ж дошки з картками.

Лічильники дефектів

Команді розробників напевно потрібен перелік поточних завдань. До них належать як завдання щодо реалізації нових можливостей і функцій, так і виправлення помилок. Для команди звичайного розміру (від 5 до 12 розробників) подібний список має містити від кількох десятків до сотень позицій. Але не тисяч!

Якщо у вашій системі тисячі помилок, із нею явно щось не так. Якщо ваш список налічує тисячі завдань та/або функцій, із ним теж щось не так. У загальному випадку список повинен бути відносно невеликим, тому для роботи з ним має вистачити таких нескладних інструментів, як wiki, Lighthouse або Tracker.

На ринку присутні комерційні програми, що мають непоганий вигляд. Я бачив, як мої клієнти користуються ними, але поки що не мав можливості попрацювати особисто. Не маю нічого проти таких інструментів, але за умови, що список завдань залишається невеликим та легко керованим. Коли засоби відстеження завдань вимушені працювати зі списками, що налічують тисячі позицій, саме слово «відстеження» втрачає сенс. Список поточних завдань перетворюється на «звалище поточних завдань» (і часто тхне як будь-яке звалище).

Безперервне складання

Останнім часом, для забезпечення безперервного складання я використовую Jenkins. Система невибаглива, проста, а робота з нею не вимагає тривалої підготовки. Ви завантажуєте програму, запускаєте її, проводите нескладне налаштування конфігурації — і далі все працює. Дуже зручно.

Мій підхід до безперервного складання простий: зв’яжіть його із системою управління вихідним кодом. Щоразу коли в базі реєструється змінений код, має виконуватися автоматичне безперервне складання, звіт про результати якого повинен видаватися команді.

Команда зобов’язана стежити, щоби складання завжди виконувалося успішно. Якщо складання не проходить, це повинно стати тривожним сигналом, а команда має негайно зібратися для розв’язання проблеми. За жодних умов збій, що стався, не повинен зберігатися протягом доби або довше.

У проєкті FitNesse я вимагаю, щоби кожен розробник виконував сценарій безперервного складання перед реєстрацією внесених змін. Складання забирає менше п’яти хвилин, що не надто обтяжливо. Якщо під час складання виявляються проблеми, розробники усувають їх до реєстрації. Отже, автоматичне складання лише зрідка стикається із будь-якими проблемами. Найпоширенішим джерелом збоїв автоматичного складання стають проблеми, пов’язані із налаштуваннями робочого середовища, оскільки моє середовище автоматичного складання значно відрізняється від середовищ розробників.

Інструменти модульного тестування

Для кожної мови існують свої спеціалізовані засоби модульного тестування. Я особисто використовую JUnit для Java, rspec для Ruby, NUnit для .Net, Midje для Clojure і CppUTest для C та C++.

Утім, хай би який інструмент модульного тестування ви обрали, всі вони повинні мати набір базових властивостей і функцій.

1. Тести повинні запускатися легко і швидко. Не має значення, як саме це робиться — за допомогою плагінів IDE або простих утиліт командного рядка; головне полягає в тому, щоби розробники могли запускати ці тести на власний розсуд. Команда запуску має бути тривіально простою. Наприклад, я запускаю свої тести CppUTest у TextMate простим натисканням клавіш command+M. Я зв’язав цю комбінацію із запуском makefile, що автоматично виконує тести і виводить короткий однорядковий звіт у тому випадку, якщо всі тести пройдені успішно. IntelliJ підтримує JUnit та rspec, тому мені потрібно лише натиснути кнопку. Для виконання NUnit я використовую плагін Resharper.

2. Інструмент має видавати чітку візуальну ознаку проходження/непроходження тесту — хай це буде зелена смуга на графічному екрані або консольне повідомлення «Усі тести пройдено». Суть у тому, щоби ви могли швидко й однозначно визначити, що всі тести пройдені. Якщо для визначення результату тестування доводиться читати багаторядковий звіт чи (що ще гірше) порівнювати вихідні дані двох файлів,— умову не виконано.

3. Програма має видавати чітку візуальну ознаку прогресу. Не важливо, чи буде це графічний індикатор або рядок точок, що поступово з’являються,— головне, щоби користувач бачив, що процес триває, а тестування не зупинилося і не перервалося.

4. Програма має перешкоджати взаємодії між окремими тестовими сценаріями. JUnit вирішує цю проблему, створюючи новий екземпляр тестового класу кожного тестового методу; таким чином цей інструмент запобігає використанню змінних екземплярів у взаємодії між тестами. Інші інструменти запускають тестові методи у випадковій послідовності, щоб унеможливити будь-яку залежність від конкретної послідовності виконання тестів. Незалежно від вибору конкретного механізму, програма має вжити заходів для забезпечення незалежності тестів. Залежні тести — підступна пастка, якої слід уникати.

5. Інструмент має за можливості спрощувати написання тестів. Наприклад, JUnit надає зручний API для перевірки умов (assertions), а також використовує рефлексію та атрибути Java, щоби відрізняти тестові функції від звичайних. Зрештою вдалі IDE можуть автоматично ідентифікувати тести, позбавляючи вас від клопоту із підготовкою.

Інструменти тестування компонентів

Інструменти цієї категорії призначені для тестування компонентів на рівні API. Їхня роль — визначення поведінки компонента мовою, зрозумілою для бізнесу і спеціалістів із контролю якості. В ідеалі бізнес-аналітики та фахівці з контролю якості мусять писати специфікації з використанням саме цих інструментів.

Визначення «Виконано»

Інструменти компонентного тестування більшою мірою, ніж будь-які інші, виражають наше уявлення про те, що розуміється під «виконаною» роботою. Коли бізнес-аналітики і спеціалісти з контролю якості створюють специфікацію, що визначає поведінку компонента, і коли ця специфікація виконується як набір тестів, які або проходять, або ні,— поняття «done» набуває абсолютно чіткого значення: «Всі тести пройдено».

FitNesse

Мій улюблений інструмент компонентного тестування — FitNesse. Я написав більшу частину його коду, і я його основний автор. І взагалі це моє дітище.

FitNesse — система на базі wiki, що дозволяє бізнес-аналітикам і спеціалістам із контролю якості писати тести в дуже простому табличному форматі. Ці таблиці за формою і призначенням мають багато спільного з таблицями Парнаса. Тести легко поєднуються в пакети, які можна виконати будь-якої миті.

Система FitNesse написана на Java, однак може використовуватися для тестування систем на будь-якій мові, бо взаємодіє із базовою системою тестування, що може бути написана будь-якою мовою. Нині підтримуються мови Java, C#/.NET, C, C++, Python, Ruby, PHP, Delphi тощо.

В основі FitNesse лежать дві системи: Fit і Slim. Систему Fit написав Ворд Каннінгем, вона стала джерелом натхнення для FitNesse і є її близьким родичем. Slim — простіша і більш портативна система тестування, якою сьогодні користуються багато прихильників FitNesse.

Інші інструменти

Мені відомі ще кілька систем, які можна зарахувати до категорії інструментів для тестування компонентів.

• Система RobotFX була розроблена інженерами Nokia. Як і у FitNesse, у ній використовується табличний формат, але не на базі wiki. RobotFX просто працює з неструктурованими файлами, створеними в Excel або іншій аналогічній програмі. Програма написана на Python, але, за використання відповідних мостів, може тестувати системи, написані будь-якою мовою.

• Green Pepper — комерційна програма, що в деяких аспектах схожа на FitNesse. Базується на популярній confluence wiki.

• Cucumber — текстова програма, що працює на ядрі Ruby, але підходить для тестування на багатьох різних платформах. У мові Cucumber використовується популярний стиль Given/When/Then.

• JBehave — аналог та «ідеологічний батько» Cucumber. Програма написана на Java.

Інструменти інтеграційного тестування

Інструменти компонентного тестування можуть використовуватися для виконання багатьох інтеграційних тестів, але погано підходять для тестів, керованих через інтерфейс користувача.

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

Утім, деякі тести мусять виконуватися через інтерфейс користувача — і насамперед йдеться про тести самого інтерфейсу. Крім того, деякі комплексні тести мають проходити через усю зібрану систему, включно з інтерфейсом користувача.

Для тестування інтерфейсу користувача я зазвичай використовую програми Selenium і Watir.

UML/MDA

На початку 1990 років я дуже сподівався, що галузь автоматизованої розробки ПЗ кардинально змінить характер діяльності розробника. Зазираючи в майбутнє із тих бурхливих днів, я сподівався, що через пару десятиріч усе вже буде кодуватися у вигляді діаграм на вищому рівні абстракції, а текстовий код залишиться в минулому.

Як же я помилявся! Мої мрії не лише не справдилися, а й незліченні спроби руху в цьому напрямку зазнали цілковитого краху. Річ навіть не в тім, що не існує інструментів і систем, що мають потенціал для такого підходу; просто ці інструменти по-справжньому не реалізують цю мрію і навряд чи хтось забажає ними скористатися.

Так, я мріяв, що розробники позбавляться подробиць текстового коду й почнуть будувати системи на більш високому діаграмному рівні. У цих зухвалих мріях розробники взагалі здавалися зайвими. Архітектори могли будувати цілі системи за діаграмами UML. Ядро системи — величезне, безпристрасне і байдуже до турбот пересічних розробників — самотужки перетворюватиме діаграми на виконуваний код. Ось як виглядала велична мрія про модельно-орієнтовану архітектуру (MDA, Model Driven Architecture).

На жаль, у величної мрії була і є одна крихітна вада. MDA передбачає, що проблема в коді. Але проблема не в коді. Це ніколи не було проблемою. Проблема в деталізації.

Деталізація

Розробники керують деталями. Так, саме цим ми займаємося. Ми описуємо поведінку системи в найдрібніших подробицях. Задля цього ми використовуємо текстові мови, бо вони надзвичайно зручні (візьміть, наприклад, хоча б англійську).

Але якими деталями ми керуємо?

Чи відомо вам, чим відрізняються два символи \n і \r? Перший із них — це перехід рядка (line feed), а другий — повернення каретки (carriage return).

Що таке каретка? У 1960-х і на початку 1970 років основним пристроєм виведення для комп’ютерів був телетайп. Модель ASR33{52} була найпоширенішою.

Цей пристрій складався із друкувальної голівки, що могла друкувати до 10 символів за секунду. Друкувальна голівка складалася із циліндра, на який були нанесені рельєфні символи. Циліндр повертався так, аби до паперу був звернений правильний символ, після чого молоточок ударяв по циліндру і притискав його до паперу. Між циліндром і папером містилася просочена фарбою стрічка, фарба з якої переносилася на папір, повторюючи обриси символу.

Друкувальна голівка переміщалася на каретці. Із кожним символом каретка зміщувалася на одну позицію праворуч, разом із нею зміщувалась і друкуюча головка. Коли каретка досягала кінця 72-символьного рядка, її доводилося повертати на початок рядка, вводячи символ повернення каретки (\r = 0 × 0D); без цього друкуюча голівка продовжувала би друкувати символи у сімдесят другому стовпці, і від багаторазового друку там виникав би чорний прямокутник.

Звісно, цього було замало. Повернення каретки не призводило до зсуву паперу до наступного рядка. Якби після повернення каретки не передавався символ переходу рядка (\n = 0 × 0A), то новий рядок друкувався би поверх старого.

Отже, для телетайпа ASR33 всі рядки повинні були завершуватися послідовністю \r\n. Однак і тут була необхідна обережність, бо повернення каретки могло забрати більше ста мілісекунд. Якщо обмежитися лише відправкою \n\r, наступний символ міг бути надрукований під час зворотного ходу каретки, а в середині рядка з’явився би змащений символ. Для надійності, символи кінця рядка часто доповнювалися одним або двома символами «забій»{53} (0 × FF).

У 1970 роках, коли телетайпи почали поступово відходити в минуле, в операційних системах UNIX послідовність кінця рядка скоротилася до n. Однак інші операційні системи на кшталт DOS продовжували використовувати позначку \r\n.

Коли до вас потрапляв текстовий файл, що використовував «неправильне» позначення? Я стикаюся із цією проблемою не рідше одного разу на рік. Два ідентичні файли з вихідним кодом не порівнюються, а їхні контрольні суми різняться, бо в них використовуються різні завершувачі рядків. Текстові редактори некоректно переносять слова або поділяють рядки подвійним інтервалом, бо інтерпретують \r\n як два рядки. Деякі програми розуміють \r\n, але не розпізнають \n\r… І так далі.

Ось що я маю на увазі під деталізацією. Спробуйте закодувати логіку обробки завершувачів рядків на UML!

Без змін та надій

Рух MDA обіцяв, що використання діаграм замість коду дозволить виключити із програмування велику кількість другорядних подробиць. Досі ці обіцянки не виконані. Як виявилося, у коді не так багато зайвих деталей, що їх можна було би виключити за допомогою діаграм. Ба більше: діаграми також містять власні другорядні деталі. Вони мають свою граматику, синтаксис, правила та обмеження. Зрештою розбіжності в ступені деталізації виявляються незначними.

Рух MDA також обіцяв, що робота з діаграмами буде вестися на більш високому рівні абстракції, ніж робота з кодом,— подібно до того, як Java стоїть на вищому рівні абстракції порівняно з асемблером. Але і ці сподівання також не виправдалися. Відмінності в рівні абстракції виявилися, у кращому разі, незначними.

Наостанок уявіть, що одного прекрасного дня буде винайдено дійсно працездатну й ефективну діаграмну мову. Але ж малювати діаграми будуть не архітектори, а ті самі розробники! Діаграми перетворяться на новий різновид коду, і розробникам доведеться «малювати» цей код — адже все зводиться до подробиць, а керувати ними доводиться саме розробникам.

Висновки

Відтоді як я зайнявся програмуванням, з’явилися безліч нових і надзвичайно потужних інструментів. Мій поточний інструментарій обмежується невеликою підмножиною цього арсеналу. Я використовую git для керування вихідним кодом, Tracker для відстеження поточних завдань, Jenkins для безперервного складання, інтегроване середовище IntelliJ, XUnit для тестування і FitNesse для компонентного тестування.

Я працюю на комп’ютері Macbook Pro із процесором Intel Core i7 із тактовою частотою 2,8 ГГц, із 17-дюймовим монітором, 8 Гб пам’яті, 512 Гб SSD та двома додатковими екранами.

На жаль, цей розділ недоступний у безкоштовному уривку.