Ios, чистий код, блог

Ios, чистий код, блог

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

Отже, якими критеріями визначається чистота коду?

іменування

Іноді це дуже складний і «філософський» питання. Основні правила:

  • ім'я змінної повинно бути максимально коротким і максимально чітко відповідати на питання «що зберігається в цій змінній» і «яким чином змінна буде використовуватися». При цьому зрозумілість має більший пріоритет, ніж стислість. Те ж саме стосується і функцій;
  • використовуємо camelCase для назв змінних і функцій, які складаються з декількох слів;
  • тільки англійську мову. Часто буває, що першу версію проекту писали розробники з однієї країни, а другу версію - з іншого. І франкомовний розробник вже не зрозуміє, що хотів сказати російськомовний, назвавши змінні var moiTovary. var cena. var ssylka;
  • короткі імена типу «var a, let b» має сенс використовувати тільки для змінних місцевого значення, в невеликому фрагменті коду.

Основні критерії, якими я керуюся при написанні функцій:

  • створення нової функції замість дублювання коду. Якщо в 2-х місцях є однаковий код на 2-3 або більше рядків, то варто винести цю частину коду в окрему функцію.

форматування

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

Приклад структури проекту:

Дотримання єдиної структури проекту прискорює пошук потрібних файлів. Не менш важливим є і форматування класів. основні його принципи:

Один файл - один клас (структура).

Детальніше по пунктам:

Більш повний список Pragma Marks:

Код виглядає ще більш структурованим, якщо функції і змінні форматируются за допомогою PragmaMarks в заданій послідовності, а не розкидані випадковим чином. Особисто я додав такий список в Xcode як сніпетів, для зручності.

Хороша практика, коли в компанії є документ з назвою на кшталт «iOS Code Styles Guidline», з яким новий співробітник ознайомлюється перед початком роботи і далі форматує код в очікуваному стилі.

рефакторинг

Рефакторинг - це контрольований процес поліпшення вашого коду без написання нового функціоналу. Завдання рефакторінга - зробити код чистим.

Написання коду можна поділити на 2 пункти: зробити, щоб код працював і провести рефакторинг коду. Що може бруднити наш код? Такі речі, як:

архітектурні паттерни

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

Головним дизайн-патерном в Apple (MacOS iOS) є MVC (Model-View-Controller). Згодом з'явилося ще кілька, в результаті сьогодні список основних архітектурних патернів має такий вигляд:

  • MVC (Model-View-Controller);
  • MVP (Model-Passive View-Presenter);
  • MVVM (Model-View-ViewModel);
  • Viper (CleanSwift).

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

View - об'єкти, що відповідають за візуальне уявлення, за те, що користувач бачить. В iOS - це все класи, які мають префікс UI (і їх спадкоємці).

Соntroller - посередник між View i Model. Координує всю роботу: реагує на дії користувача, виконані на view, і оновлює view, використовуючи model.

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

Ios, чистий код, блог

Використовуючи MVC, ми отримуємо такі переваги:

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

Недоліком MVC є те, що з часом, коли проект поступово збільшується і змінюється, Controller розростається і в деяких проектах може досягати позначки в 1000 рядків коду і більш, і чим далі, тим більше це ускладнює підтримку проекту: багфіксінг або додавання нового функціоналу. З цієї причини деякі розробники «розшифровують» абревіатуру MVC як «Massive» ViewController :) Поки ми робимо щось одне, ми боїмося зламати щось інше. В результаті, працюючи з таким контролером, розробник не можемо правильно оцінити поставлену задачу, не вкладається в зазначений час, втрачає довіру і репутацію у замовника. Тут можна було б звинувачувати клієнта, тому що:

  • клієнт не хоче розуміти, наскільки важко реалізувати таку велику кількість функціоналу на одному екрані;
  • клієнт не розуміє, що не можна постійно змінювати вимоги в ТЗ;
  • клієнту багаторазово намагалися пояснити, що спочатку треба зосередитися на UX, а не на UI-дизайні;
  • якби клієнт на старті проекту вказав на цей функціонал, то це зайняло б значно менше часу ...
  • ваш варіант :)

Але все це не скасовує того, що ситуація раз по раз буде повторюватися.

Як можна «розвантажити» ViewController?

Ios, чистий код, блог

MVP-патерн «еволюціонував» з MVC і складається з таких трьох компонентів:

  • Presenter (незалежний посередник UIKit);
  • Passive View (UIView і / або UIViewController);
  • Model.

Цей патерн визначає View як отримує UI-події від користувача і тоді викликає відповідний Presenter, якщо це потрібно. Presenter же відповідає за оновлення View з новими даними, отриманими з моделі.

Переваги: ​​краще розділення коду, добре тестується.

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

Цей патерн зручний в проектах, де використовуються такі фреймворки, як ReactiveCocoa i RxSwift, в яких є концепція «зв'язування даних» - зв'язування даних з візуальними елементами в двосторонньому порядку. В цьому випадку, використання патерну MVC є дуже незручним, оскільки прив'язка даних до подання (View) - це порушення принципів MVC.

Ios, чистий код, блог

View (ViewController) і Model мають «посередника» - View Model. View Model - це незалежне від UIKit уявлення View. View Model викликає зміни в Model і самостійно оновлюється з уже оновленим Model, і, так як зв'язування відбувається через View, то View оновлюється теж.

Недоліком є ​​те, що «замість 1000 рядків в ViewController може вийти тисячі рядків в ViewModel». Також одна з проблем використання фреймворків для «реактивного програмування» - досить просто все поламати і може піти дуже багато часу на багфіксінг. Комусь може здатися, що RxSwift, наприклад, спрощує написання коду, але досить заглянути в стек викликів одного «rx-» методу, щоб оцінити це «спрощення». Можна сюди ж додати проблеми з документацією і постійні проблеми з автокомплітом в xCode.

Viper (CleanSwift)

Ios, чистий код, блог

Interaptor містить бізнес-логіку, пов'язану з даними (Entities).

Presenter містить бізнес-логіку, пов'язану з UI (але UIKit-незалежну), викликає методи в Interaptor.

Entity - прості об'єкти даних, вони не є шаром доступу до даних, так як це відповідальність Interaptor.

Router несе відповідальність за переходи між VIPER-модулями.

Навіть при такому поверхневому огляді очевидно, що краще поділ обов'язків виходить за рахунок великої кількості класів з невеликою кількістю обов'язків.

Схожі статті