Рефакторинг - міць прихована в якісному коді

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

Проектування

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

Почати проектувати можна дуже легко. Завжди тримайте на робочому місці блокнот і кілька кольорів ручок. Перш ніж писати код, намалюйте схему - як додаток буде працювати в цілому, UML-діаграму класів (продумайте як можна з мінімальною кількістю класів, досягти максимального результату), структуру баз даних (оптимізуйте БД ще до її створення, подумайте які запити у вас повинні будуть «бігати» до вашої БД, продумайте індекси, звичайно ж нормалізуйте вашу модель даних).

Для тих же цілей підійде проста програма для проектування starUML. Мінус її в тому, що не можна нормально встановлювати потужність відносин (кратність), але сам інтерфейс дуже зручний.

Проектувати потрібно навіть для того, щоб потім не довелося рефакторити структурні помилки, а ще гірше переписувати взагалі весь модуль.

Кілька принципів, які точно потрібно знати при проектуванні класів вашої «Feature»:

1. SOLID (single responsibility, open-closed, Liskov substitution, interface segregation и dependency inversion)

Це основа основ у проектуванні класів. Якщо ви ще не знайомі з SOLID, тут можна ознайомитися.

2. DRY (do not repeat yourself)

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

Наприклад:

- Замість того, щоб використовувати три рядки коду в декількох місцях, можна помістити їх у функцію і використовувати всього лише один рядок коду - виклик функції.

- Замість використання функції progress50 (), краще застосувати абстрактнішу progress ($ percent).

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

3. KISS (keep it simple, stup...)

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

Наприклад:

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

Стиль коду

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

Стандарт стилю коду (і не тільки) PSR (PHP Standards Recommendations), тут можна ознайомитися. Вміст англійською мовою, оскільки англійська більш ясно дає зрозуміти ступінь застосування одного або іншого правила ("MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "",, MAY "

Кілька зауважень, які автор визнав важливими:

1. Ознайомтеся з PHPDOC для написання коментарів до вашого коду.

2. Найкращий коментар - це правильно названий клас, метод, параметр або змінна.

3. Використовуйте програми PHPMD, PHPCS, їх застосування ширше, ніж тільки для визначення невідповідностей у стилі коду. Ось документація: PHPMD, PHPCS.

4. Використовуйте просунуте IDE.

Рефакторинг у чистому вигляді

Дуже проста аксіома - на продакшн повинен потрапляти тільки код, що пройшов рефакторинг. Іноді після розробки ви самі робите рефакторинг, що дуже навіть не погано (наприклад, розробка через тестування взагалі включає рефакторинг, як обов'язковий крок, так як спочатку пишеться «працюючий код», а потім вже «чистий»), але для того, щоб код був по-справжньому якісним, він повинен пройти перевірку коду (code-review) іншим програмістом. Якщо проект дозволяє виділити час на перевірку коду, то на такому проекті ти будеш вчитися писати код чистіше і чистіше, що надалі призведе до автоматичного написання якісного коду.

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

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

1. Довгі методи (краще розділити функціонал на кілька методів).

2. Гучні класи (ваш клас повинен виконувати одну функціональну задачу у вашій системі).

3. Незрозуміла структура класу (методи в хаотичному порядку, конструктор в середині класу, замість констант - магічні значення в коді - клас повинен легко відображати, що він робить в правильній послідовності).

4. Надто багато параметрів у методі (деякі розрахунки можна зробити всередині методу, використовуючи внутрішні константи, значення отримані з атрибутів і геттерів).

5. Класи, що містять однакові змінні та методи. Проблему можна вирішити через створення додаткового класу).

6. Складно читається IF (вираз можна винести в окрему змінну і розділити на логічні частини, які також винести в змінні, якщо багато перевірок на null, то найкраще використовувати NullObject - кількість перевірок значно зменшиться).

7. Громіздкий SWITH (виносимо в окремий метод).

8. Використання спадкування через однакові методи і властивості, в різних за своєю суттю сутностях (кішка і стілець мають ноги, але їх не можна групувати в категорію «тварини»).

9. Занадто велика кількість маленьких класів для виконання одного завдання, які надалі складніше підтримувати.

10. Занадто складний функціонал в одному класі, який можна розділити на кілька класів.

11. Клас робить занадто мало, щоб його залишати в системі.

12. «Мертвий код» - його слід видалити.

13. Не використані структури класів, які ви проектували на майбутнє, але вони так і не стали в нагоді - такі краще видалити.

14. Методи класу більше використовуються в іншому класі, а в своєму взагалі не використовуються або ж рідше (варто перенести метод в той клас, де він більше використовується).

15. Занадто довгий ланцюжок викликів ($ a- > b () - > c () - > d () - > e ()), у цьому випадку варто створити додаткові методи.

16. Клас, що містить лише один метод, який створює інший клас. (Такий клас потрібно використовувати з розумом, наприклад, для патерну «Проксі», в іншому випадку цей клас тільки збільшує час і ресурс на підтримку проекту).

17. Занадто багато дій в конструкторі. (Конструктор повинен тільки встановлювати властивості класу, якщо ж у конструкторі створюються інші класи, відбуваються якісь розрахунки, то це робить його складним для розуміння, доводиться вникати в суть реалізації. Щоб створити об'єкт і виконати якісь дії, додайте статичний метод create ($ param1,...), який створить екземпляр класу з додатковими діями над ним, цей метод можна назвати більш підходящим до того, що він буде все ж таки робити).

Список літератури

» Source Making

» PSR

» UML

logo