7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Tools & Tips

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

Scroll to top
Read Time: 17 mins

Russian (Pусский) 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 (за исключением некоторых редких случаев реализации начальной страницы веб-сайта (* обычно содержит логотип, информацию о версии, об авторских и/или лицензионных правах)). Вместо этого используйте всплытие (* когда события «всплывают» от внутреннего элемента вверх через родителей) и погружение событий (* наоборот).

Давайте представим, что у вас имеется контейнер с изображениями, при нажатии по которым должно запускаться модальное окно (* блокирует взаимодействие пользователя с приложением, инициирующим диалог; в графическом интерфейсе пользователя (GUI) - дочернее окно (child window) для взаимодействия пользователя с приложением: оно служит для получения информации от приложения или для ввода запрашиваемых данных и выбора опций; поэтому модальное окно часто называется диалоговым. Если открывается модальное окно, то возврат управления приложению может произойти только после реакции пользователя. B Windows могут открываться только модальные окна, относящиеся к одному и тому же приложению; модальное окно). Ниже показано то, чего вам не следует делать. Обратите внимание: мы используем в этом примере 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. Полагайтесь на возможности процессора базы данных

(* процессор базы данных – часть СУБД, которая на физическом уровне сохраняет данные и манипулирует ими в соответствии с командами, поступающими от приложений). Если у вас имеются мысли по сокращению кода, то это – чутье кода (* наименование тех инстинктивных мыслей, которые возникают у вас при просмотре кусочка далекого от идеала кода).

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

Например, вы можете избежать избыточных запросов к базе данных во многих случаях. В большинстве скриптов для управления записями пользователей, работающих по принципу "подключи и работай" (* принцип автоматического распознавания и конфигурирования подключённых устройств, реализуемый в компьютерах и отдельных их компонентах и широко поддерживаемый ОС Windows), используются два запроса для выполнения регистрации пользователей: один для проверки, существует ли уже e-mail/username (* адрес электронной  почты/имя пользователя), и другой для собственно добавления его в базу. Намного более удачный подход реализуется за счет задания ограничивающего условия UNIQUE для поля, в которое  добавляются имена пользователей. Затем вы можете воспользоваться нативными функциями MySQL для проверки, была ли запись добавлена в базу данных.

18. Именуйте ваши переменные надлежащим образом

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

Если вы постоянно программируете, то  уверены ли вы, что вспомните назначение тех переменных $sut через год? Вероятно, нет: именуйте переменные в соответствии с их назначением. Если у вас имеются мысли по сокращению кода, то это – чутье кода (* наименование тех инстинктивных мыслей, которые возникают у вас при просмотре кусочка далекого от идеала кода).

19. Именуйте методы в соответствии с выполняемыми ими действиями

Ошибки случаются; главное – учиться на них.

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

Также избегайте использования какого-либо языка за исключением английского при наименовании ваших методов. Досадно, когда вы встречаете имена вроде 做些什麼() или делатьчтото() в вашем проекте. Другие разработчики, вероятно, не поймут ваш код. Возможно это и не легко, но, как бы там ни было, английский – официальный язык для написания кода. Постарайтесь использовать его, если работаете в большой команде.

20. Советы по структурированию кода программы

Наконец, структура кода так же важна для читабельности и удобства сопровождения, как и все остальное, о чем мы говорили в этом руководстве. Вот вам две рекомендации:

  • Используйте отступы шириной в четыре или два пробела. Отступы большей величины, например в восемь пробелов, – слишком много, и из-за этого ваш код будет трудно читать.
  • Установите приемлемую ширина строки и придерживайтесь ее. Сорок символов в строке? Мы больше не в 70-х; установите в качестве предела ширины строки 120 символов, отметьте это на экране и сделайте так, чтобы ваша IDE придерживалась его. При таком лимите вам предоставляется достаточная ширина и нет необходимости прокручивать код.

Заключение

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

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

Спасибо за проявленный интерес!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
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.