Все началось как вызов. Успейте сделать это до понедельника как можно лучше. Я поставил цель провести один продуктивный день на этой задаче. Это означает ~ 6 часов кодирования, чтобы сделать все это, так как всегда есть более важные дела, чем развлечения.

Большую часть времени я думал о простоте и дизайне программ на Ruby, и это основная тема того, что вы собираетесь прочитать. Я решил написать об этом в блоге, так как мне очень нравится разработка Ruby, и, вероятно, из-за предстоящего eruko2016.org, вдохновившего меня поделиться некоторыми причинами, по которым я люблю Ruby. Вернемся к правилам игры.

Короче говоря: создайте CLI-редактор изображений.

— Пиксель изображения представлен символом в верхнем регистре.

— Пользователь должен иметь возможность рисовать другим цветом (скажем, символом) с заданными координатами x и y.

— Пользователь должен иметь возможность рисовать линии по вертикали и горизонтали слева направо и справа налево

— Изображение должно отображаться/отрисовываться в консоли

06:00 Планирование

Простота, удобочитаемость и расширяемость. Это были мои приоритеты. Держать его просто глупо.

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

  1. Для программы с интерфейсом командной строки нам определенно нужен «клиент» CLI, который обрабатывает ввод-вывод.
  2. Модель изображения, содержащая пиксели, представленные символами. 2D-массив? Матрица?
  3. Четкий способ редактирования изображения и добавления новых функций. (Нужно ли нам хранить историю?)
  4. Интерфейс рендерера с базовым консольным рендерером, который можно легко заменить на тот, который выводит в файл.

05:30 Нейминг

Это всегда самая важная часть. Никогда не недооценивайте.

05:29 Реализация

app/
|_edit.rb     # module that holds all edit actions
|_cli.rb      # class to handle user input
|_image.rb    # somethin to represent image
|_renderer.rb # renders image in console
runner.rb     # runs the whole party

Все работает, пара спецификаций покрывает это, и базовая структура выглядит правильно, верно?

03:30 Нет.

После того, как я создал и протестировал изображение, средство визуализации и базовый интерфейс командной строки, пришло время заняться реальным делом. Редактирование. Цель состояла в том, чтобы сохранить его легко обширным. Напишите 1 или 2 коротких метода, если хотите добавить новый инструмент.

Несмотря на то, что он оставался базовым с изображением и средством визуализации, он, безусловно, содержал код в чистоте (массив 2d, содержащий пиксели), кажется, что редактирование изображения не требует ввода, и edit.rb быстро вырос до более чем сотни loc, что является умственным барьер для меня. Пришлось разделить.

app/
|_edit/
  |_base.rb              # initialize(@image);
  |_clear.rb             # exec(params)
  |_dot.rb               # exec(params)
  |_vertical_line.rb     # exec(params)
  |_horizontal_line.rb   # exec(params)
cli.rb: Edit::Clear.new(@image).exec # seems legit

03:27:56.8

Конечно, это решение мне нравилось целых 3,2 секунды, пока в голове не закипели все остальные варианты.

Эй, если вы хотите произвести впечатление на всех, загрузите эти команды редактирования во время выполнения!
О боже, о боже!

Должен ли я перечислить их в .yml, чтобы команды имели описания и
все автоматически считывались во время выполнения??

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

Придерживайтесь своего плана. Упростите это. Не усложняйте. Следует задавать такие вопросы, как «Нам это нужно?», «Нам это когда-нибудь понадобится?», «Как мы можем справиться с ситуацией тогда, если мы не сделаем этого сейчас?». Если вы сомневаетесь, всегда задавайте их в этой последовательности. Просто не позволяйте себе думать слишком далеко без причины. Тик-так. Код.

01:00 Брейн, ты рад, что я ничего этого не делал?

Я придерживался своего основного первоначального решения. Все просто работает. Никаких хаков, никаких умопомрачительных джунглей объектов. Меню всего пять, когда дела в цикле? Делает работу на данный момент. Не сексуально, но все же достаточно хорошо. Когда (если) он растет, это нужно изменить на какой-то интерпретатор. Упаковать в драгоценный камень? Ставить КИ? Думаю, вы поняли. Это легкие части, и их всегда можно сделать позже. Тратьте время с умом и производите меньше.

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

Как всегда, правильное тестирование (имеется в виду последние 10%) займет большую часть времени, но даже с несколькими крайними сценариями мы можем покрыть 90% логики. Метод делает что-то необычное? Специфицируйте это! В противном случае не утруждайте себя тестированием рубиновых структур и методов.

00:10 Заканчиваем. Я всегда хотел…

… строки юникода должны обрабатываться одинаково! Я решил, что последний час я потрачу на какую-нибудь крутизну, например, на Ruby 2.40, а также на поддержку

"мария".upcase() # out of the box. Mind blown.

Заворачивать.

00:00. git push

Мне понравилось, как концентрация на достижении простой цели простым способом дает чистый и удобный код. Если я чему-то и научился, так это тому, чтовключайте инструмент только тогда, когда обходной путь сложнее, чем просто его использование.

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

Начинается неделя рубинового чуда. ❤ или подпишитесь, чтобы узнать больше.