Примечание. Я использовал Ruby только в качестве примера. Это применимо к любому языку программирования.

3 года назад, когда я присоединился к Freshworks, я выучил новый язык программирования - Ruby. В рамках буткемпа я решил 3 упражнения. Мне сразу понравился этот язык, так как он был настолько легким для чтения и записи, как те языки, которые я уже знал - C, C ++, Java.

Сегодня, после 3 лет профессионального опыта в разработке автоматизированных тестов, проверке кода, написании служебных сценариев, чтении гемов (библиотек) и создании небольших веб-приложений , я хотел снова повторить те же упражнения и посмотреть, как я улучшили решение проблем с Ruby. Взгляните на формулировки проблем и разницу в коде по ссылкам, приведенным ниже:

Формулировки проблемы: https://github.com/hassyyy/RubyExercises/blob/master/README.md
v2017 vs v2020:
https://github.com/hassyyy/RubyExercises/compare /v2017...v2020

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

Давайте посмотрим, как я за 3 шага напишу идеальный код для следующей постановки задачи.

Узнайте числа, которые встречаются в массиве ровно дважды
Например, если входные данные - [5, 2, 2, 1, 3, 5, 2, 6, 3, 2], выходными данными должны быть [5 , 3]

Шаг 1. Разберитесь в логике

Решает ли это проблему? Это работает как ожидалось?

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

Сделайте так, чтобы это работало, а затем улучшайте

ip = [3, 2, 2, 1, 5, 3, 2, 6, 5, 2]
op = []
ip.each do |n|
  op << n if ip.count(n) == 2
end
p op.uniq
+------------+----------------------------+
| Array Size | Execution Time(in seconds) |
| 10         | 0.000027                   |
| 100        | 0.000096                   |
| 1000       | 0.008036                   |
| 10000      | 0.695064                   |
| 100000     | 67.535688                  |
+------------+----------------------------+

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

- Дональд Кнут

Шаг 2. Упростите понимание

Легко ли читать? Могу ли я понять логику, просто взглянув на код примерно через год?

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

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

- Гарольд Абельсон

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

input_numbers = [3, 2, 2, 1, 5, 3, 2, 6, 5, 2]
output_numbers = input_numbers.select{ |number| input_numbers.count(number).eql?(2) }
p output_numbers.uniq
+------------+----------------------------+
| Array Size | Execution Time(in seconds) |
| 10         | 0.000025                   |
| 100        | 0.000091                   |
| 1000       | 0.009406                   |
| 10000      | 0.704435                   |
| 100000     | 67.162448                  |
+------------+----------------------------+

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

- Мартин Голдинг

Шаг 3. Настройте производительность

Масштабируемость? Будет ли этого достаточно быстро для больших наборов данных?

Пришло время по-настоящему задуматься о том, насколько быстр и насколько безопасен ваш код. Вы можете пропустить это, если ваш код не будет использоваться для больших наборов данных, или вы можете сделать это позже.

input_numbers = [3, 2, 2, 1, 5, 3, 2, 6, 5, 2]
output_numbers = input_numbers.uniq.select{ |number| input_numbers.count(number).eql?(2) }
p output_numbers
+------------+----------------------------+
| Array Size | Execution Time(in seconds) |
| 10         | 0.000012                   |
| 100        | 0.000054                   |
| 1000       | 0.001173                   |
| 10000      | 0.039133                   |
| 100000     | 0.961844                   |
+------------+----------------------------+

Советы по улучшению:

  1. Обратитесь к документации по часто используемым классам или библиотекам и узнайте обо всех доступных методах. Например: Строка, Массив и Хэш в Ruby.
  2. Узнайте о стандартах и ​​соглашениях языка программирования. Ознакомьтесь с этим руководством по стилю для Ruby.
  3. Много тренируйтесь. Написание служебных сценариев для автоматизации часто выполняемых рабочих процессов и создания небольших приложений.
  4. Просмотрите код, написанный вашими коллегами. Это идеальный способ узнать о различных проблемах и понять, почему код должен быть легко читаемым.
  5. Узнайте, как популярные библиотеки работают под капотом. Недавно я понял, как работает мой самый любимый драгоценный камень (sidekiq), и научился писать код, который имеет сильную логику, легкий для чтения и надежный по производительности.

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