Почему я люблю copy-paste при написании кода?
Не только люблю, но и всячески советую использовать этот подход. “Избегайте copy-paste любыми возможными способами!” – сколько раз я это слышал – столько-же раз умилялся. Если начать расспрашивать автора подобных заявлений об этих самых “всех возможных способах”, получите типичную жевачку про “паттерны проектирования” и инкапсуляцию.
Всё дело в том, что сразу писать программу паттернами проектирования не имеет никакого практического смысла. Получите неоправданно сложную систему или выбросите всё к чертям и начнёте сначала. И инкапсулировать правильно, пока еще есть много неизвестных деталей, вы не сможете. Основым принципом при написании софта – да и вообще по жизни – у меня является YAGNI – You Aren't Gonna Need It. Когда я начинаю писать программу, я абсолютно не представляю, какой структурой классов закончится этот мой творческий акт через неделю или месяц.
Я три года писал свои программы в стиле test-driven development. По-честному. Сначала тест или сразу несколько тестов – потом код. Среднее покрытие кода в 75-80% – это то, что я мог гарантировать даже изначально. Это с учётом того, что кое-что тестами покрыть всё равно не получается, а кое-что будет покрыто на 100%. Я научился тестировать пользовательский интерфейс “из кода”, а не снаружи, и добился того, что мои программы после интеграции работали безошибочно; доработал под себя один хороший тестовый фреймворк в .NET, опубликовал несколько статей по test-driven development на blogs.gotdotnet.ru. И могу с уверенностью сказать, что именно эта методология сделала из меня хорошего дизайнера программного обеспечения. Первое, что я делал при знакомстве с новой средой разработки, это учился писать и выполнять тесты. И только потом брался за разработку продукта.
Я люблю test-driven development. И если вы новичок в разработке софта, я всячески рекомендую начать именно отсюда. Чтобы обосновать свою глубокую причастность к test-driven development и был написан предыдущий абзац. Но со временем я набил руку до такой степени, что перестал писать тесты где-то в отдельных файлах. Я стал писать тесты сразу в коде! Смысл test-driven development легко можно изложить в одном предложении: “Вы пишете тест таким образом, как вы хотите, чтобы потом ваш код можно было использовать”. То-же самое я стал делать прямо в своём коде.
Другими словами, я создавал какой-то новый класс, который должен был выполнять некоторую высокоуровневую задачу. Разумеется, что в таком случае нам понадабятся классы-помощники, или сервисы, если придерживаться англоязычной терминологии. Но их не было. Не важно. Это не мешало мне создавать экземпляры несуществующих типов и вызывать несуществующие методы и уже не где-то на бумаге, а прямо на клавиатуре создавать будущий публичный интерфейс сервисов!
Вы, естественно, можете удостовериться дополнительно, что ваша программа совершенно случайным образом не компилируется. Хоть для меня это более, чем очевидно, тем не менее, в test-driven development это отыгрывает очень важную роль. Тесты на проверку состояния мне стали не нужны. Благодаря простому и надёжному дизайну это легко просматривается уже из кода, а многие ситуации я могу просчитать и предугадать и в голове. Поэтому никакого неудобства от отсутствия проверки на состояния я не испытываю. В крайнем случае я делаю вывод в консоль и очень редко ставлю точку останова. Тем не менее, так я достиг качества кода, сравнимое с тем, что я получал при test-driven development, но избавился от написания отдельных тестов, т.к. сам код как-бы являлся тестом для самого себя. Вы должны работать только над тем кодом, который впоследствии окажется вкомпилированным в исполняемый файл, который вы отдаёте клиенту.
N.B. Я по совместительству являюсь еще и сейлзом проектов. И еще ни один клиент не раскрыл рот, когда я ему заявлял, что я ему гарантирую покрытие 90% для функционального кода. Я встречал разные эмоции – от игнорирования до равнодушия. Думаю, вы меня понимаете. Платят за конечный качественный результат. Я рассказываю, как достичь этого, не делая двойной или даже четверной работы. Вы можете как угодно обосновывать стоимость проекта, но вы должны оставаться конкурентноспособными, не жить в проголодь и работать по своему расчётному рейту или даже выше.
Только теперь, когда у вас есть план того, как должны выглядеть помощники, вы начинаете их реализацию. Реализацию, естественно, для начала не полноценную, а только так, чтобы программа компилировалась. Возвращаете указатель – возвращайте пока nil, а не “хороший” объект. Если функция должна быть void – объявите ее и все. Просто доведите код до состояния Build succeeded.
Главное для нас – это публичный интерфейс. Никакие внутренние детали нас касаться не должны. Они могут быть неаккуратными, фейковыми, быть обыкновенными заглушками или ужасно тормозить. Если где-то в каком-то месте программы вы чувствуете, что нужно скопи-пастить – берите и копи-пастите. Никакой инкапсуляцией на этом этапе заниматься противопоказано! Вы насоздаёте мелких классов и получите головную боль в итоге. Копи-пастите и копи-пастите, похожие куски кода в разных классах или методах доводите до идентичности. Возведите этот принцип в абсолют. Именно он позволяет мне строить элегантные объектно-ориентированные системы. Выполняйте эту процедуру столько, сколько необходимо для того, чтобы у вас в голове созрел дизайн следующего сервисного класса.
Еще одним бонусом, который вы получаете при использовании test-driven development – это возможность безболезненного рефакторинга. В нашем случае рефакторинг – это превращение идентичных кусков в отдельные классы. Да, так просто. Никаких там книжек толстенных по рефакторингу вам читать не нужно, чтобы добиться качественного кода. Просто запомните: рефакторинг – это очень просто. Это перемещение и объединение кусков кода. Правильно и без ошибок это гораздо быстрее сделать без тестов, чем с тестами. Ваш рефакторинг – это не на пол-дня, как у некоторых происходит. Вы пишете программу мелкими перебежками. Любая операция – простая. Вырезать из одного места, перенести в другое, удалить дубликаты, заменить на обращения к сервису. Любой класс – простой и осягаемый глазом, все связи и зависимости легко просматриваются. При таком подходе и голове на плечах отсутствие тестов сбросит с вас оковы (а это всё-таки оковы, кто-бы что не говорил) и вы сможете лепить код, как из глины, не озираясь на какие-то вторичные факторы и не нанося ущерба стабильности.
Я всегда думал, что книжки вроде “Паттерны проектирования” написаны для тех, кто не умеет писать программы. Ну согласитесь-же, что если вы просто как любой нормальный мужчина можете без труда, когда заблагорассудиться, заводить отношения с девушками, то вы не будете заниматься вот этой вот херней с пикапами, эриксоновскими гипнозами и рутинами. Паттерны – это рутины, для тех, кто не умеет программировать.
У хороших-же программистов паттерны выскакивают прямо из-под клавиатуры. Сами по себе. Сначала идёт код, потом паттерны, а не наоборот. Вы просто работаете в тональности “наделать как можно больше похожих кусков – и вытащить функционал в отдельный класс”. И все паттерны придут к вам сами по себе.
Это всё, что вам нужно знать о test-driven development и agile вообще, если вдруг вы захотите этим действительно заниматься и зарабатывать деньги, а не вступать в академические флеймы на rsdn.ru.
N.B. Я закончил свою форумную карьеру после того, как мой счётчик сообщений на gotdotnet.ru перевалил за 2500. После этого мне стало скучно участвовать в форумах и я стал писать статьи или вообще заниматься несвязанными с компьютером вещами. Приоритеты меняются со временем, но это позволило мне выработать свой взгляд на многие явления в жизни.
Всё остальное к вам придёт с практикой. Существует очень много вещей, которые нельзя изложить на бумаге, это нужно прочувствовать, осознать. Тем не менее, сейчас для закрепления материала, мы с вами напишем что-то в моём стиле. Под iPhone, т.к. это то, с чем я сейчас работаю больше всего. (Продолжение в следующих сериях.)
Всё дело в том, что сразу писать программу паттернами проектирования не имеет никакого практического смысла. Получите неоправданно сложную систему или выбросите всё к чертям и начнёте сначала. И инкапсулировать правильно, пока еще есть много неизвестных деталей, вы не сможете. Основым принципом при написании софта – да и вообще по жизни – у меня является YAGNI – You Aren't Gonna Need It. Когда я начинаю писать программу, я абсолютно не представляю, какой структурой классов закончится этот мой творческий акт через неделю или месяц.
Я три года писал свои программы в стиле test-driven development. По-честному. Сначала тест или сразу несколько тестов – потом код. Среднее покрытие кода в 75-80% – это то, что я мог гарантировать даже изначально. Это с учётом того, что кое-что тестами покрыть всё равно не получается, а кое-что будет покрыто на 100%. Я научился тестировать пользовательский интерфейс “из кода”, а не снаружи, и добился того, что мои программы после интеграции работали безошибочно; доработал под себя один хороший тестовый фреймворк в .NET, опубликовал несколько статей по test-driven development на blogs.gotdotnet.ru. И могу с уверенностью сказать, что именно эта методология сделала из меня хорошего дизайнера программного обеспечения. Первое, что я делал при знакомстве с новой средой разработки, это учился писать и выполнять тесты. И только потом брался за разработку продукта.
Я люблю test-driven development. И если вы новичок в разработке софта, я всячески рекомендую начать именно отсюда. Чтобы обосновать свою глубокую причастность к test-driven development и был написан предыдущий абзац. Но со временем я набил руку до такой степени, что перестал писать тесты где-то в отдельных файлах. Я стал писать тесты сразу в коде! Смысл test-driven development легко можно изложить в одном предложении: “Вы пишете тест таким образом, как вы хотите, чтобы потом ваш код можно было использовать”. То-же самое я стал делать прямо в своём коде.
Другими словами, я создавал какой-то новый класс, который должен был выполнять некоторую высокоуровневую задачу. Разумеется, что в таком случае нам понадабятся классы-помощники, или сервисы, если придерживаться англоязычной терминологии. Но их не было. Не важно. Это не мешало мне создавать экземпляры несуществующих типов и вызывать несуществующие методы и уже не где-то на бумаге, а прямо на клавиатуре создавать будущий публичный интерфейс сервисов!
Вы, естественно, можете удостовериться дополнительно, что ваша программа совершенно случайным образом не компилируется. Хоть для меня это более, чем очевидно, тем не менее, в test-driven development это отыгрывает очень важную роль. Тесты на проверку состояния мне стали не нужны. Благодаря простому и надёжному дизайну это легко просматривается уже из кода, а многие ситуации я могу просчитать и предугадать и в голове. Поэтому никакого неудобства от отсутствия проверки на состояния я не испытываю. В крайнем случае я делаю вывод в консоль и очень редко ставлю точку останова. Тем не менее, так я достиг качества кода, сравнимое с тем, что я получал при test-driven development, но избавился от написания отдельных тестов, т.к. сам код как-бы являлся тестом для самого себя. Вы должны работать только над тем кодом, который впоследствии окажется вкомпилированным в исполняемый файл, который вы отдаёте клиенту.
N.B. Я по совместительству являюсь еще и сейлзом проектов. И еще ни один клиент не раскрыл рот, когда я ему заявлял, что я ему гарантирую покрытие 90% для функционального кода. Я встречал разные эмоции – от игнорирования до равнодушия. Думаю, вы меня понимаете. Платят за конечный качественный результат. Я рассказываю, как достичь этого, не делая двойной или даже четверной работы. Вы можете как угодно обосновывать стоимость проекта, но вы должны оставаться конкурентноспособными, не жить в проголодь и работать по своему расчётному рейту или даже выше.
Только теперь, когда у вас есть план того, как должны выглядеть помощники, вы начинаете их реализацию. Реализацию, естественно, для начала не полноценную, а только так, чтобы программа компилировалась. Возвращаете указатель – возвращайте пока nil, а не “хороший” объект. Если функция должна быть void – объявите ее и все. Просто доведите код до состояния Build succeeded.
Главное для нас – это публичный интерфейс. Никакие внутренние детали нас касаться не должны. Они могут быть неаккуратными, фейковыми, быть обыкновенными заглушками или ужасно тормозить. Если где-то в каком-то месте программы вы чувствуете, что нужно скопи-пастить – берите и копи-пастите. Никакой инкапсуляцией на этом этапе заниматься противопоказано! Вы насоздаёте мелких классов и получите головную боль в итоге. Копи-пастите и копи-пастите, похожие куски кода в разных классах или методах доводите до идентичности. Возведите этот принцип в абсолют. Именно он позволяет мне строить элегантные объектно-ориентированные системы. Выполняйте эту процедуру столько, сколько необходимо для того, чтобы у вас в голове созрел дизайн следующего сервисного класса.
Еще одним бонусом, который вы получаете при использовании test-driven development – это возможность безболезненного рефакторинга. В нашем случае рефакторинг – это превращение идентичных кусков в отдельные классы. Да, так просто. Никаких там книжек толстенных по рефакторингу вам читать не нужно, чтобы добиться качественного кода. Просто запомните: рефакторинг – это очень просто. Это перемещение и объединение кусков кода. Правильно и без ошибок это гораздо быстрее сделать без тестов, чем с тестами. Ваш рефакторинг – это не на пол-дня, как у некоторых происходит. Вы пишете программу мелкими перебежками. Любая операция – простая. Вырезать из одного места, перенести в другое, удалить дубликаты, заменить на обращения к сервису. Любой класс – простой и осягаемый глазом, все связи и зависимости легко просматриваются. При таком подходе и голове на плечах отсутствие тестов сбросит с вас оковы (а это всё-таки оковы, кто-бы что не говорил) и вы сможете лепить код, как из глины, не озираясь на какие-то вторичные факторы и не нанося ущерба стабильности.
Я всегда думал, что книжки вроде “Паттерны проектирования” написаны для тех, кто не умеет писать программы. Ну согласитесь-же, что если вы просто как любой нормальный мужчина можете без труда, когда заблагорассудиться, заводить отношения с девушками, то вы не будете заниматься вот этой вот херней с пикапами, эриксоновскими гипнозами и рутинами. Паттерны – это рутины, для тех, кто не умеет программировать.
У хороших-же программистов паттерны выскакивают прямо из-под клавиатуры. Сами по себе. Сначала идёт код, потом паттерны, а не наоборот. Вы просто работаете в тональности “наделать как можно больше похожих кусков – и вытащить функционал в отдельный класс”. И все паттерны придут к вам сами по себе.
Это всё, что вам нужно знать о test-driven development и agile вообще, если вдруг вы захотите этим действительно заниматься и зарабатывать деньги, а не вступать в академические флеймы на rsdn.ru.
N.B. Я закончил свою форумную карьеру после того, как мой счётчик сообщений на gotdotnet.ru перевалил за 2500. После этого мне стало скучно участвовать в форумах и я стал писать статьи или вообще заниматься несвязанными с компьютером вещами. Приоритеты меняются со временем, но это позволило мне выработать свой взгляд на многие явления в жизни.
Всё остальное к вам придёт с практикой. Существует очень много вещей, которые нельзя изложить на бумаге, это нужно прочувствовать, осознать. Тем не менее, сейчас для закрепления материала, мы с вами напишем что-то в моём стиле. Под iPhone, т.к. это то, с чем я сейчас работаю больше всего. (Продолжение в следующих сериях.)



комментарии (172)