Advertisement
  1. Code
  2. Tools & Tips

Всі 20 найпоширеніших «підводних каменів» для розробників-початківців

by
Read Time:15 minsLanguages:

Ukrainian (українська мова) translation by AlexBioJS (you can also view the original English article)

Незалежно від нашого поточного рівня майстерності ми всі колись були новачками. Здійснення класичних помилок новачка є невід'ємним етапом при становленні програміста. Сьогодні ми попрохали авторів штату Nettuts+ поділитися їх переліком підводних каменів, що зустрічаються у різних мовах програмування.

Вчіться на наших помилках; не повторюйте їх!


Поради з JavaScript

1. Непотрібні маніпуляції з DOM

Модель DOM (* Document Object Model – об'єктна модель документа) працює повільно. Завдяки обмеженню взаємодії з нею продуктивність вашого коду значно підвищиться. Погляньте на нижченаведений (невдалий) код:

У цьому коді, власне, DOM модифікується 100 разів та створюється 100 зайвих об'єктів jQuery. 100! Більш правильно було би або скористатися фрагментом документа (* інтерфейс DocumentFragment являє собою мінімальний об'єкт документа, у якого нема батька. Використовується для зберігання сегмента структури документа, що складається з вузлів. Оскільки він не є частиною деревоподібної структури активного документа, то зміни, внесені во фрагмент, не впливають на документ) або зібрати рядок зі 100 елементів <li/> та потім додати цей HTML-код до елемента, в якому він повинен знаходитися. При цьому підході ви взаємодієте з DOM тільки раз. Нижче наведено приклад:

Як було згадано вище, при цьому ми взаємодіємо з DOM тільки раз, що добре, проте для створення великого рядка використовується конкатенація рядків (* операція послідовного об'єднання двох або більшої кількості елементів даних в один, наприклад, кількох рядків символів в один рядок, кількох текстових файлів у один файл. Наприклад, конкатенація рядків "ABC" і "DE" дасть рядок "ABCDE"). Є інший підхід до вирішення цієї проблеми – за допомогою масивів.

При створенні великих рядків зберігання кожного кусочка рядку в якості елемента масиву та виклик join(), напевно, є елегантнішим рішенням, ніж конкатенація рядків. Це один з найшвидших та найпростіших способів об'єднання HTML-елементів у коді JavaScript без використання бібліотеки шаблонів або фреймворка.

2. Непослідовність при найменуванні змінних та функцій у JavaScript

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

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

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

При найменуванні функції, яка додає 5 до заданого числа, слід дотримуватися того ж шаблону, який продемонстровано нижче:

Іноді ви могли би найменувати функцію на основі значення, яке вона повертає. Наприклад, ви могли би найменувати функцію, що повертає рядок з кодом HTML, getTweetHTML(). Також ми могли би додати на початку імені функції do, якщо функція просто виконує якусь дію та не повертає ніякого значення, наприклад doFetchTweets().

При найменуванні конструкторів (* в ООП – спеціальний метод, який забезпечує ініціалізацію об'єкта; у JavaScript конструктором стає будь-яка функція, викликана через new) звичайно дотримуються принципу найменування класів в інших мовах, набираючи перший символ у верхньому регістрі.

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

3. Використання hasOwnProperty() у циклах for...in

Масиви JavaScript не є асоціативними; спроби використання їх у цій ролі не схвалюються товариством. З об'єктами, з іншого боку, можна поводитися як з геш-таблицями (* таблиця, для роботи з якою використовують геш-кодування. У ранніх СКБД широко застосовували для створення індексних файлів; структура даних, що реалізує інтерфейс асоціативного масиву, а саме, вона дозволяє зберігати пари (ключ, значення) та виконувати три операції: операцію додавання нової пари, операцію пошуку та операцію видалення пари за ключем), і ви можете здійснювати ітерацію над властивостями об'єкта за допомогою циклу for...in наступним чином:

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

Ви можете вирішити її завдяки використанню методу hasOwnProperty(). Нижче наведено приклад:

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

4. Порівняння булевих значень

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

Зверніть увагу на умову foo == true. Порівняння foo та true зайве, оскільки foo вже є логічним значенням (або значенням «істина» / «неправда»). Замість порівняння foo просто використовуйте його в якості умови як показано нижче:

Для перевірки, чи виступає в якості значення умови «неправда» використовуйте логічний оператор NOT як показано нижче:

5. Оброблення подій

Подія – складне питання у JavaScript. Минув час, коли розробники використовували вбудовані обробники подій onclick (за винятком деяких рідких випадків реалізації початкової сторінки веб-сайту (* зазвичай містить логотип, інформацію про версії, авторські й/або ліцензійні права)). Замість цього використовуйте спливання (* коли події «спливають» від внутрішнього елемента угору через батьків) та занурення подій (* навпаки).

Давайте уявимо, що у нас є контейнер із зображеннями, при натисненні по яким повинно запускатися модальне вікно (* блокує взаємодію користувача з додатком, що ініціює діалог; дочірнє вікно для взаємодії користувача із застосуванням: воно служить для отримання інформації від додатка або для вводу запитуваних даних та вибору опцій; тому модальне вікно часто називають діалоговим (dialog box , modal dialog). Якщо відкривається модальне вікно, то повернення керування застосуванню може відбутися тільки після реакції користувача). нижче показано те, чого вам не варто робити. Зверніть увагу: ми використовуємо у цьому прикладі jQuery, припускаючи, що ви також використовуєте подібну бібліотеку. Якщо ні, то знайте, що той самий принцип спливання справедливий і для нативного JavaScript.

Відповідний код HTML:

Невдалий код JavaScript:

Згідно з цим кодом перед викликом модульного вікна відбувається передача якірного елемента, що є посиланням на повнорозмірне зображення. Замість того щоб прив'язувати обробник події до кожного якірного елементу, додавайте його до елементу з ідентифікатором #grid-container.

У цьому коді і this, і event.target посилаються на якірний елемент. Ви можете використовувати цей самий підхід до будь-якого батьківського елемента. Тільки впевніться, що вказали цільовий елемент (* елемент, на якому відбулася подія).

6. Уникайте надмірного використання тернарних виразів

Надмірне використання тернарних виразів доволі поширено при використанні JavaScript та PHP.

Умовний вираз завжди повертає значення true або false, так що вам нема потреби явно додавати true/false в якості значень тернарного виразу. Замість цього ви могли би просто повернути умовний вираз:


Поради з PHP

7. Використовуйте тернарні вирази, коли це доречно

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

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

Цей код чіткий, лаконічний та виконує те, що вам потрібно.

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

8. Викидайте винятки замість вкладень у стилі фільму «Початок»

(* виняток – незвичайна, непередбачена або помилкова ситуація, яка може виникнути при виконанні програми та змінити її нормальне функціонування); («Початок» (фільм, 2010) («Inception») – науково-фантастичний трилер Крістофера Нолана). Давайте поглянемо правді у вічі: якщо ви використовуєте безліч рівнів вкладення, то ваш код виглядає жахливо та його важко підтримувати. Наступний код – відносно спрощений приклад, проте ситуація погіршується з часом:

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

Можливо, у вас залишиться та сама кількість рядків, проте при цьому підході у вас виходить код, який значно легше читати та підтримувати. Також ви уникаєте тих важких сеансів налагодження, викликаних тим, що ви забули додати можливу гілку для оператора if. Пишіть код простіше!

Погляд третьої, незацікавленого сторони: будьте дуже обережні при використанні винятків для керування виконанням програми (* визначає, які оператори програми виконуються; термін стосується операторів циклів та if- then, for, switch, що іменуються flow-of-control statements (оператори потоку керування)). За додатковою інформацією звертайтеся сюди.

9. Методи, в яких у випадку помилки повертається false

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

Розробники Ruby або Python звикли відстежувати незначні винятки. Хоча це здається стомлюючим, це, на справді, того варте. Якщо щось не так, то викидається виняток і ви одразу ж дізнаєтеся, у чому полягає проблема.

У PHP – особливо при використанні фреймворків на зразок CodeIgniter – у вас виходить те, що я називаю кодом, в якому при виникненні помилок повертається значення false (на противагу тому, коли у цих випадках викидається виняток). Замість викидання вам винятку у такому коді просто повертається значення false, та рядок з помилкою присвоюється якійсь іншій властивості. У результаті вам потрібно достати її з класу за допомогою методу get_error().

Користь від отримання винятку у випадку виникнення помилки значно більше, ніж від отримання значення false. При виникненні у вашому коді помилки (наприклад «не вийшло підключитися до S3 (* Amazon Simple Storage Service (Amazon S3) – онлайнова веб-служба, що пропонується Amazon Web Services та надає можливість для зберігання та отримання об'єму даних, так званий файловий хостинг) для вивантаження зображення» або «значення відсутнє») викидається виняток. Ви також можете викидати спеціальні типи винятків за допомогою класів, отриманих у результаті розширення класу Exception, наступним чином:

Завдяки викиданню користувальницького винятку налагодження програми значно полегшується.

10. Використовуйте Guard Clauses

(* Guard Clauses – запобіжні вирази; при цьому ви виконуєте команду повернення на тому самому рядку, зберігаючи той самий відступ для подальшого коду). Звичайно використовують оператор if для контролю виконуваної гілки функції або методу. Так і хочеться перевірити умову та виконати велику кількість коду у випадку, якщо результатом перевірки умови є true, і просто виконати команду повернення у виразі з оператором else. Наприклад:

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

Чи не легший він для читання?  Ця незначна зміна значно покращує читабельність вашого коду.

11. Використовуйте цикл while для простих ітерацій

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

Є поважні причини для використання циклу for, проте цикл while може бути вдалішим варіантом, якщо вам всього-на-всього потрібно щось простеньке на зразок цього:

Не завжди він підходить для кожного випадку, проте це один із альтернативних варіантів.

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

Це, безумовно, одна з найчастіших помилок, здійснюваних новачками.

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

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

Ось бачите – чіткіший код, який легше налагоджувати!

13. Уникайте багаторівневих вкладень

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

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

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

Коли ви виявили, що використовуєте вкладені оператори if, ретельно перегляньте свій код; можливо, ваш метод виконує більше однієї дії. Нижче наведено приклад:

У цих випадках оформіть вкладені методи у вигляді окремих методів:

14. Уникайте використання магічних чисел та рядків

Магічні числа та рядки – згубні для вашого коду. Визначте змінні та константи зі значеннями, які ви хочете використовувати у вашому коді.

Замість наступного

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

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

15. Використовуйте вбудовані функції масиву

Використовуйте вбудовані функції масиву замість foreach().

Не найкращий варіант:

Краще:

PHP пропонує різні методи масиву. Спочатку вам буде тяжкувато, але виділіть день та спробуйте розібратися з максимально великою їх кількістю.

16. Не зловживайте змінними

Доволі легко зловжити змінними, проте пам'ятаєте, що змінні зберігаються у пам'яті. Для кожної створеної вами змінної система повинна виділити пам'ять. Погляньте на наступний код:

У змінній $result нема потреби. У наступному коді цю змінну опущено:

Зміна незначна, проте ми змогли покращити цей простий приклад. Ми залишили змінну $query, оскільки вона відноситься до бази даних, тоді як $result мала відношення до логіки нашої програми.


Поради з програмування у цілому

17. Покладайтеся на можливості процесора бази даних

(* процесор бази даних – частина СКБД, що зберігає дані та маніпулює ними згідно з командами, які надходять від застосувань). Якщо у вас є думки зі скорочення коду, то це – чуття коду.

База даних створена для роботи з даними; користуйтеся її інструментами та можливостями для підвищення ефективності вашого додатка.

Наприклад, ви можете уникнути зайвих запитів до бази даних у багатьох випадках. У більшості скриптів для керування записами користувачів, працюючих за принципом «"підключи і працюй» (* принцип і специфікація швидкого підключення до комп'ютера додаткового устаткування і самоконфігурування системи, підтримувані сучасними BIOS, ОС і апаратними засобами. ОС виявляє знову підключений пристрій, опитує його, оцінює висунуті ним вимоги до системи, визначає і виконує оптимальні установки для кожного пристрою), використовується два запити для виконання реєстрації користувачів: один для перевірки, чи існує вже e-mail/username (* адреса електронної пошти/ім'я користувача), та інший для власне додавання його до бази. Набагато вдаліший підхід реалізується завдяки заданню обмежуючої умови UNIQUE для поля, до якого додаються імена користувачів. Потім ви можете скористатися нативними функціями MySQL для перевірки, чи було додано запис до бази даних.

18. Іменуйте ваші змінні належним чином

Минув час, коли ви іменували вашу змінні x, y, z (хіба що, звісно ж, ви працюєте з системою координат). Змінна є важливою частиною логіки вашого додатка. Не хочете набирати довге ім'я? Обзаведіться більш просунутою IDE (* інтерактивне середовище розроблення). Сучасні IDE надають можливість миттєвого автозаповнення (* функціональна можливість, надавана програмним забезпеченням, завдяки якій частини слів або рядків додаються без участі користувача) імен змінних.

Якщо ви постійно програмуєте, то чи впевнені ви, що пригадаєте значення тих змінних $sut через рік? Напевно, ні: іменуйте змінні згідно з їх призначенням. Якщо у вас є думки зі скорочення коду, то це – чуття коду (* найменування тих інстинктивних думок, що виникають у вас при перегляді фрагменту далекого від ідеалу коду).

19. Іменуйте методи згідно з виконуваними ними діями

Помилки трапляються; головне – вчитися на них.

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

Також уникайте використання будь-якої мови за винятком англійської при найменуванні ваших методів. Досадно, коли ви зустрічаєте імена на зразок 做些什麼() або робитищось() у вашому проекті. Інші розробники, напевно, на зрозуміють ваш код. Можливо, це й не легко, але, хай там що, англійська мова – офіційна мова написання коду. Спробуйте використовувати його, якщо працюєте у великій команді.

20. Поради зі структурування коду програми

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

  • Використовуйте відступи шириною у чотири або два пробіли. Відступи більшої величини, наприклад у вісім пробілів, – занадто багато, і через це ваш код буде важко читати.
  • Встановіть допустиму ширину рядку та дотримуйтесь її. Сорок символів у рядку? Ми більше не у 70-х; встановіть в якості границі ширини рядку 120 символів, відмітьте це на екрані та зробіть так, щоб ваша IDE дотримувалася його. При такому ліміті вам надається достатня ширина та нема потреби прокручувати код.

Завершення

«Я ніколи не робив дурну помилку при програмуванні» – Ніхто та ніколи.

Помилки трапляються; головне – вчитися на них. Ми, команда розробників Nettuts+, робили та будемо робити помилки. Ми сподіваємося, що ви навчитесь на наших помилках, завдяки чому зможете їх уникнути у майбутньому. Але, правду кажучи, найкращий спосіб засвоєння усталеної практики – здійснення власних помилок!

Дякую за проявлену зацікавленість!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.