Перед тим як почати писати дану статтю я спробував знайти інших людей
які намагались розглянути код в даному ракурсі - знайшов наступний пост How deep is your code?
Мені потрібен був приклад складного Service Object і
я знайшов його в репозиторії Discourse файл. Я в жодному разі
не критикую даний код, більше того в тому ж самому репозиторії я знайшов чудовий приклад
того що я намагаюсь описати файл
Особисто я надаю перевагу маленьким класам, коротким, single purpose методам,
а не одному великому шматку коду. Проте мушу визнати що даний підхід
має значний недолік - досить часто методи короткі лише тому що
вони викликають інші методи, які викликають інші методи,
які викликають інші методи… Отож, перш ніж я зможу побачити що насправді відбувається,
мені доводиться переглядати купу методів і досить часто я вже не пам’ятаю з чого починав, коли
нарешті знайду те що шукав.
Я не хочу цим займатись, я не хочу переглядати 5-10 приватних методів щоб
мати уявлення якими будуть наслідки виклику одного публічного методу.
я хочу щоб метод одразу, з першого погляду давав зрозуміти що саме відбувається,
можливо є спосіб цього досягнути?
Одного разу я бачив метод оцінки складності коду, який описала Sandi Metz в своєму виступі All the Little Things - the Squint Test.
Не зважаючи на те, що даний метод був застосований для оцінки вкладених conditionals, ми
можемо розглянути виклик методів у схожому контексті. Якщо метод викликає інший метод
давайте ми зробимо відступ зліва, так ніби ми маємо вкладений if:
тепер давайте запишемо всі задіяні методи і зробимо відступи для кожного вкладеного виклику
ми отримали схожу фігуру, що більші нерівною є права її частина - то
більше вкладених викликів ми маємо.
#2.2.1 Refactor UserUpdater#update_user_profile метод (commit)
#2.2.2 Refactor UserUpdater#update_user метод (commit)
#2.2.3 Refactor UserUpdater#update_user_option метод (commit)
#2.2.4 Refactor UserUpdater#save_user_data метод (commit)
Я пропущу деталі, тому що зміни є досить прості і звичні для refactoring, вони були зроблені щоб спростити
UserUpdater#update метод, зробити його коротким і простим для розуміння.
Проте я вважаю, що тепер надто багато інформації приховано
Якщо подивитись на тіло методу ми більше не бачимо що:
В методі використовується транзакція
Деякі частини змінюються лише за виконання певних умов
Ми покладаємось на константу, коли визначаємо які дані змінити
Не очевидно що ми повертаємо (і використовуємо значення) true/false в залежності від
результату транзакції
In addition to hiding information, I storngly dislike how new
Окрім прихованої інформації, мені надзвичайно не подобається як виглядає
UserUpdater#update_user_profile - це приватний метод, який
складається лише викликів інших приватних методів і приховує існуючі conditionals.
Я вважаю що схожі методи лише підвищують складність коду
і не мають права існувати.
На цьому кроці ми позбудемось приватних методів, що були (майже) лише
обгортками навколо інших приватних методів і трохи змінимо назви методів, що залишились,
щоб краще відобразити їх мету
UserUpdater#update метод став майже утричі більшим в порівнянні з
попередньою версією, проте тепер він значно краще розповідає свою історію.
Він не ідеальний (і ніколи таким не буде), проте ми зробимо ще один крок
для його покращення і знову порівняємо з версією з Кроку #2