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

Извлечение классов и рефакторинг

Во-первых, всем, кто, как и я, занимается эвакуацией, я рекомендую прочитать как можно больше Санди Мец. Ее книга Практическое объектно-ориентированное проектирование в Ruby, например, была неоценимой. Когда я готовился к рефакторингу своего кода, я наткнулся на пост, в котором кратко излагались несколько ее правил для разработчиков из серии подкастов, которые она подготовила для начинающих. Это были правила, которые я нарушил:

1. Классы не могут быть длиннее ста строк кода.

2. Методы не могут быть длиннее пяти строк кода. — Калеб Томпсон, правила Сэнди Метц для разработчиков

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

Вернувшись к работе над проектом, я решил отказаться от того, что написал, и начать заново. Я вспомнил введение в Corey Haines Understanding the Four Rules of Simple Design и то, как принуждение начать заново часто может привести к лучшему коду и заставить вас подойти к проблеме по-новому:

Большинство людей начинают работать над проблемой так, как им удобно. Ограничения существуют для того, чтобы лишить их возможности кодировать знакомым и удобным способом… Отделение идентичности от кода освобождает их для экспериментов с новыми идеями. Когда ценность не привязана к количеству (или качеству) кода, они могут с большей готовностью признать, что попытка не работает, и отказаться от нее. — Кори Хейнс понимает четыре правила простого дизайна

Мой подход

В конце концов я решил провести рефакторинг того, что мне нужно было сделать, чтобы удобнее было извлекать классы. Мой подход заключался в том, чтобы увеличивать масштаб по одному шагу за раз. Этот фокус внимания помог мне не перегружаться поставленной задачей. Вот краткое описание того, как я делал свою добычу:

Показать

Я уже создал класс Display, но не использовал его должным образом. На самом деле в нем был только один метод, который служил определенной цели, но это означало, что большая часть его поведения была передана Takeaway, и это было одной из основных причин, почему класс Takeaway был таким длинным.

Первое, что я сделал, это нашел все puts и извлек их в класс Display. Это дало мне много преимуществ, поскольку я получил ясность по программе. Он упростил класс Takeaway примерно на 50 строк, сведя методы к единой ответственности. Стало очевидным, что многие методы делают несколько вещей, и одной из причин этого было то, что они отображали выходные данные. Я переименовал методы и некоторые переменные, чтобы было ясно, что эти объекты делают в контексте поведения класса.

Другое преимущество было в моих тестах. Поскольку у всех них теперь был стандартный вывод в качестве теста, мне было легче определить закономерность того, как правильно справляться с этим последовательно.

Меню

Второе, что я сделал, это переложил часть ответственности с Takeaway на Menu. На самом деле уже были некоторые методы, такие как «extract_starters», которые явно указывали своим именем, что их поведение принадлежит другому классу.

Это было похоже на весеннюю уборку, поскольку я снова взял около 37 строк кода из Takeaway в Menu. Это дало мне и другим разработчикам, которые могли прийти в программу, ясность в различиях между ними. С целью, перефразируя Кента Бека, сделать мою программу выражением требований в коде.

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

Забегая вперед, я хотел бы убедиться, что почти непрерывные решения, принимаемые в отношении таких вещей, как присвоение имен переменным и извлечение методов (Corey Haines Understanding the Four Rules of Simple Design), стали практикой, которую я неукоснительно интегрирую с самого начала разработки. проект, а не в конце.

Я также хотел бы поэкспериментировать с более экстремальным подходом, описанным Кори Хейнсом для ката, чтобы заставить себя меньше отождествлять себя с кодом и попробовать новые способы решения проблемы, которые находятся вне моей зоны комфорта.