8 пасток програмування

  
 
Ця стаття містить ті пастки програмування, в які я потрапляв сам, продовжую потрапляти і можливо ніколи не припиню, а також ті, в яких я знаходив своїх товаришів.
 
Однак я вірю в те, що їх можна уникнути, якщо знати в які пастки можна потрапити і як з них вибиратися. Можливо ця віра — чергова пастка.
 
 Короткий вступ
Уявіть, що ви потрапили в яму. Нехай вона буде глибиною 3 метри. Ви почнете з неї вибиратися, дертися, чіплятися, не знаю, що ви там ще придумаєте, але швидше за все ви виберетеся.
 
У програмуванні ви також можете потрапити в пастку. Але якщо ми візьмемо яму як аналогію, то глибиною вона буде метрів 50, а зверху прикрита важкої сталевою пластиною.
 
Як думаєте, довго ви пробудете в такій ямі?
 
Швидше за все до тих пір, поки вас хто-небудь там не знайде!
 
Але це не така вже велика проблема, з кожної пастки програмування можна вибратися самотужки й майже без сторонніх зусиль — потрібно всього-знати три речі: в якій ви пастці, як ви туди потрапили і де "потайні двері" — вихід.
 
Є одна дивна річ у пастках програмування — майже кожна пастка це прихильність однієї з двох протилежних крайнощів, а вибратися з пастки — значить вміло балансувати між ними.
 
Можна сказати, що уникнення пасток — це ходьба вузькій доріжці, де ліворуч — проблеми, а праворуч — шляхи їх вирішення, доведені до абсурду.
 
Гаразд, все-одно, введення ніхто не читає, так-що поїхали!
 
 
Пастка № 1: Оптимізація
 
 
Як і писав Кнут, передчасна оптимізація — корінь всіх зол. Багато хто знає це правило, деякі йому не слідують, деякі зводять його в абсолют, але мало хто знає, що запізніла оптимізація ще гірше!
 
 

Надто велика увага оптимізації

Часто цим грішить такий тип програмістів як "олімпіадників". Знання ефективних алгоритмів або внутрішнього устрою процесора змушує їх думати, що код повинен бути максимально ефективний.
 
На практиці на оптимізацію витрачається занадто багато часу, код стає абсолютно непідтримуваним, розширюваним та нестійким до помилок.
 
 
Ознаки того, що ви в пастці
• Спроба відразу писати швидкий / невимогливий до ресурсів код
• Бажання вичавити з коду все, на шкоду іншим показникам
• Віра в те, що O (n) замість O (n ^ {2}) або заміна всіх операцій множення на 2 на побітовий зрушення зроблять з програми цукерочку
 
 

Занадто маленьке увагу оптимізації

Один з ще незакінчених моїх проектів добігає кінця. Намагаючись уникнути помилки передчасної оптимізації, оптимізація була забута до закінчення — перенесена на останню (передостанню якщо вже зовсім бути чесним) стадію.
 
Зараз, коли готові вже більше половини я зрозумів — намагаючись уникнути однієї пастки я потрапив у протилежний!
 
Тепер для того, щоб поліпшити продуктивність до прийнятного рівня, потрібно не просто прогнати пару раз профайлер і виправити пару ізольованих у функції алгоритмів, потрібно переписати як мінімум третину вже написаного коду!
 
Ця пастка називається — запізніла оптимізація, якщо ви не передбачаєте можливість оптимізації заздалегідь, будьте готові до того, що значну частину вашого красивого і зрозумілого коду доведеться викинути!
 
 
Ознаки того, що ви в пастці
• Щира віра в те, що будь-яка оптимізація — передчасна
• Відкладання оптимізації на заключну частину проекту
• Відмова передбачити деякі невеликі архітектурні рішення для майбутньої оптимізації
 
 

Вихід

• Не намагайтеся оптимізувати код відразу — створюйте можливості для майбутньої оптимізації
• Не відкладайте оптимізацію без причини
• Правило 20/80: витрачайте свій час на ті 20% коду, що дадуть 80% результату (так, використовуйте профілювальник)
 
 
Пастка № 2: Абстракція
 
 
Абстракція в програмуванні мабуть сама хороша штука. Спочатку були двійкові коди, потім мнемоніки команд процесора, потім імперативне програмування — стан та операції (затвердження), далі структурний, процедурне, модульне, об'єктно-орієнтоване, функціональне програмування.
 
Уявіть собі, що вам все-ще потрібно використовувати goto, щоб організувати цикл.
 
Уявіть собі, що вам все-ще потрібно плодити однакові функції, що відрізняються лише типом даних (замість використання переваг динамічної типізації і шаблонів / генериків).
 
Уявіть собі, що ви не можете просто так взяти і змінити розмір колекції — потрібно виділити нову ділянку пам'яті, скопіювати туди стару колекцію, додати новий елемент, звільнити не використовується пам'ять.
 
 

Зайва складність

Знову почнемо з пастки, де спроба абстрагувати все на світі доводиться до абсурду.
 
Нагромадити 20 класів, використовувати 12 різних патернів, реалізувати свій DSL для парсинга іншого DSL, створити багатоплатформовий фреймворк для візуалізації циклічних графів для створення чергового тетрису — це про "поборників абстракції".
 
 
Ознаки того, що ви в пастці
• Написання універсального фреймворка перед реалізацією основної функціональності, причому використовуватися буде від сили 30% написаного коду
• Віра в те, що з будь-якої проблеми кращий вихід — використовувати будь патерн
• Написання максимально узагальненої, приймаючої все на світі і видає коректні результати для будь-яких вхідних значень функції, замість спеціалізованої, навіть якщо її функціонал ніколи не буде використаний
 
 

Спрощення до нескінченності

Ознаки "поборників абстракції" частіше зустрічаються у більш досвідчених програмістів. Ігнорування абстракцій — у новачків. Кращі знову балансують десь між цими крайнощами.
 
Новачки часто ще не знають, що за абстракції є в програмуванні взагалі і у використовуваному ними мовою зокрема. Через це вони часто пишуть невиразний код — такий, який можна було б переписати, використовуючи вбудовані мовні засоби або сторонні бібліотеки / фреймворки зробивши його коротше, зрозуміліше і, найчастіше, ефективніше.
 
 
Ознаки того, що ви в пастці
Для цього пункту досить складно підібрати загальні ознаки — все залежить від мови, завдання і купи інших факторів, але все-ж:
 
• Ігнорування абстракцій, які могли б об'єктивно поліпшити код (наприклад ітераторів в C + +, монад в HaskellЯ маю на увазі відмова від написання своєї монади, там де це має сенс, генераторів в Python, інтерфейсів в Java і т.д.)
• При переході на нову мову програмування — відмова від вивчення його абстракцій, з причини того, що і без них жилося непогано (знову-ж приклад — при переході з C на C + + — відмова від вивчення ітераторів, при переході з імератівного мови на Haskell — відмова від вивчення монад)
• Віра в те, що ті можливості мови, які ви не використовуєте насправді зайві (не стосується програмістів на C + +; жарт звичайно, але як відомо в кожному жарті ...)
 
 

Вихід

• Не використовуйте абстракції заради абстракцій
• Використовуйте відомі / доступні вам абстракції там де їм місце і не використовуйте їх там, де їм місця немає
• Вивчіть абстракції, які надає ваш мова програмування
• Перед реалізацією якої-небудь функціональності, подумайте — чи справді вона вам потрібна (принцип YAGNI)
• Де можливо без особливих втрат обійтися без абстракцій — обходитесь без них (принцип KISS)
 
 
Пастка № 3: Перфекціонізм
 
 
Мабуть найпопулярніша пастка серед розробників, занадто багато знають, щоб просто брати і писати код. На цю тему зовсім недавно вийшла чудова невелика стаття на Хабре, можете знайти посилання на неї в кінці статті.
 
 

Прагнення до досконалості

По цій темі все було розжовано і до мене, однак я хочу бути послідовним, тому також розберу по-кісточках і цю пастку.
 
 
Ознаки того, що ви в пастці
• Віра в те, що головне в коді — краса, читаність і поддерживаема
• Безперервний рефакторінг і переписування навіть прийнятного коду
• Пошук недоліків в будь-якому коді
• Віра в те, що можливо написати ідеальний код за розумний час
• Підвищена увага до дрібниць
• Спроби досягти максимально можливого результату
• Тривале обдумування архітектури навіть найпростіших частин проекту
 
 

Шлях хаосу

З попереднього списку видно, що перфекціонізм — небезпечна пастка, може відмовитися від нього зовсім?
 
Можливо повне повне ігнорування чистоти коду, відмова від рефакторинга і відключення критичного мислення та будуть краще абсолютного перфекціонізму (все-таки поганий результат — це результат, а абсолютний перфекціоніст тільки викидає написаний код), але як і з рештою пастками, тут важливий баланс.
 
Тому повна відмова від свого прагнення до досконалості зажене вас в повністю протилежну пастку.
 
 
Ознаки того, що ви в пастці
• Віра в те, що читаність і розширюваність коду не важлива
• Відсутність критичного мислення, особливо по відношенню до свого коду
• вдовольниться навіть мінімально прийнятним результатом, або неприйнятним зовсім
• Повна відмова від рефакторинга
• Відмова від обдумування складних частин архітектури
• Неприйняття можливість переписати проект або його частина з нуля
 
 

Вихід

Як завжди десь посередині:
 
• Прийміть, що важлива і краса коду і досягнення результату, часом другий навіть важливіше
• Вважайте, що переписування з нуля — крайній захід, але змиріться з тим, що це може бути необхідно
• Виділіть собі максимальний час, який ви можете витрачати на рефакторінг. Це може бути 20, 50, навіть 80% від усього робочого часу, головне — ніколи його не перевищуйте, щоб не застрягти
• Коли ви виявляєте недолік — подумайте, чи настільки він сильний, щоб витрачати час на його виправлення
• Використовуйте правило 20/80 — намагайтеся в першу чергу робити ті 20% роботи, які принесуть 80% результату
 
Сподіваюся ці поради допоможуть вибратися з пастки перфекціонізму хабровчанам. Всі вони були зрозумілі на гіркому досвіді боротьби з цією недугою і буквально вистраждані за весь той час, що я займаюся програмуванням.
 
 
Пастка № 4: Технології та інструменти
 image
 
Програмування не стоїть на місці і зараз у вашому розпорядженні тисяча і один інструмент і бібліотека, які якщо й не зроблять за вас всю роботу, то вже точно полегшать її.
 
Однак іноді вони використовуються або занадто часто, або занадто рідко. Почнемо знову-ж з першого випадку.
 
 

Лень

Звичайно використання вже створених бібліотек, фреймворків та інструментів — всього-лише розумне прояв ліні, але іноді навіть з благими намірами це заходить занадто далеко.
 
Підключення одночасно boost, Qt і активне використання STL при написанні Hello World — не найкраща ідея, але іноді схожі речі трапляються і це — чергова пастка.
 
 
Ознаки того, що ви в пастці
• Підключення бібліотеки на 30 + мегабайт, заради Вихора Мерсена
• Віра в те, що все, що потрібно вже було написано
• Неприйняття того, що велосипед може виявитися краще
• Неможливість написати і строчки коду без автодоповнення в IDE
• Активне використання інструментів, без розуміння принципів їх работиНапрімер часте використання інструментів для візуального редагування GUI (начебто Qt Creator, CodeGear Rad Studio, MS Visual Studio) і, при цьому, відмова від спроби розібратися в їх пристрої
 
 

Трудоголізм

Чи означає це, що я закликаю всіх відмовлятися від використання всіх інструментів і бібліотек, закликаю писати голий код зі своїми велосипедами в nano (або ще гірше — на папірусі)?
 
Аж ніяк. Навпаки, як ви побачите, повне ігнорування нашого програмістського спадкування — ще гірший порок. І напевно сама небезпечна пастка для програмістів.
 
 
Ознаки того, що ви в пастці
• Регулярне написання все нових і нових велосипедів, без вагомих причин для цього
• Віра в те, що можливостей мови і стандартної бібліотеки повинно вистачати для всього
• Віра в те, що автодоповнення (не як в Sublime Text, а як в IDE) — для склеротиків
• Написання своєї билиотека, нехай і монструозної, але навіть не наближається за функціональністю до існуючих аналогам
• Заяви про те, що отладчики і профіліровщики потрібні тим, хто не розуміє як працює власний код
 
 

Вихід

• Познайомтеся з доступними вам інструментами, але не намагайтеся застосовувати їх де попало
• Ретельно зважте всі за і проти, перед тим як вибирати між використанням сторонньої бібліотеки і написанням велосипеда
• Намагайтеся покращити свою продуктивність використовуючи сучасні інструменти, в теж час не завісьте від них
• Прийміть те, що в навчальних / тестових проектах можна робити винятки з цих правил
 
 
Пастка № 5: Золотий молоток
 
 
Ще один пункт в нашому хіт-параді пасток — золотий молоток.
 
Золотий молоток — це шкідлива звичка. Після того, як який-небудь метод спрацював при вирішенні кількох завдань, ліпший в пастку починає використовувати цей метод скрізь, де тільки можна!
 
Є кілька схожих термінів — панацея, чарівна таблетка, срібна куля, тобто такий метод, який завжди, в 100% випадків виконує будь-яке завдання. Ще одна має до цієї теми приказка — забивати цвяхи мікроскопом.
 
Золотий молоток — досить часто зустрічається, але абсолютно несхожа на інші пастка. Золотим молотком може бути все що завгодно, хтось може закохатися в ООП і писати класи на кожен чих, хтось у патерни проектування і побудувати програму з одних лише фабрик і Сінглтон.
 
Для когось золотий молоток — це улюблений мова програмування, для когось — улюблена парадигма, для когось — методологія розробки.
 
Головне, що виділяє золотий молоток — спроба використовувати його завжди і скрізь.
 
 
Ознаки того, що ви в пастці
• Використання однієї мови програмування для всіх завдань
• Віра в те, що одна парадигма може вирішити всі проблеми програмування (найчастіше так говорять про ООП і ФП)
• Використання для всіх проектів, незалежно від умов однієї методології розробки, наприклад бездумне використання TDD у всіх проектах
• Застосування будь-якого кошти, що надається мовою для більшої частини завдань, наприклад:
 - Передача всіх аргументів тільки по константної посиланням
 - Використання у всій програмі лише одного типу колекцій, скажімо масивів (векторів)
 - Використання всюди немутабельних об'єктів
 - Використання в схожих по синтаксису мовах (наприклад Java і C)
 одного стилю відступів і методу найменування сутностей
 
 

Срібної кулі не існує

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

Вихід

• Якщо ви знаєте лише одну мову програмування — вивчіть ще один, або два (можна і більше, але в розумних межах)
• Якщо ви знаєте кілька мов програмування, але у вас є очевидний любимчик, спробуйте частіше використовувати інші мови
• Якщо ви програмували тільки дотримуючись імперативного або об'єктно-орієнтованого програмування, спробуйте функціональне
• Якщо ви постійно використовуєте яку-небудь одну методологію розробки, спробуйте що-небудь нове
• Перед тим як приймати рішення за інерцією (і застосовувати свій золотий молоток) — подумайте про можливі альтернативні рішення
 
 
Пастка № 6: Кросплатформеність
 
 
Кросплатформені додатки — ті, що запускаються на декількох ОС та / або на декількох платформах.
 
І тут знову є дві крайності — деякі розробники намагаються написати додаток так, щоб воно працювало на всіх можливих ОС і однаково добре підходило і для ПК і для планшета і для смартфона.
 
 

Для всіх і кожного

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

Існує тільки Win32

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

Вихід

• Обережно визначте цільові ОС / платформи
• Будьте готові до того, що для деяких ОС / платформ доведеться змінити частину коду або навіть написати окрему версію з нуля
• не прив'язуйте код до одній платформі спеціально
• Намагайтеся охопити кілька платформ, якщо це ускладнить розробку
 
 
Пастка № 7: Захист
 
 
(Без) захисне програмування — ще одна чудова пастка, в якій ви можливо побачите себе (насоящее або минулого).
 
 

Беззахисне програмування

Беззахисне програмування — протилежність практики захисного програмування, це віра в те, що функції завжди будуть передані правильні аргументи, що побічних ефектів не існує, або вони не вплинуть на роботу коду, що покажчик ніколи не буде дорівнює null і тому подібні штуки.
 
Іноді це добре, це робить код вільним від безлічі перевірок, проте налагодження такого коду — суще пекло. Саме тому це пастка.
 
 
Ознаки того, що ви в пастці
• безстрашних перед переповненням, діленням на нуль і помилками округлення
• Віра в абсолютну непогрішність стандартних і бібліотечних функцій / класів
• Віра в те, що користувач не допустить помилку при введенні
• Віра в те, що пам'ять ніколи не закінчиться
• Віра в те, що всі необхідні додатком файли конфігурації існують і до них завжди є доступ
 
 

Захисне програмування

Мільйони тестів для завідомо працюючих частин додатка, 15 ASSERT'ов всередині кожної функції, власна бібліотека винятків, логування, спроби впустити додаток при найменших відхиленнях.
 
Це зворотна сторона медалі — пастка захисного програмування.
 
 
Ознаки того, що ви в пастці
• Кожна функція в проекті починається з пачки АССЕРТ або збудження винятків
• Тестами покривається абсолютно весь код, включаючи сторонні бібліотеки
• У проекті є власний клас MyProjectException і складна ієрархія як мінімум 10 його спадкоємців, зміст яких зводиться до повідомлення про невірних аргументах функції
• Запис в лог більшої частини всього того, що відбувається з додатком
• Навіть невеликі відхилення для вас неприйнятні і повинні упускати додаток з повідомленням про помилку і автоматичної відправки баг-репорт з повним дампом пам'яті
 
 

Вихід

• Ретельно обмірковуйте що варто перевіряти, а що ні
• Особлива увага при перевірках приділяйте користувача введення і зовнішніх ресурсів
• По-можливості намагайтеся використовувати стандартні класи виключень
• Не намагайтеся перевірити всі
• Відокремлюйте критичні помилки від незначетельних, дозвольте додатком працювати далі, якщо нічого особливо страшного не сталося
• Записуйте в лог тільки найважливіші дані, реалізуйте ненав'язливу можливість відправити баг-репорт
 
 
Пастка № 8: Відкладання на потім
 
 
Пастка досить цікава, тому-що знайти в цьому питанні баланс дуже складно.
 
Суть пастки в тому, що часто реалізуючи яку-небудь функціональність, ми ставимо позначки — TODO, HACK, і деякі інші.
 
Реалізація цих завдань самому собі відкладається, про TODOшкі рідко хто згадує і вони довгий час так і залишаються недоробленими.
 
 
Ознаки того, що ви в пастці
• Безліч позначок TODO і HACK в проекті і їх кількість не зменшується
• Code Review не приносить ніяких результатів, крім розстановки нових TODO і WTF
• Неможливість ненадовго відволіктися від виконуваного завдання, щоб реалізувати побічно-пов'язану з нею (замість залишення TODO) або виправити виявлену помилку (замість залишення FIX або HACK)
 
 

Багатозадачні програмісти

Існують програмісти, які не можуть перемкнутися в процесі реалізації якої частини проекту на іншу, нехай навіть безпосередньо з нею пов'язану (скажімо написати клас винятку і викинути його, замість залишення позначки "TODO: check argument to null").
 
І навпаки, існують програмісти, які це вміють, я називаю таких багатозадачними програмістами, але от біда — реальної багатозадачності немає і насправді вони просто швидко переключаються з одного завдання на інше.
 
У цього є свій плюс — TODO і HACK в коді не ставляться а відразу правляться, знайдені помилки в іншому коді — усуваються.
 
І як зазвичай, безкоштовно це не дається, як підсумок через занадто частого перемикання програміст може забути про первісної задачі або не встигнути її доробити, а коли повернеться до неї знову — не згадати у якому напрямку рухався.
 
Якщо вам подобається швидко і часто перемикатися між різними частинами проекту, у мене для вас погані новини.
 
 
Ознаки того, що ви в пастці
• Ви не залишаєте жодного TODO на потім, щоб сконцентруватися на задачі
• Ви перемикаєтеся так часто, що почавши реалізовувати один функціонал, реалізуєте замість нього дві абсолютно незв'язані фичи
• Коли ви програмуєте в парі, партнер не може устежити за ходом ваших думок
 
 

Вихід

• Перед тим як відкласти завдання і поставити TODO подумайте, може реалізувати її можна швидко
• Не бійтеся відволікатися від основного завдання, але не робіть це занадто часто і на довго
• Оглядаючи код, виправляйте знайдені помилки відразу
• Відкладайте незв'язаний з поточним завданням великий функціонал — залишайте TODO
• Програмуючи в парі, уникайте перемикань взагалі, відкладайте всі сторонні завдання
 
 
Посилання
 
AlenaC + +: Кому насправді належить цитата про передчасну оптимізації
Wordpresse: Захисне програмування
 
Habrahabr: Запізніла оптимізація
Habrahabr: 5 стадій некомпетентності програміста
Habrahabr: Ці незліченні парадигми, концепції, інструменти та фреймворки
Habrahabr: Параліч аналізу: ви знаєте занадто багато, щоб просто писати код
Habrahabr: Три ключових принципу ПО, які ви повинні розуміти
Habrahabr: Кросплатформеність — це круто
Habrahabr: Апаратна кроссплатформенность: чи є вихід?
Habrahabr: Захисне програмування
 
Wikipedia: KISS
Wikipedia: YAGNY
Wikipedia: DRY
Wikipedia: Перфекціонізм
Wikipedia: Золотий молоток
Wikipedia: Прокрастинація
 
 Замість висновку
Всім удачі в ходьбі по канату!
  
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.