Будь кращою версією себе, або Як стати гарним розробником

Усім привіт! Мене звуть Євгеній. Я розробник зі стажем у багатьох сферах. Дуже люблю ділитися своїм досвідом, щоб робити цей світ кращим :)

У світі розробки є споконвічна проблема. Її описують одним словом, що викликає завжди неприємні емоції як у розробника, так і в усіх, хто причетний до цього, — «гавнокод». Зазвичай після цього кажуть: «Я б тут усе переписав». Звісно, чути це теж малоприємно, але в деяких випадках таке рішення раціональне, бо розвивати такий код неможливо, а підтримка займає чимало часу.

Причин цієї проблеми мільйон. Хто як хоче, так і виправдовує себе.

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

Розробник вирішує проблеми

Найбільша проблема поганого коду в тому, що розробники фокусуються на коді, не зрозумівши суть проблеми. Запам’ятайте: гарний розробник не «пише код» — він «вирішує проблему». У сучасному світі вже вирішено чимало проблем, і вашу проблему, ймовірно, також. Тому краще пошукати готове рішення, ніж витратити купу часу на винайдення велосипеда.

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

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

Спочатку продукт, потім код

Щоб писати код, треба спочатку зрозуміти бізнес, його потреби й можливі напрями розвитку. Краще поставити 10 додаткових запитань замовникові, щоб глибше зрозуміти продукт, ніж потім 10 разів переписувати код, бо щось було не до кінця зрозуміло. Адже щоразу, коли ви переписуєте код, у вас лишається дедалі менше часу, і ви приречені писати неякісний код.

Починайте писати код тільки тоді, коли повністю зрозуміли продукт.

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

Абстракція, а не конкретика

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

У DDD є такий прекрасний термін як «єдина мова» (ubiquitous language). Використовуйте єдину мову, щоб налагодити ефективну комунікацію з бізнесом і сформувати поняття, якими ви будете оперувати.

Не забувайте про інтерфейси й навіщо їх придумали.

Наприклад, коли ви спілкуєтеся про фігури (Circle, Square, Triangle), що повинні малюватися й стиратися на якійсь поверхні, то вам не треба обговорювати деталі, як кожна фігура малюватиметься і скільки фігур буде в системі. Ви абстрагувалися від цього інтерфейсом Shape й оперуєте терміном Shape, що спрощує розуміння системи на певному рівні.

Не дозволяйте, щоб конкретна реалізація впливала на вашу бізнес-логіку. Ви пишете код, щоб вирішити проблему бізнесу, — не допускайте моментів, коли бізнес повинен підлаштовуватися під ваші реалізації. З прикладу вище видно, що під час додавання нової фігури, це ніяк не вплине на бізнес, бо нова фігура ПОВИННА відповідати правилам бізнесу, а конкретно інтерфейсу Shape, і ніяк інакше. Додавання фігури не повинно змінювати погляди на сформоване розуміння поняття Shape.

Будуйте свою систему так, щоб у вас не було явних залежностей на реалізації. Якщо взяти для прикладу випадок з фігурами, описаний вище, то тут мається на увазі, що якби у вас не було абстракції Shape, то ви б напряму зав’язувались на кожну фігуру Circle/ Square/ тощо, що дуже сильно ускладнило б вам систему, оскільки з’явилися б додаткові перевірки на тип фігури. Усе, що можна абстрагувати — абстрагуйте. Якщо щось може жити окремо — винесіть це взагалі в окремий сервіс, який буде виконувати необхідні запити. Цим самим ви максимально ізолюєте реалізацію і не будете взагалі про неї думати в рамках цього контексту.

DRY і принцип єдиної відповідальності

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

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

Таких самих принципів дотримуйтеся й у даних. Унікальність даних завжди має якийсь сенс, і про це можна говорити оперуючи поняттями. Якщо ж дані не унікальні, то це сміття, яке важко описати, а тим паче працювати з ним. Якщо говорити про базу даних, то не допускайте, щоб ваші таблиці могли зберігати дублікати — визначайте правила унікальності даних і ставте перевірки на унікальність. Це дасть змогу, по-перше, зменшити обсяг даних, що зберігаються, а по-друге, знати, що у вас у системі або є такий запис, або його немає, що спрощує розуміння в роботі з такими даними (зокрема ніяких дублікатів і можливих неправильних зв’язків з ними).

Описуйте в коді реальний світ

Багато причин непорозуміння в коді викликає неправильний опис речей, а саме не такий, як у реальності. Наприклад, вам сказали: «Ми — компанія, що буде займатись домашніми тваринами. Нам потрібен сервіс для роботи з тваринами». Ви трохи проанізували і зрозуміли, що є такі домашні тварини як Собака та Кіт, побачили, що у них по чотири лапи, хвіст, голова, майже все ж схоже, що потрібно для потреб бізнесу, і вирішили, що краще оперувати поняттям «Тварина», почали зберігати тип тварини в об’єкті і всі інші дані.

Що тут поганого?

Те, що в світі не існує Тварини. Існують Кіт, Собака тощо. Такий опис ускладнює читаємість, розуміння та майбутнє масштабування коду. Усе, чого не існує в реальному світі, це абстракція, і повинно залишатись абстракцією в коді. Усе, що існує — конкретика, і повинно бути чітко описане в коді як унікальна одиниця.

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

Розділяйте поняття по контекстам

Багато складнощів в коді починається з невизначення чітких понять, коли розробник уже почав писати код. Усе те, що ви бачите і чим оперуєте в житті, повинно бути в коді. Наприклад, у вас є поняття Company (компанія) та User (користувач) і вам потрібно описати, що компанія може мати багато членів. На перший погляд може здатись, що зв’язавши Company з User, це і буде швидко (класно/ефективно/тощо), але в цьому якраз і вся проблема, через яку ви в майбутньому будете багато рефакторити.

Потрібно проаналізувати, чи справді User — це член компанії? Якщо відповідь не однозначна, то, швидше за все, існує поняття CompanyMember (Член компанії), яке вводиться для того, щоб абстрагуватись від поняття User у цьому контексті. У свою ж чергу CompanyMember може мати набагато більше інформації, ніж звичайний User, але нам неважливо вже буде, хто такий User і що він має, бо в нас з’явилося поняття CompanyMember. У заданому контексті воно повністю описує всю бізнес-логіку.

Найменування змінних, методів, класів, дітей :)

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

Жесть якасьНабагато простіше для розуміння
class Data
{
   public function getData(): array
   {
       $v1 = $this->getValues1();
       $v2 = $this->getValues2();
       $res = $this->doProcessing($v1, $v2);

       return $res;
   }

   /**
    * Returns children names
    */
   private function getValues1(): array
   {
       return ['John', 'Alice'];
   }

   /**
    * Returns children ages
    */
   private function getValues2(): array
   {
       return [13, 18];
   }

   /**
    * Merge children names and ages
    */
   private function doProcessing(array $a, array $b): array
   {
       $res = [];

       foreach ($a as $key => $item) {
           $res[] = [
               $item => $b[$key]
           ];
       }

       return $res;
   }
}
class ChildrenDataProvider
{
   public function get(): array
   {
       $childrenNames = $this->getChildrenNames();
       $childrenAges = $this->getChildrenAges();
       $mergedChildrenData = $this->mergeChildrenData($childrenNames, $childrenAges);

       return $mergedChildrenData;
   }

   private function getChildrenNames(): array
   {
       return ['John', 'Alice'];
   }

   private function getChildrenAges(): array
   {
       return [13, 18];
   }

   private function mergeChildrenData(array $names, array $ages): array
   {
       foreach ($names as $key => $name) {
           $mergedData[] = [
               $name => $ages[$key]
           ];
       }

       return $mergedData ?? [];
   }
}
new (Data())->getData();
new (ChildrenDataProvider())->get();

У прикладі вище показано, як можна писати код без коментарів, не втрачаючи його легкочитності як усередині класу, так і під час виклику його зовні.

Коли вам треба придумати ім’я змінної, уявіть, що вибираєте ім’я своїй дитині. Навряд чи ви хотіли б назвати дитину на кшталт «s1» (Сергій, перший син). Можливо, вам здається, що все зрозуміло, але поверніться до такого коду за тиждень або місяць. А уявіть, що людина щойно прийшла в проєкт — для неї такі шифри взагалі будуть незрозумілі. І вгадайте, куди ця людина найперше дивитиметься: так, усе правильно — у git :), щоб дізнатися, хто таке написав. Думайте.

Розвивайте технічну базу

Поганий той солдат, що не мріє стати генералом. Бути гарним розробником — це постійно вчитися й удосконалюватися. Є різні підходи, як можна знаходити час на вивчення чогось нового. Один з моїх улюблених:

«Якщо ви думаєте, що зробили все заплановане на сьогодні, то зробіть ще одну якусь річ».

Насправді нашому розвитку заважають тільки лінощі, і дуже важливо вміти побороти свої лінощі різними способами. Коли робитимете щось не зважаючи на лінощі, то відразу побачите, що й сили у вас є, і бажання. Просто розпочніть, і все вдасться. 50% успіху це почати щось робити.

Швидкість написання коду

Є чимало речей, що впливають на ефективність роботи розробника. Сумно, але багато розробників не використовують усі переваги IDE-шок, у яких працюють (плагіни, автогенератори, шаблони тощо), не запам’ятовують комбінації клавіш, не вчаться сліпого методу набору на клавіатурі.

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

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

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

Технічний борг

Кожен з нас опинявся в ситуації, коли треба відрефакторити N класів або методів. Тоді ми собі говоримо: «Немає часу це робити». Дуже часто проблема не в браку часу, а в лінощах. Так, знову лінощі. Спробуйте наступного разу, коли говоритимете собі таке, просто виділити 10–15 додаткових хвилин, але зробити це. Ви побачите, що часу не так багато це зайняло, але ви уникнули технічного боргу.

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

Гарний розробник — добре відпочилий розробник

Відпочинок — дуже важлива річ для написання гарного коду. Щоб мозок працював на повну, він повинен відпочивати. Навіть під час роботи намагайтеся перемикатися на різні речі. Уміння вчасно перемкнутися (піти прогулятися, попити води, почитати статтю тощо) може значно скоротити час розробки. Так ви освіжаєте мозок, даючи йому змогу подивитися на проблему з іншого ракурсу, а це дуже часто допомагає знайти ефективніший і простіший розв’язок поставленого завдання.

Любіть те, що ви робите

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

Наостанок

«Пишіть код так, ніби з ним працюватиме серійний маніяк, що знає, де ви живете!»

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

Я пишаюся кожним написаним мною кодом, кожною архітектурою, кожним осмисленим рішенням! А ви?

Похожие статьи:
Компания ASUS представила новые игровые аксессуары линейки Cerberus - клавиатуру и компьютерную мышь. По словам производителя, новые решения...
Попри санкції США генеральний директор американської платформи Patreon Джек Конте вирішив продовжити роботу компанії в росії,...
Айтівці з невеликим досвідом роботи — найбільш вразливі до коливання ринку вакансій після початку війни рф проти...
Зараз в українських ІТ-компаніях працюють орієнтовно 280-300 тисяч спеціалістів, кожен з яких створює п’ять...
В выпуске: аппаратное ускорение, работа с CoordinatorLayout, самокомпилирующееся приложение, audio latency,...
Яндекс.Метрика