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

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

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

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

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

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

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

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

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

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

Щоб писати код, треба спочатку зрозуміти бізнес, його потреби й можливі напрями розвитку. Краще поставити 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 я можу зрозуміти, що тут треба було зробити. Дуже важливо залишати позначки в коді, щоб вони постійно привертали до себе увагу. Так ви не забуватимете про недороблені речі.

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

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

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

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

Наостанок

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

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

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

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

👍ПодобаєтьсяСподобалось1
До обраногоВ обраному10
LinkedIn

Схожі статті




Найкращі коментарі пропустити

Хех, тот редкий случай, когда я не согласен практически со всеми пунктами (я не беру в учёт «люби свою работу» и другие сантименты).

гарний розробник не «пише код» — він «вирішує проблему»

Don’t be a Programmer?

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

Ну, как бы да, изобретать свой велосипед, скорее всего, не стоит. Но у своего велосипеда есть колоссальный плюс — он свой. Потому что:

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

почти всегда только за деньги. Зачастую — за огромные деньги. Даже если это open source, конкретно твою проблему почти точно никто решать не будет. Решать ее будешь ты сам в форке. И у тебя в любом случае будет форк, потому что тебе нужен хотя бы минимальный контроль над зависимостью. А в случае аматорского open source — «специализированная команда людей» будет состоять из одного азиата, который сейчас болеет коронавирусом, поэтому он не может посмотреть на твою Issue на гитхабе.

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

Охох. Я уже больше года работаю в своей компании, но не берусь утверждать, что понял бизнес хотя бы на 30%. Даже не уверен, что знаком со всем фичами нашего мобильного приложения. Но те «продукты» (так у нас называют фичи) с которыми я работал, я, конечно, понимаю хорошо. В общем, мысль здравая, но радикальная формулировка вызывает снисходительную улыбку.

Оперуйте завжди абстракцією і зводьте все до абстракції. Це дуже важливе правило, якого слід дотримуватися.

Преждевременная абстракция — это из той же серии, что и преждевременная оптимизация. Начинать почти всегда лучше с конкретной реализации и уже при необходимости выводить из неё абстракцию или общее решение.
Как минимум, потому что общие решения не всегда возможны ввиду несовместимости/конфликтности интерфейсов или невозможности выведения/преобразования общих типов (привет, теория категорий). Это может быть совершенно неочевидно, пока не упрёшься в тупик. Если выводить общее из конкретного, то тупиковые ходы проявляются сразу.

Про свой провальный опыт преждевременной абстракции геометрических фигур недавно в блоге написал Dan Abramov . Советую почитать.

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

А это уже совсем дикие постулаты свидетелей ООП (которое даже не столько про объекты, сколько про отправку им сообщений).
Пытаться описывать в коде реальный мир нелепо. Мир устроен совсем не так, как устроены программы и компьютеры. Пожалуй, подавляющее большинство концепций с которыми мы работаем не существуют за пределами компьютера и математик.
Если мне удобнее будет представить собачек и кошечек из твоего примера в виде вершин на биграфе, чтобы решить задачу линейного программирования на паросочетание, при этом сохраняя промежуточные результаты в хэш-таблицу, то я так и сделаю. На реальный мир, правда, это будет совсем не похоже. Возможно в коде даже не будут фигурировать слова Cat и Dog.

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

А я не верю :)
У меня есть одна программка, которую я написал как фрилансер еще в универе больше 10 лет назад для одной украинской компании. Они до сих пор с ней работают. А я боюсь заглядывать в код, потому что там просто адская жесть, а переписывать нет никакой мотивации да и работает же :)

85 коментарів

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.
Я пишаюся кожним написаним мною кодом, кожною архітектурою, кожним осмисленим рішенням! А ви?

А що були і неосмислені рішення? А по суті, якщо ви дійсно пишаєтеся, можете викласти свій код (фрішний) для review?

Прошу прощение ТС, я не имею столько опыта в разработке, но сложилось ощущение, что большая часть статьи

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

.
Общие фразы, которые не подтверждены кодом, увы, никак не помогут.

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

Спору нет, именно поэтому предпочитаю лишний раз глянуть в код ТС, и убедится, что он описывал то, что я себе напредставлял.
Взять к примеру

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

Звучит просто
Более джун скажет — SOLID,
Джун со стажем дополнит: GRASP.
Но так ли просто было внедрить эти практики в свою жизнь, если читать только абстрактно обо всём?

Я даже не знаю, как это расшифровывается)

Но так ли просто было внедрить эти практики в свою жизнь, если читать только абстрактно обо всём?

Це і є відмінність гарного розробника від недостатньо гарного. Гарний розробник давно вже перепробував всі види сексу розробки та не сильно відрізняє, наприклад колбеки від асінк/евейтів.

Не понял, а SOLID где? Всю статью ждал, куда ж без солида??
А если серьёзно, то напрягла первая же фраза «Я розробник зі стажем у багатьох сферах.» — сильное заявление. Проверять я его конечно не буду. ©
По остальным пунктам там ребята уже очень хорошо и подробно разобрали по косточкам.
У меня другой вопрос — а что заставляет людей писать такие статьи?
Думаю всё происходит примерно так: автор коммитит свой код и, смахивая слезу умиления, говорит сам себе — до чего же я ***енный разработчик! Хочу сделать этот мир лучше, и чтобы все разработчики были такими же как я! И принимается писать статью, наполняя её весьма сомнительными утверждениями.
А вечером перед сном в памяти снова всплывают великолепные строки своего кода, да такие, что на них не грех и передернуть, чего уж там. Ничто человеческое гениям не чуждо.

пацталом ))))

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

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

Взаємовиключаючі параграфи детектид:

в світі не існує Тварини. Існують Кіт, Собака тощо.

І вище:

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

Тут іграєм, а тут рибу заварачіваєм...

С точки зрения галерного менеджмента — хороший разработчик это тот который «виден сверху» и не отказывается выполнять любую работу — открывает рот на митингах, развязывает проблемы, предлагает решения. и к способностям программировать это имеет очень малое отношение. все хотят универсального солдата который «умеет все». -а вот поправь там конфиги в деплойменте , а вот у нас QA енв лежит, а тут у нас место на диске закончилось, а тут какая-то прога на пайтоне не запускается ! — но я же фронтендщик, я пайтон первый раз вижу -тыжпрограммист, разберись!

А еще важный фактор — чтобы он не делал это все слишком быстро, а то заказчик спросит, зачем платить пяти синьорам, когда один мид делает работу быстрее их вместе.

поправил одну строчку — зарепортил 2 часа работы :-)

Я как-то эту строчку искал неделю, испортил желудок излишним количеством пуэра, обиделся, и начал увольняться.

Типа браузер юзает старый рендерер хромиума, его депрекейтят, народ не успевает перейти на новый рендерер, и после пары ежемесячных мержей все вообще перестает отрисовываться. А релизиться — нужно. Итого: найти в 10 М строк кода почему перестал работать старый рендерер.

Ну да это класика. См. старый бородатый анекдот о 999 + 1 долларе за работу Уатта.

Гарний програміст той, хто з часом пише все менше коду. Не через лінь.

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

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

В ФП це теж не легше

ФП вообще максимально далеко от описания реального мира. Через призму лямбда-исчислений и теории категорий мир выглядит, мягко говоря, странно. Как эпизод Рика и Морти :).

Мой любимый пример на эту тему: из доклада Gary Bernhardt — Boundaries.
Открывок на 11:45:
Покормить моржа в ФП — это создать новую копию моржа с помощью желудка старого моржа + еда :)

Как поймать льва в клетку?
Метод инверсивной геометрии. Помещаем в заданную точку пустыни клетку, входим в нее и запираем изнутри. Производим инверсию пространства по отношению к клетке. Теперь лев внутри клетки, а мы — снаружи.
Метод проективной геометрии. Без Ограничения общности мы можем рассматривать пустыню Сахара как плоскость. Проектируем плоскость на линию, а линию — в точку, находящуюся внутри клетки. Лев проектируется в ту же точку.
Метод Дирака. Отмечаем, что дикие львы в пустыне Сахара являются величинами ненаблюдаемыми. Следовательно, все наблюдаемые львы в пустыне Сахара — ручные. Поимку ручного льва предоставляем читателю в качестве самостоятельного упражнения.

Больше методов здесь

Ну это страрые приколы )) А вот
ваш ответ я заценил: в десятку!

Гарний програміст той, хто з часом пише все менше коду. Не через лінь.

Для цього достатньо затриматись на новому проекті кілька років)
Що далі, то менше коду пишеться, а більше часу йде на підтримку. І щось нове інтегрувати важко — бо купа старих модулей, котрі можуть з новим бути якось пов’язані.

Легасізація — підтвердження того, що розробники не сильно гарні.

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

Підтримка та розробка — різні речі. Я про розробку нового коду, а не підтримку старого.

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

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

Я тут один бачу суттєвий архітектурний про...кол? Чому воно не було закладено з самого початку?

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

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

Я тут один бачу суттєвий архітектурний про...кол? Чому воно не було закладено з самого початку?

Наприклад, тому, що треба показати замовнику, що команда може щось зробити. І об’єм PoC/MVP не настільки маленький, щоб його викидати.
Або: з’являються нові потреби, не передбачені в початкових умовах. Приклад для модулів — потреба вигружати модулі, що жеруть багато пам’яті й не використовувались останнім часом. До цього — спокійно усі модулі статично лінкувались й завантажувались на старті.
Закласти щось «з самого початку» можливо лише там, де проект «на конвеєрі» — вже раніше таке робили, усе передбачувано. Там, де RnD чи просто в замовника або виконавців експертиза в області менше 90% — передбачити неможливо. Починається craft, not mass production.

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

В ембедеді усе сильнозв’язане. Щоб запустити систему, вона має виконувати мінімальну функціональність. Наприклад, робимо шлюз між IP телефонією та телефонними шнурками. Щоб показати, що воно влазить в залізо, і що залізо робоче, треба, власне, підняти IP телефонію, підняти SLIC (плата, що працює з телефонним шнурком), зробити прокачку голоса між ними, та базову логіку управління. Потім, коли замовник побачив, що все працює — додається що загодно — багато облікових записів, паралельні дзвінки, історія дзвінків та телефонна книга, правила заміни номера, логи. Якщо телефонна книга додається неінвазивно, то, наприклад, логи дзвінків для користувача — це жах, бо в них треба тягнути дані, котрі ніде більше не використовуються — імена телефонів на шнурку, назви облікових записів і ще що завгодно. І формат цих логів буде ще тричі змінюватись. В результаті маленька фіча «логувати дзвінки» розповзається по половині модулів.

В ембедеді усе сильнозв’язане. Щоб запустити систему, вона має виконувати мінімальну функціональність.

Ви трохи плутаєте архітектуру та функціональність... Навіть на C можна писати в OOP стилі, хоча мова не підтримує OOP аж ніяк.

Не знаю, як Ви створите архітектуру, не зав’язану на домен та функціональність.

Не знаю, навіщо прямо зі старту обмежувати себе...

Якщо не обмежувати — отримуєте спагеті. Будь-яка структура є обмеженням. Абсолютна свобода == абсолютна ентропія.

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

«Неструктуровантий код» == спагетті. Ви пропонуєте зі старту «не обмежувати себе». Себто, зі старту писати спагетті.

Структура є обмеженням. Якщо пишеш Actors чи Pipes and Filters — то код з одного потоку не може звертатись до змінних іншого потоку. Це — очевидне обмеженя: правило, що можна робити, а чого — робити не можна.

Якщо я невірно розумію — поясніть.
www.youtube.com/watch?v=vXbCWJNfq_0

«Неструктуровантий код» == спагетті.

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

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

Якщо пишеш Actors чи Pipes and Filters — то код з одного потоку не може звертатись до змінних іншого потоку. Це — очевидне обмеженя: правило, що можна робити, а чого — робити не можна.

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

Заміна парадигми (базового архітектурного патерну) під час розробки неможлива. Вона призведе до потреби переписати більшість коду.

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

Заміна парадигми (базового архітектурного патерну) під час розробки неможлива. Вона призведе до потреби переписати більшість коду.

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

Далі коментувати не буду. Ваші острахи, повторюся, лише в вашій голові. Як й всі ваші обмеження.

Ви не бачите різниці між тим, щоб закласти правильну структуру програми від початку, та тим, щоб змінювати структуру в середині розробки?

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

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

Створення алгоритму в голові розробника — подія реального світу. Ви забули мабуть, що інформація є невід’ємною частиною нашого всесвіту.

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

Не бачу тавтологій. Будь-яке структурування, чи сама структура, є часткою інформаційного світу. Алгоритм — аналогічно. Я не розумію, чому це викликає у вас такі складнощі? Ви намагаєтеся щось довести, але перестрибаєте з одного на інше постійно.

Ви стверджуєте, що програма описує світ, і сама є частиною світу, тому програма, що описує програму, описує світ.

Рівняння х = х вірне, але нафіг нікому не потрібне, бо значення х знайти з нього неможливо.

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

Ви стверджуєте, що програма описує світ, і сама є частиною світу, тому програма, що описує програму, описує світ.

Так. Будь-яка програма є частиною інформаційного світу та описує/реалізує процеси інформаційного світу. Навіть галузь, в якій ви працюєте, називається Інформаційні Технології. Ваша робота — створювати інформацію, а не намагніченість певних ділянок металевих поверхонь або насичення електронами областей матеріалів з напівпровідниковими властивостями. Ви не програмуєте фізичні або хімічні процеси, а інформаційну складову цих процесів. Фізика в іграх описує інформаційну модель без створення реальних фізичних процесів.

За Вашим твердженням, умовна програма {0×86, 0×03, 0xF5} описує світ, бо вона описує умовну програму {0×86, 0×03, 0xF5}

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

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

Я казав, що в об’єктивному світі нема сутностей, котрим би відповідав розподіл ОС на шари (Layers pattern). Ви пишете:

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

Спираючись на Ваше твердження, я пишу, що код

{0×86, 0×03, 0xF5} описує світ, бо вона описує умовну програму {0×86, 0×03, 0xF5}

І, за Вашим твердженням, це сміття існує в реальному світі — і у Вашій голові з того часу, як Ви це читали, і навіть — на серверах ДОУ. А Ви у відповідь кажете, що це не так? Як то?

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

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

Я казав, що в об’єктивному світі нема сутностей, котрим би відповідав розподіл ОС на шари (Layers pattern)

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

І, за Вашим твердженням, це сміття існує в реальному світі — і у Вашій голові з того часу, як Ви це читали, і навіть — на серверах ДОУ.

Це сміття дійсно існує в реальному світі. В інформаційному.

А Ви у відповідь кажете, що це не так?

Я не зрозумів, як ви прийшли до цього висновку?

Це сміття дійсно існує в реальному світі. В інформаційному.

Тоді яка різниця між пошаровою архітектурою ОС та програмою, що друкує сміттия? Обидві моделюють реальний світ?

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

Тоді повернемося назад.
dou.ua/...​ign=reply-comment#1828300

Ви не бачите різниці між тим, щоб закласти правильну структуру програми від початку, та тим, щоб змінювати структуру в середині розробки?

Для мене це не важливі речі. Правильність структури програми — умовна річ. Вона залежить від десятків параметрів, починаючи від поточного рівня програмістів на проекті, їхнього попереднього досвіду, психосексуальних проблем, кольором бороди менеджера та інших тимчасових збочень, закінчуючи наявністю залізних помилок в чіпі DSP та неправильному розведенню доріжок на п’ятому шарі матплати, через що виникають наведення при перевищенні температури порогу в 40 градусів. Тому я не бачу причин обмежувати себе та наражати себе на довічні страждання через ці обмеження.

Ви з багатопоточними програмами працювали? На практиці?

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

Питання до того, що з Ваших слів не видно, щоб Ви на практиці стикалися з синхронізацією потоків. Ті, хто стикалися, не вважають обмеження непотрібними.
Наприклад, розділяють пам’ять, з котрою працюють потоки, або захищають змінні мютексами. Це — обмеження, котрі Ви вважаєте зайвими.

Прочитайте ваше запитання уважно.

Ви з багатопоточними програмами працювали?

Запитання про те, чи працював я з програмами. Не розробляв. Вчіться правильно формулювати запитання.

Дайте відповідь на мої запитання, будь ласка.

На які? Про ОС? Читав LDD та Таненбаума. В компіляторах — здається, генеряться процеси, а не потоки. В CPU потоків нема, але є синхронізація кешів. Ще щось?

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

Інший приклад: код. Якщо весь код в одному файлі — його неможливо читати. Але нема обмежень. Якщо є обмеження — розділяти код по модулях, файли можна читати. Але вже не пишеш як хочеш.

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

Маєте ще питання?
Контраргументи до необхідності обмежень?

Якщо Ви не розробляли багатопоточні програми — то не розумієте необхідність архітектури й обмежень для цього.

Ви не допускаєте думки, що теоретична частина однакова для розробників, які щось на практиці робили, та які просто досліджували варіанти реалізації?

Інший приклад: код. Якщо весь код в одному файлі — його неможливо читати. Але нема обмежень. Якщо є обмеження — розділяти код по модулях, файли можна читати. Але вже не пишеш як хочеш.

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

Ще приклад: Хроміум запускає відкриті сторінки в окремих процесах.

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

В CPU потоків нема, але є синхронізація кешів.

Про яку синхронізацію йде мова?

Ви не допускаєте думки, що теоретична частина однакова для розробників, які щось на практиці робили, та які просто досліджували варіанти реалізації?

Думку допускаю, та спілкування з Вами доводить, що ця думка не є вірною.

А якщо код для читання зливається в один файл? Такої думки ви не допускаєте? А якщо ваш код автоматом розрізається на файли також?

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

А якщо код в файлах написаний таким чином, що він самодостатній та не вимагає розуміння всієї системи в цілому, щоб зрозуміти що він робить та навіщо?

А от для цього існує розділення кодової бази проекта на файли. Що Ви вважаєте за обмеження свободи розробників)

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

Те, що Ви чомусь (через недостачу досвіду?) вважаєте за недолік, більшість спеціалістів вважає перевагою. Якщо можете запропонувати ліпший варіант реалізації — давайте обговоримо.

В CPU потоків нема, але є синхронізація кешів.

Про яку синхронізацію йде мова?

en.wikipedia.org/wiki/Cache_coherence

А от для цього існує розділення кодової бази проекта на файли. Що Ви вважаєте за обмеження свободи розробників)

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

Те, що Ви чомусь (через недостачу досвіду?) вважаєте за недолік, більшість спеціалістів вважає перевагою. Якщо можете запропонувати ліпший варіант реалізації — давайте обговоримо.

В кожного рішення є ціна. Ціна за рішення форкати таби в процеси повністю — надмірне споживання пам’яті.

Навіщо мені пропонувати те, що вже було запропоновано Mozilla? Та реалізовано. Вони пішли іншим шляхом, та порізали функції на ті, що бажано параллелити, та ті, що важко параллелити. Процес рендерінгу гарно параллелиться, процес формування DOM — погано.

В CPU потоків нема, але є синхронізація кешів.

Розробник не контролює цей процес, може тільки інвалідувати щось, але не саму синхронізацію.

Як стати гарним розробником

Помыться.

Новая рубашка.

Новая машина.

Новая страна. Там купить себе новое офисное кресло.

Done.

Хех, тот редкий случай, когда я не согласен практически со всеми пунктами (я не беру в учёт «люби свою работу» и другие сантименты).

гарний розробник не «пише код» — він «вирішує проблему»

Don’t be a Programmer?

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

Ну, как бы да, изобретать свой велосипед, скорее всего, не стоит. Но у своего велосипеда есть колоссальный плюс — он свой. Потому что:

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

почти всегда только за деньги. Зачастую — за огромные деньги. Даже если это open source, конкретно твою проблему почти точно никто решать не будет. Решать ее будешь ты сам в форке. И у тебя в любом случае будет форк, потому что тебе нужен хотя бы минимальный контроль над зависимостью. А в случае аматорского open source — «специализированная команда людей» будет состоять из одного азиата, который сейчас болеет коронавирусом, поэтому он не может посмотреть на твою Issue на гитхабе.

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

Охох. Я уже больше года работаю в своей компании, но не берусь утверждать, что понял бизнес хотя бы на 30%. Даже не уверен, что знаком со всем фичами нашего мобильного приложения. Но те «продукты» (так у нас называют фичи) с которыми я работал, я, конечно, понимаю хорошо. В общем, мысль здравая, но радикальная формулировка вызывает снисходительную улыбку.

Оперуйте завжди абстракцією і зводьте все до абстракції. Це дуже важливе правило, якого слід дотримуватися.

Преждевременная абстракция — это из той же серии, что и преждевременная оптимизация. Начинать почти всегда лучше с конкретной реализации и уже при необходимости выводить из неё абстракцию или общее решение.
Как минимум, потому что общие решения не всегда возможны ввиду несовместимости/конфликтности интерфейсов или невозможности выведения/преобразования общих типов (привет, теория категорий). Это может быть совершенно неочевидно, пока не упрёшься в тупик. Если выводить общее из конкретного, то тупиковые ходы проявляются сразу.

Про свой провальный опыт преждевременной абстракции геометрических фигур недавно в блоге написал Dan Abramov . Советую почитать.

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

А это уже совсем дикие постулаты свидетелей ООП (которое даже не столько про объекты, сколько про отправку им сообщений).
Пытаться описывать в коде реальный мир нелепо. Мир устроен совсем не так, как устроены программы и компьютеры. Пожалуй, подавляющее большинство концепций с которыми мы работаем не существуют за пределами компьютера и математик.
Если мне удобнее будет представить собачек и кошечек из твоего примера в виде вершин на биграфе, чтобы решить задачу линейного программирования на паросочетание, при этом сохраняя промежуточные результаты в хэш-таблицу, то я так и сделаю. На реальный мир, правда, это будет совсем не похоже. Возможно в коде даже не будут фигурировать слова Cat и Dog.

Браво!

Особенно жирный плюс к аргументам про велосипеды. Чужие готовые решения могут не подходить по множеству разных причин.
— Их уже никто не поддерживает.
— Поддерживают, но хреново.
— Нельзя затащить библиотеку из-за её лицензии.
— Неоправданно тащить библиотеку, потому что она тянет за собой кучу ненужных зависимостей.
— Чужое решение слишком неэффективное.
— ...

Поэтому бояться изобретения велосипедов не стоит — нужно просто понимать, когда это оправдано, а когда нет.

нужно просто понимать, когда это оправдано, а когда нет

 А фиг. Сдалешь быстро простой велосипед — прийдет заказчик и скажет «хочу рюшечки». И еще раз потом прийдет и еще скажет. И по результату — проще было тянуть готовый чужой, чем свой трни раза переписывать.

Тоже, значит, история. Надо необычный регексп для телефонии tools.ietf.org/...​tml/rfc3435#section-2.1.5 в роутер. Зависимости тянуть не хочется, и давно было желание попробовать динамическое программирование. Сел, подумал, заимплементил. Соседи, правда, сделали за 2 дня через scanf, а у меня ушло 2 недели. Зато с поддержкой рекурсии и защитой от malicious regexp. А тут типа «круто, а давайте еще туда же оператор для замены номера». И еще пара недель разработки, и до месяца выгребания багов.

Если бы знал, чем обернется — замапил бы синтаксис на обычную либу для регекспов. Зато натренировался с динамическим программированием и синтаксическими деревьями по самое нехочу.

Сдалешь быстро простой велосипед — прийдет заказчик и скажет «хочу рюшечки». И еще раз потом прийдет и еще скажет. И по результату — проще было тянуть готовый чужой, чем свой трни раза переписывать.

Так я озвучу ему эстим, сколько будет стоить доклепать эти рюшечки, и сколько в сравнении с этим будет стоить затянуть чужое решение, какие плюсы и минусы у каждого варианта. И тогда мы вместе будем решать, по какому варианту идти.

Хотя изначально я говорил о более «технических» велосипедах, не видимых заказчику, но с которыми регулярно работают девелоперы. Например, кастомная реализация какого-то шаблона, аналог которого (казалось бы!) уже есть в стандартной библиотеке или бусте. Вспомнилось, как я затащил в наш проект быстрый велосипедный SCOPE_EXIT, написанный по мотивам лекции Александреску (простая лямбда в деструкторе), вместо громоздкого BOOST_SCOPE_EXIT_ALL, который там до сих пор не могут реализовать оптимально (под капотом — аналог std::function, компилящийся в тормозное месиво при любых оптимизациях).

Тут проблема, что каждый инкремент своего велосипеда вроде и не сильно страшный, но если просуммировать количество инкрементов — то лучше было втянуть готовую либу.
А сколько их будет — никто вначале не знает — зависит, насколько фича понравится заказчику и пользователям.

Задумывался об этом, скажу так, лучший код тот, который не написан. Можно сколь угодно абстрагироваться дабы блюсти принцип единой отвественности, но тогда получаешь тонну зависимостей .

Як стати гарним розробником

Сделать причёску, похудеть, купить новую одежду...

Хотелось бы «больше статьи». Не просто «не оставляйте технически долг», а если оставляете, то запилите TODO или FIXME. А почему не стоит оставлять технический долг? Пример, когда это существенно вылезет боком и т.п.
Кроме DRY еще можно рассмотреть и случаи, когда копи-паст оправдан. А то начинаются 28уровневые абстракции для избежания копи-паста одной функции )). А потом, когда один из объектов не требует эту функцию — костыли. Это из личного опыта ))) Иногда копи-паст функции (по сути, повторение себя, которое противоречит Don’t Repeat Yourself) лучше сделать, чем городить непонятно что.
На счет развития, то вообще отдельная тема. «Сделайте что-то еще» так себе совет. Минимум, нужно понимать свои пробелы и там работать. У кого-то это может быть БД, у кого-то вопросы по работе сетей, кто-то ограничился 4мя паттернами и т.п. А кому-то полезно кроме «молотка» познакомится еще с другими инструментами. Ибо «если у тебя в руках молоток, всё вокруг начинает казаться гвоздями». И потом все задачи начинают решаться только с помощью узкого круга знакомых инструментов (к примеру, логи с меткой времени в реляционку + костыли по ротации, а можно было вполне юзануть TSDB. ПыСы.: просто пример). Но в то же время с акцентом, что зоопарк технологий не стоит разводить.

Майже кожен пункт не витримує перевірки практикою.
Є об’єктивні причини на те, щоб проекти з часом перетворювались на www.laputan.org/mud

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

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

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

1) Про Agile забули? Замовник сам не розуміє детально, що він хоче. І не може передбачити, що захочуть покупці чи маркетинг після першого релізу. Тим більше, він не зможе це все Вам розказати.
2) Існують великі системи. Навіть якщо не казати про якесь управління підприємством. Навіть не операційні системи. Той же Хроміум (+Блінк) зі своїми 10 мільйонами рядків коду. Проекти такого розміру ніхто один не роузміє в деталях.
В результаті, розробка йде ітеративно згори донизу — спочатку малюємо щось, а коли це щось якось працює — додаємо деталі. Бо деталі на початку розробки або невідомі, або їх занадто багато, щоб охопити свідомістю.

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

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

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

Кешування даних в контексті потоку чи машини, щоб не робити асинхронні операції або не блокувати поток?

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

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

Ого)) я аж відчув всю біль, з якою Ви стикнулися))
Так, все вірно пишете. Дуже багато кейсів, які не можна підчинити своїй волі чи зрозуміти цілком.
Я розумію, що «замовник сам незнає, що він хоче», і це проблема, але таке майже в більшості кейсів відбувається. Для цього потрібно аналізувати продукт, бути на стороні замовника, і намагатись показати можливості продукту. Якщо просто слухати що хоче клієнт і намагатись якось це перевести в код, то так ніколи це не буде працювати. Має бути діалог заради єдиної цілі.
Я не прихильник галер, де підалять код по таскам, мені важливо розуміти продукт і я вважаю що це поввині робити всі розробники, а не топ менеджмент, який сформував бачення, а в результаті воно неправильне, через що всі розробники страждають.
В даній статті я намагався пояснити «як ТИ, як особистість, можеш стати кращим розробником», а не розглядати кейси великого ентерпрайзу де все закручено що хоч бери і вішайся)
Якщо розробник сформує правильні погляди і намагатиметься їх притримуватись, а ще краще, якщо він буде їх передавати далі іншим людям, то це вже успіх.
Якщо навіть в проекті є погано написаний код, з яким ви постійно пересікаєтесь, то, маючи вже розуміння «що таке поганий код», спробуйте змінити це.
Можливо ніколи не буде ідеального коду в вашому проекті, але кожне така зміна поганого коду буде додавати вам +1, +5, +15 хвилин вільного часу коли ви будете з ним працювати.
Рефакторинги ніхто не відміняв, і не потрібно забувати про їх важливість для системи.

Вибачте за оффтоп.
«Біль» в українській мові все-таки «хлопчик», на відміну від російської «болі».
Ну і рефакторинги-таки ніхто не скасовував, бо провідміняти їх можна наступним чином:
Н: рефакторинги
Р: рефакторингів
Д: рефакторингам
З: рефакторинги
О: рефакторингами
М: на рефакторингах
Кл: рефакторинги!

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

нафіга?
мова має жити, й правила пристосовуватись під живу мову.
ви ж хочете її загратувати мертвими правилами

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

Очень интересно будет почитать ваши правки к статье после того как вы ознакомитесь с KISS методами.

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

А я не верю :)
У меня есть одна программка, которую я написал как фрилансер еще в универе больше 10 лет назад для одной украинской компании. Они до сих пор с ней работают. А я боюсь заглядывать в код, потому что там просто адская жесть, а переписывать нет никакой мотивации да и работает же :)

Ахах)) так, є таке) Я теж боюсь заглядувати в код, який писав 10 років тому) Але ж суть не в цьому) Суть в тому, щоб намагатись бути кращим зараз, і тоді ці старання будуть помітні через 10 років. Я не можу сказати що 10 років тому я мав такі погляди. Проте, як вони в мене зявились — з того часу я вже інший, і я спираюсь конкретно на цю свідомість)
Ми не можемо стати відразу супер стар кодєрами, і ми не можемо змінити все написане, бо цього навіть і не потрібно робити. Проте ми можемо вже зараз робити по максимуму для того, щоб потім це не виколювало очі)))

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

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

В одному з проектів в яких працював раніше залишив свої контакти LI та FB в README.md, а їх потім затерли

Git не затреш ;) бо це було б дуже не розумно з їхньої сторони)

твои контакты и так есть в git log без readme

У Git-а є можливість видалити будь-який файл разом з історією про нього а також перезаписати автора на іншого

Підписатись на коментарі