Дванадцять порад початківцю від досвідченого Rails ментора

10 хв. читання

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

Тестування

Розпочнемо з тестування. Для впевненості у тому, що сайт працює правильно, потрібно його тестувати. Rails по замовчуванню використовує Minitest у ролі фреймворку для тестування, але я віддаю перевагу RSpec.

Test-driven development або TDD — процес розробки застосунку, який передбачає створення тестів перед додаванням нового функціоналу. З першого погляду це може здаватися як марна трата часу — потрібно витратити додатковий час для написання тесту, вирішити що протестувати. Але вони спрощують процес додавання нового і редагування старого функціоналу. Вам не потрібно після кожної зміни перевіряти в браузері чи код працює, достатньо запустити тести.

Нижче декілька ресурсів з навчальним матеріалом про TDD:

DRY(Don't repeat yourself)

Rails підтримує ідею DRY (не повторюй сам себе). Принцип полягає в тому, щоб при потребі використовувати один і той же код в декількох місцях. Це призводить до зменшення кількість помилок та пришвидшує розробку.

Правила Сенді Метц

Сенді Метц добре відомий Рубі інженер. Вона є автором таких книг як: Practical Object-Oriented Design in Ruby і Ruby and 99 Bottles of OOP. Нижче наведені рекомендовані нею правила:

1. Клас не повинен бути довшим за сто рядків.

Хорошим способом дотримання цього правила є винесення певного функціонала в інші модулі (include/extend/prepend). Нижче наведені посилання на корисні ресурси.

2. Методи не повинні бути довшими за п'ять лінійок.

Чим менша кількість лінійок, тим простіший метод. Назва методу повинна чітко описувати те що він виконує. Правило п'яти лінійок пов'язане з if-else оператором. Саме його реалізація потребує стільки ж рядків. На практиці важко описати метод п'ятьма лінійками, старайтесь використати найменше.

3. Передавайте не більше чотирьох аргументів в метод.

Багато параметрів в результаті дадуть:

  • Складність сприйняття
  • Важче тестувати, через створення великої кількості даних.
  • Чим менше параметрів, тим простіший і зрозуміліший метод.

4. В методі контролера не використовувати більше ніж одну змінну (instance variable).

З одною змінною ви зберігаєте кращий контроль над нею, і запобігаєте її перезаписанню. Шаблон виглядатиме більш чистим та зрозумілим.

Трохи більше про правила можете дізнатися тут: Sandi Metz' Rules For Developers.

Extract method

Важливо, щоб назва методу відповідала його призначенню. Існує хороша практика на кожну дію, створювати окремий метод. Це дозволить швидше зрозуміти логіку новим розробникам, полегшить тестування, та зробить процес визначення незрозумілої поведінки простішим.

SOLID

SOLID – абревіатура принципів проектування класів в програмуванні, розшифровується як:

  • Принцип єдиної відповідальності (Single responsibility).
  • Принцип відкритості / закритості (Open-closed).
  • Принцип підставлення Лісков (Liskov substitution).
  • Принцип поділу інтерфейсу (Interface segregation).
  • Принцип інверсії залежностей (Dependency invertion).

Дотримання цих правил дозволить вам писати зрозумілий, гнучкий код.

N+1 Query

N+1 – проблема шаблону проектування доступу до реляційних баз даних (ActiveRecord), яка впливає на швидкодію запитів та збільшує їхню кількість. Вона з'являється коли потрібно отримати дані з декількох пов'язаних таблиць. Наприклад:

class User
 has_many :posts
end
class Post
 belongs_to :user
end

posts = Post.last(10)
posts.map { |post| post.user.name }

Вище наведений приклад виконає 11 запитів в БД. Один запит витягне десять останніх Post записів, і ще десять інших ім'я user. В Rails є простий і ефективний спосіб вирішення цієї проблеми:

  posts = Post.includes(:user).last(10)
  posts.map { |post| post.user.name } 

Після додавання includes(:user), ми зменшимо кількість запитів до двох. Назва цього підходу eager loading. Більше інформації зможете знайти в цих статтях:

Memoization

Memoization – процес кешування результатів обчислень методів. Кожний наступний виклик такого методу, буде повертати закешований результат, це збереже ресурси системи та суттєво пришвидшить час відповіді. Memoization доречно використовувати коли метод викликається більше одного разу. Скажімо, вам потрібно створити звіт для компаній у вигляді таблиці з їх назвами в <header> та деякими обрахунками в <body>.

class CompaniesController
 def index
   @companies ||= Company.all
 end
 private

 helper_method :grouped_by_day_activities
 helper_method :activities_count
 def grouped_by_day_activities
   @grouped_by_day ||= Activity.all.group_by(&:day)
 end
 def activities_count
   @activities_count ||= grouped_by_day_activities.map do |day, activities|
     grouped_by_company_activities_count =     activities.group_by(&:company_id).map do |c_id, activities|
       [c_id, activities.count]
     end.to_h
     [day, grouped_by_company_activities_count]
   end.to_h
 end
end
# activities_count =>
# { '1/1/2018': { 1: 10, 2: 6, 3: 9 },
#   '2/1/2018': { 1: 5, 2:  4, 3: 7} }
.....
/companies/index.haml
%table
 %thead   
   %th Date
   - @companies.each do
     %th= copmany.name
 %tbody
   - grouped_by_day_activities.each do |day, activities|
     %tr
       %td= day
       - @companies.each do |company|
         %td= activities_count.fetch(day).fetch(company.id, 0)

В цьому випадку кожен метод контролера використовує Memoization. Memoizetion ініціалізується за допомогою ||= (або-рівне) знаку. Почнемо з @companies змінної. Вона виконується двічі: в <header> таблиці та <body>. Під час другого виконання змінної виконався закешований результат, та зменшив кількість запитів в БД.

Наступний метод grouped_by_day_activities, повертає згруповані за днем дії компаній. Перший раз він викликається в тілі таблиці, а другий з методу activities_count. Activities_count повертає хеш згрупованих за day та company_id дій(activities) всіх компаній. Цей метод викликається в кожній секції таблиці, тому доречно використовувати memoizetion. Також можна використовувати memoization в більш складних випадках у поєднанні з метапрограмуванням.

Authentication

Аутентифікація – механізм перевірки ідентичності та прав доступу, дозволяє ховати частини програми від користувачів без повноважень. Я рекомендую використовувати devise гем.

Authorization

Авторизація – процес перевірки чи користувач може виконати дію. Уявімо, що система має користувачів трьох типів: адмін, гість, менеджер. Наша ціль дозволити редагувати пости тільки адмінам і менеджерам, в результаті отримаємо:

If user.role == 'admin' || user.role == 'manager'
= link_to 'Edit post', edit_post_path(post)

Припустимо, що по всьому сайті в нас є схожі перевірки. Раптом, ми вирішуємо дозволити редагувати гостям їхні пости. Після цього потрібно пройтися по всіх файлах і змінити умову на таку:

If user.role == 'admin' || user.role == 'manager' || user.role == 'guest'

Використовуючи гем pundit, в проект буде додана директорія /policies, в якій буде зберігатися логіка прав доступу кожної сутності проекту. Наприклад:

class UserPolicy
 def can_edit_post?
  user.role == 'admin' || user.role == 'manager' || user.role == 'guest'
 end
end

If оператор буде виглядати як:

If policy(user).can_edit_post?
  = link_to 'Edit post', edit_post_path(post)

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

Детальніше можна прочитати тут:

7 патернів для рефакторингу Rails застосунку

Рефакторинг – процес оновлення програмного коду, спрямований на підвищення швидкодії, покращення архітектурних рішень, які призведуть до спрощення процесу додавання нового функціоналу, не змінюючи його зовнішньої поведінки. Статті наведені нижче містять загальновідомі способи рефакторингу Rails застосунків.

Background jobs

Швидкодія є одним з найважливіших факторів сучасних веб застосунків. Отримуючи повідомлення від зовнішнього світу, чим швидше користувач отримає результат дії, тим краще. У випадку коли дія повинна виконати щось велике та трудомістке, фонові обчислення будуть правильним рішенням. Фонові чи асинхронні обчислення, виконуються поза основним робочим процесом та не створюють ефекту затримки. Одним з найпопулярніших гемів для фонових робіт є sidekiq.

Відеоуроки

Цікавий та корисний скрінкаст: ruby tapas. Там можна знайти багато відеоуроків різної складності по Рубі.

Висновок

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

Також дуже важливою є підтримка і спрямування в правильне русло від досвідчених у своїй галузі людей.

Коли починаєш вчити щось нове, найважливіше не здаватися. Особисто мені процес вивчення давався дуже складно. Кожного ранку я прокидався з думкою, «Я нічого не знаю, і не буду знати, я безнадійний в цьому». Інколи я витрачав весь день, щоб виконати п'ятихвилинне завдання. Але я не здавався, після декількох місяців почав отримувати задоволення від того що роблю та краще розуміти як працює rails.

Отже, новачкам можу порекомендувати набратись міцного терпіння, не втрачати натхнення і вірити в себе, адже це основні якості для досягнення успіху в будь-якій сфері.

happy coding ;)

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 3.9K
Приєднався: 11 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація