- PVSM.RU - https://www.pvsm.ru -

Перевод Becoming a better front-end developer using fundamentals instead of heuristics [1]
Наш опыт показывает, что не имеющие технического образования разработчики и самоучки чаще полагаются не на теоретические принципы, а на эвристические методы.
Эвристика — шаблоны и проверенные правила, которые разработчик вынес из практики. Они могут работать неидеально или ограниченно, но в достаточной мере, и не требуют серьёзных размышлений. Вот некоторые примеры эвристики:
$(document).ready(function(){}) для инициализации кода на jQuery-сайтах»var self = this необходима для вызова метода в функции обратного вызова»return»
В то же время, теоретический принцип может быть использован для поиска решений других проблем. Он неизменно верен и часто определяет само устройство работы того или иного элемента. К теоретическим принципам относятся, например:
Обратите внимание: мы заключили в кавычки только примеры эвристики — для того, чтобы подчеркнуть кустарный характер эвристики по сравнению со строгостью теоретических основ. Ни один из примеров эвристики не является универсальным для всех случаев, но они работают в достаточном количестве ситуаций, чтобы применяющие их разработчики получали рабочий код без полного понимания его работы.
Мы часто сталкивались с тем, что не имеющие технического образования разработчики не склонны решать проблемы с помощью теоретических принципов. Как правило, это объясняется тем, что в начале карьеры у них не было возможности их выучить, и, поскольку эвристические методы работают удовлетворительно, они продолжают ими пользоваться.
Однако, несмотря на кажущуюся сложность, выучить теорию может быть очень полезно. Зачем? Затем, что теория позволит вам чувствовать уверенность в том, что ваше решение работает, а также самостоятельно выводить ответы на новые вопросы, не имея потребности искать чужие решения. В краткосрочной перспективе эвристические алгоритмы могут казаться простым и быстрым решением, но часто будут приводить к неидеальным решениям — если вообще приводить.
К тому же, полагаясь на эвристические методы, вы никогда не научитесь решать проблемы по-настоящему. Возможно, достаточно часто вам удастся находить рабочее решение, но рано или поздно вы зайдете в тупик, выхода из которого не увидите. На эвристику в своей работе полагаются C&P-программисты.
Проводя собеседование с frontend-разработчиками, мы ставим перед ними задачу по программированию и говорю, что они вольны использовать любые источники, будь то Google или Stack Overflow. Таким образом можно легко определить, является ли разработчик адептом эвристики или теории.
Первые без всякого исключения копируют код из более-менее подходящих примеров со Stack Overflow. Лишь когда код заработает не так, как планировалось, они начнут подстраивать его под себя. Часто им это не удается.
Вторые же склонны искать ответы в API-документации. Там они находят информацию о том, сколько каких параметров принимает та или иная функция, или конкретный синтаксис развернутой формы нужного CSS-свойства.
Уже в первые пять минут собеседования можно точно определить, к какому типу программистов относится кандидат.
Возьмем для примера разработчика Билла. Он прошел несколько обучающих курсов, решил некоторое количество задач на JavaScript и в свободное время писал сайты, но «по-настоящему» JavaScript не изучал.
Однажды Биллу попадается объект наподобие этого:
const usersById = {
"5": { "id": "5", "name": "Adam", "registered": true },
"27": { "id": "27", "name": "Bobby", "registered": true },
"32": { "id": "32", "name": "Clarence", "registered": false },
"39": { "id": "39", "name": "Danielle", "registered": true },
"42": { "id": "42", "name": "Ekaterina": "registered": false }
}
Такой объект может отображать список пользователей и то, зарегистрировались ли они на определенное мероприятие.
Допустим, Биллу нужно извлечь список зарегистрированных пользователей. Иными словами, отфильтровать их. Ему попадался код, в котором метод .filter() использовался для фильтрации списка. Поэтому он пробует что-то вроде:
const attendees = usersById.filter(user => user.registered);
И вот что он получает:
TypeError: usersById.filter is not a function
«Какая-то бессмыслица», — думает Билл, ведь он видел код, в котором .filter() срабатывал в качестве фильтра.
Проблема в том, что Билл положился на эвристический метод. Он не понимает, что filter — метод, определяемый на массивах, тогда как usersById — обычный объект, не имеющий метода filter.
Сбитый с толку Билл гуглит «javascript фильтр». Он находит множество упоминаний массивов и понимает, что ему нужно превратить usersById в массив. Затем по запросу «javascript превратить объект в массив» он находит на Stack Overflow примеры с использованием Object.keys(). После этого он пробует:
const attendees = Object.keys(usersById).filter(user => user.registered);
На этот раз ошибка не выводится, но, к удивлению Билла, поле attendees остается пустым.
Дело в том, что Object.keys() возвращает ключи объекта, но не его значения. По сути, наименование переменной user легко вводит в заблуждение, поскольку это не объект user, а идентификатор, то есть строка. Так как атрибут registered для строк не определен, filter расценивает каждую запись как ложную, и массив выходит пустым.
Билл присматривается к ответам на Stack Overflow поближе и вносит следующее изменение:
const attendees = Object.keys(usersById).filter(id => usersById[id].registered);
На этот раз результат лучше: ["5", "27", "39"]. Но Билл хотел получить объекты посетителей, а не их ID.
Чтобы понять, как отфильтровать посетителей, раздраженный Билл ищет «javascript фильтр объектов», изучает результаты поиска по Stack Overflow и находит этот ответ [5] со следующим кодом:
Object.filter = (obj, predicate) =>
Object.keys(obj)
.filter( key => predicate(obj[key]) )
.reduce( (res, key) => (res[key] = obj[key], res), {} );
Билл копирует эти строки и пробует:
const attendees = Object.filter(usersById, user => user.registered);
Всё работает — хотя и непонятно, почему. Билл не понимает, для чего нужен reduce и как он используется. Более того, Билл не понимает, что всего лишь определил для глобального объекта Object новый нестандартный метод.
Но Биллу всё равно — работает ведь! Последствия его пока не интересуют.
Билл попробовал эвристический метод решения проблемы и столкнулся со следующими проблемами:
.filter() на переменной, Билл получил TypeError. Он не понимал, что filter не определяется на обычных объектах.
Object.keys(), чтобы «превратить объект в массив», но само по себе это результата не принесло. Ему нужно было создать массив значений объекта.Это искусственный пример, но мы много раз сталкивались с разработчиками, решающими проблемы в той же манере. Чтобы решать их эффективно, нужно отойти от эвристических методов и изучить теорию.
Если бы Билл был сторонником теоретического подхода, то процесс выглядел бы так:
Object.keys(). Я хочу получить массив потому, что массивы поддерживают перебор».map — очевидный метод создания нового массива путём трансформирования значений другого массива:
Object.keys(usersById).map(id => usersById[id])
Object.keys(usersById).map(id => usersById[id]).filter(user => user.registered)
Пойди Билл этим путем, он мог бы работать у нас.
Иногда они просто с ней не знакомы. Чаще всего они слишком заняты и не могут найти время, чтобы изучить этот способ решения проблем — им просто нужно, чтобы всё работало. Они рискуют превратить этот подход в привычку, которая станет препятствием для развития их навыков.
Чтобы избежать подобных ошибок, всегда начинайте с теории. На каждой стадии процесса задумывайтесь, с какими именно данными вы имеете дело. Вместо того, чтобы всё время полагаться на знакомые шаблоны, учитывайте примитивные типы данных: массив, объект, строка и т.д. При использовании функции или метода обращайтесь к документации, чтобы точно знать, какие типы данных их поддерживают, какие они принимают аргументы и какой получается результат.
С таким подходом вы сможете находить рабочее решение с первой попытки. Вы можете быть уверены в его правильности, ведь вы специально подбирали свои действия, основываясь на заданных входных и желаемых выходных данных. Вникайте в основы каждой операции (типы данных и возвращаемые значения), а не размытые бизнес-формулировки (вроде «зарегистрированных пользователей»).
Автор: NIX_Solutions
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka/322750
Ссылки в тексте:
[1] Becoming a better front-end developer using fundamentals instead of heuristics: https://medium.com/rubyapps-insights/becoming-a-better-front-end-developer-using-fundamentals-instead-of-heuristics-3ff7e405dab8
[2] Официальный синтаксис стрелочных функций: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Syntax
[3] API-документация к Lodash: https://lodash.com/docs
[4] Правила применения и функции vertical-align: https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
[5] этот ответ: https://stackoverflow.com/questions/5072136/javascript-filter-for-objects/37616104#37616104
[6] Источник: https://habr.com/ru/post/458642/?utm_source=habrahabr&utm_medium=rss&utm_campaign=458642
Нажмите здесь для печати.