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

Часы летят, пока вы набираете текст на клавиатуре. Вы создали класс меню интерфейса командной строки, при инициализации которого вы вызываете метод экземпляра с именем main_menu. Оттуда вы переходите к различным методам, которые представлены в виде опций в вашем меню. Когда вы начнете работать, вы поймете, что для ваших опций потребуются опции, а для этого потребуется написание подменю. То, что должно было быть простой системой меню, теперь состоит из двухсот строк операторов case, зажатых между всем отображаемым текстом, который вам нужно показать пользователю. Теперь каждый раз, когда вы хотите заняться чем-то новым или функциональным, ваш проект превращается в лабиринт, и вы тратите драгоценное время, пытаясь вспомнить, что к чему должно привести, когда вы делаете свое меню функциональным. Даже неважно, если кто-то еще должен будет просмотреть или добавить в ваш код.

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

Представим, что мы создаем приложение с интерфейсом командной строки, которое используется для бронирования планов поездок. Он должен иметь возможность бронировать поездки, просматривать места, куда можно пойти, и отменять забронированные поездки. Я собираюсь создать простую версию этого приложения в виде класса CLI, чтобы мы могли увидеть, как реализация очень простой концепции может создать множество строк кода, которые затруднят чтение вашего проекта.

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

Сначала нам нужно разработать стратегию, как мы хотим разбить это, потому что это меню управляется целочисленным вводом пользователя. Я хотел бы разбить каждую функцию меню на отдельный файл в папке библиотеки. Каждый файл будет переименован в соответствии с соглашением, основанным на структуре вашего меню. Я предпочитаю использовать символы подчеркивания и целые числа вне слова «главное» для обозначения главного меню, а затем следует выбор выбора, необходимый для выполнения функции. Таким образом, имя файла для бронирования поездки в этом примере будет «main_1», для бронирования поездки будет «main_2» и так далее. Другая стратегия - вы можете сделать имена файлов более информативными по сравнению с опциями меню, такими как «main_1book_trip». Все зависит от ваших собственных предпочтений, важно иметь системный способ организации файлов меню, чтобы вам никогда не приходилось гадать, что к чему в вашем приложении.

Выглядит лучше, но еще несколько шагов, чтобы заставить его работать. Нам нужно изменить каждый экземпляр «self» в нашей библиотеке на «cli», а также нам нужен метод main_menu, который вызывается при инициализации, передает self в качестве аргумента.

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

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

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

Давайте возьмем все строки put, которые есть в наших функциях, которые служат только для отображения текста меню, и извлечем их в функции, хранящиеся в отдельной папке. У файлов будет соглашение об именах, которое соответствует нашим функциям меню, только мы будем добавлять к ним буквы «disp».

puts “ — — — — — — — — — — — — — — — — — “

Кроме того, поскольку мы используем эту строку практически во всех наших методах, мы можем выделить ее в отдельный общий метод отображения в нашей папке средства отображения в новом файле с именем «general».

def print_line
  puts “ — — — — — — — — — — — — — — — — — “
end

Теперь, когда нам нужно вывести красивую строку в нашем меню, мы просто вызываем print_line вместо того, чтобы копировать и вставлять / вводить всю строку. Итак, когда мы завершили этот этап рефакторинга. Так будет выглядеть метод main_menu в разделении с его методами отображения после того, как наш код будет полностью переработан в соответствии с нашими соглашениями.

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