Умение разбираться в коде Чужих или как правильно делать рефакторинг
Программный код существует для того, чтобы его выполняла некая программа. Этой программе совершенно неважно то, как вы пишете код, главное, чтобы код был написан без ошибок. Если вы разделяете это мнение, то вы обладатель одного из самых распространенных заблуждений о программировании. Попробую пояснить.
Как вы считаете, что объединяет все программы в мире, что у них есть общего? Если отбросить такие очевидные вещи, что они написаны людьми на каком-либо языке программирования и состоят из символов, используемых в этом языке, то останется еще одно важное свойство. Что, кроме языка, отличает текст программы от текста книги? Да, книга нужна для того, чтобы ее читать, а не выполнять, но есть еще одно важное отличие. Любая программа, чтобы продолжать существование, вынуждена изменяться! И касается это абсолютно всего, начиная с модных мобильных приложений и вплоть до корневых компонентов операционных систем. Можно сказать, что код, создаваемый программистом, как бы адресован другим программистам (или самому себе в будущем). Вы думаете я что-то помню о коде проектов над которыми работал пять лет назад? Да я ничего не помню даже о том, что писал полгода назад!
Реализация программы должна быть проста и понятна не только вам в момент написания, но и каждому, кто впервые с ней встретится
Этой статьи не хватило бы, чтобы раскрыть полностью такую сложную тему, как рефакторинг или архитектура кода. Про это написано много интересных книг. Я же попробую обозначить направление, в котором можно двигаться, чтобы сделать лучше свой код или код, доставшийся от других разработчиков.
Часть 1: Именование
“Мир был таким первозданным, что многие вещи не имели названия и на них просто тыкали пальцем”.
— Габриель Гарсия Маркес
Однажды мой коллега-программист рассказал историю, которая весьма меня позабавила. Речь шла о том, что в некоторых компаниях с очень высоким уровнем безопасности от разработчиков скрывается смысл бизнес-логики, которую они реализуют. Разработчики не должны понимать, что делает их программа. Точнее, они должны этого НЕ понимать. Но как можно написать программу, не понимая, что она делает? Для того, чтобы это осуществить, нанимают специальных аналитиков, уровень доступа безопасности у которых выше, чем у штатных программистов. Эти аналитики все-таки могут понимать, о чем будет программа, но сами они не программируют. У них есть специальные таблички, в которых хранятся соответствия реальных имен с кодовыми. Они просматривают их и дают задания разработчикам. К примеру: “Напиши функцию func_352, которая должна принимать число DEP20, умножать его на коэффициент CF1850 и записывать результат в базу, в ячейку FIELD255”. А на самом деле функция func_352 принимает сумму вклада, умножает на ежегодный процент и записывает в баланс пользователя, но разработчик, создавая функцию, об этом не знает.
В данном примере все выглядит несложно. Но представьте себе функцию, в которой десятки таких переменных, и программу, в которой их тысячи. Скорость ее разработки будет примерно такой же, как если бы вы захотели написать рассказ на венгерском, общаясь по телефону с другом, имеющим русско-венгерский словарь. Такую же путаницу чувствуют программисты, работающие с чужим кодом, имена в котором были подобраны недостаточно тщательно.
В литературе по программированию вы можете найти много рекомендаций по именованию различных программных объектов. Основная же идея состоит в том, чтобы имена были осмысленными.
Имя функции должно отражать то, что она делает. Имя переменной должно отражать то, что в ней будет храниться
Достаточно легко подобрать имя для такой простой функции, как в примере с расчетом баланса вклада пользователя. Но как быть, если функция делает куда больше операций? Об этом будет следующая часть.
Часть 2: Принцип Разделения Ответственности
“Простое лучше, чем сложное.
Сложное лучше, чем запутанное”.
— Zen of Python
Представьте себе несчастного сотрудника компании, которому сегодня нужно составить акты приема-передачи товаров, сесть за руль автомобиля и доехать до склада. Забрать товар со склада и подписать документы. Приехать в магазин и разложить товар по витринам. Заказать товар у оптового поставщика и произвести его оплату.
Многие живут в подобном графике — ничего плохого тут нет. Но если бизнес расширяется, и у вас уже не один, а десять магазинов, то не будете же вы нанимать десять подобных сотрудников? Куда логичнее нанять одного бухгалтера, одного водителя, а выкладку товара доверить администратору или продавцу.
Что-то подобное происходит и в разработке программы. До тех пор, пока программа небольшая, подобный сценарный стиль кода показывает себя неплохо, ведь на его планирование тратится минимум времени. Но как только программа разрастается, а любая программа растет, то сценарии ее становятся все сложнее и все запутаннее. Возникают вопросы: “А как бы назвать ту функцию из 200 строчек, чтобы название передавало суть? Может назовем ее “функция СДЕЛАТЬ ВСЕ”?
Будет логично разбить эту функцию на более мелкие функции, каждая из которых будет решать конкретную задачу. Да, подобные советы звучат слишком очевидно, но, возможно вы мне не поверите, многие профессионалы-разработчики до сих пор совершают подобные ошибки. В чем причина? Лень перерабатывать свой код? Или здесь как с английским: мы годами учим его правила, но когда должны что-то сказать, все знания забываются? Неважно, пусть это остается на совести нерадивых программистов, а мы пойдем дальше.
Есть такое замечательное правило:
Если для функции сложно подобрать имя, то ее нужно переписать (разбить на подфункции)
И еще один хороший принцип:
Одна функция — одна задача
Часть 3: Уровни Абстракции
“Чем больше употребляет художник эти абстрагированные или абстрактные формы, тем более он будет дома в их стране и тем глубже будет он вступать в эту область”.
— Василий Кандинский
Любой IT продукт, будь то веб-сайт, мобильное приложение или наручные электронные часы, является наглядным примером многоуровневых абстракций. К примеру, кнопки, которые мы видим на веб-сайте, через интернет запускают функции в коде. Но это лишь начало. Затем код, написанный разработчиком сайта, будет использовать библиотеки языка программирования, на котором написан сайт, допустим, Python. Python в свою очередь будет вызывать библиотеки более низкоуровнего языка программирования, при помощи которого он работает. В данном случае, это язык C++. Дальше библиотеки C++ будут обращаться к языку Assembler, на котором написаны компоненты операционной системы, а они будут совершать системные вызовы, через которые запрос дойдет до процессора и где-то там преобразуется в нолики и единички, а дальше в электрические сигналы, которые и сделают нужное нам вычисление. После чего результат вычисления по той же цепочке вернется обратно.
И это очень упрощенная схема того что происходит, когда мы спрашиваем у Гугла, сколько будет два плюс два. В действительности этих ступеней намного больше. Их созданием занимались самые разные специалисты: физики, инженеры-микроэлектронщики, программисты операционных систем, создатели и разработчики языков программирования, программисты веб-сайтов. Каждый из них старался максимально упростить жизнь другим специалистам, которые будут пользоваться результатом их трудов. Сегодня мы можем очень быстро разработать веб-сайт только потому, что 99.9% работы уже сделано до нас.
Те же самые законы действуют, когда мы работаем с кодом внутри проекта. Нам необходимо разделять код по уровням абстракции, чтобы разработка не стала слишком сложной. Каждый компонент системы должен “думать” на том уровне, на котором он находится. Функция, записывающая e-mail пользователя в базу данных, не должна знать, откуда пришел этот e-mail: из формы на веб-сайте, из мобильного приложения или из интеграции с социальной сетью. За это отвечают более высокие уровни. Этот принцип работает и в другую сторону: функция для записи e-mail в базу не должна знать, в какую базу она запишет данные. За это отвечают более низкие уровни, адрес и вид базы должен быть обозначен в них. Такой подход с четким разделением уровней абстракции в коде дает огромное преимущество в разработке, позволяет сделать ее проще и быстрее.
Представьте, что коллега говорит: “Нам нужно отправить нотификации на мобильные приложения, но я уже все сделал. Просто вызови мою функцию, передай в нее текст сообщения и Id пользователя”. По-моему, звучит неплохо! Разработчик абстрагировал отправку нотификаций от другой логики приложения. Теперь в проекте есть функция, занимающаяся именно этим, и ее можно использовать. И представьте другую ситуацию. Ваш коллега говорит: “Нам нужно отправить нотификации на мобильные приложения. Я уже сделал это для сообщений об оплате для клиента по имени Билл. Теперь нам нужно сделать сообщение о пополнении счета для Джона — ты посмотри, как я написал функцию, напиши свою, примерно такую же, только поменяй текст и Id пользователя.” Звучит уже не так хорошо. В этом случае придется изучить код коллеги, копировать части кода, изменять их и адаптировать под свои задачи. Это займет намного больше времени и обязательно приведет к дублированию в коде.
Не мешайте конкретику с абстракциями
Работая с кодом в одиночку также необходимо задумываться об уровнях абстракции. Таким образом мы помогаем самим себе в будущем. У программистов есть такое понятие: “закладывать в архитектуру», то есть заранее предусмотреть некую ситуацию, и, когда заказчик попросит что-то сделать, код уже будет максимально готов к таким изменениям. Разделение по уровням абстракции — это один из способов быть готовым к возможным новым требованиям. Нужно сделать нотификации для Айфона? Отлично, мы уже сделали их для Андроида. Теперь остается наладить соединение с новой платформой, а сами нотификации делать не придется — они уже у нас есть. Так это работает.
Часть 4: DRY (Don’t repeat yourself / Не повторяйся)
“Хотя бы свитер ему купи. Смотреть стыдно. Ведь он уже не маленький. Ему стыдно ходить раздетым. Хоть свитер ему купи. Смотреть стыдно. Ведь он уже не маленький. Ему совестно ходить раздетым”.
— Из к/ф “Чеховские Мотивы”, реж. Кира Муратова
DRY — золотое правило программирования, значение которого трудно переоценить. Множество различных приемов программирования, таких как абстракции, наследование, композиция, разделение ответственности, паттерны проектирования и сама парадигма ООП (объектно-ориентированное программирование) во многом были сделаны для того, чтобы избежать повторений в коде. Такая, на первый взгляд, тривиальная задача порой ставит разработчика в очень сложные ситуации. Давайте рассмотрим как это происходит и какие виды дублирования бывают.
Дублирующее значение
Есть такой “анти-паттерн проектирования», как Магическое число. Допустим, переменная price умножается на число 0.13 и записывается в переменную tax. В этом случае можно догадаться, что tax — это коэффициент налога (13% налог НДФЛ). Любой российский разработчик знает величину подоходного налога и присутствие такого числа рядом с переменной price никого не удивит. И все-таки это — Магическое число! Во-первых, разработчик, незнакомый с российскими законами, не поймет откуда оно взялось. Во-вторых, величина налога НДФЛ в любой год может измениться, и тогда придется переделывать все участки кода, где данное число дублировано.
Подобные магические числа, как правило, повторяются в коде неоднократно. Но даже если сейчас оно имеется в единственном экземпляре, то велика вероятность, что в будущем нам снова придется его использовать. Так почему бы сразу не создать из него переменную?!
Любое значение должно присутствовать в коде в одном экземпляре
Исключение можно сделать в том случае, если значение присутствует повторно, но с другим смыслом. К примеру, в одном месте кода 0.13 может быть коэффициентом налога, а в другом месте 0.13 является уже комиссией, увеличивающей стоимость товара. Тогда это должны быть разные переменные.
Дублирующие блоки кода
C данной проблемой нередко сталкиваются даже профессиональные разработчики. Представьте, что перед вами стоит задача создать процедуру, похожую на какую-либо уже имеющуюся. Действительно, легче и быстрее скопировать блок кода, чем выносить его в отдельную функцию и вызывать ее в нужном месте. Но сколько такой подход может создать проблем! Изменение этого блока необходимо применять сразу в двух, а часто в трех и более местах, куда был скопирован код. А если вынести этот код в отдельную функцию, то, кроме очевидной выгоды от отсутствия дублирования, мы приобретаем еще несколько менее очевидных, но не менее важных преимуществ.
Выделение блока кода в отдельную функцию соответствует принципу разделения ответственности. Так как данный блок имеет определенное назначение, то будет правильным сделать из него отдельную процедуру, не перемешивая ее с логикой функций, которые ее вызывают.
Выделение блока кода в отдельную функцию способствует хорошему описанию кода, ведь созданная функция получит имя. Это имя должно описывать ту процедуру, которая происходит в функции, следовательно, нам станет легче понимать этот код.
Не копируйте код! Выносите его в отдельную функцию
Дублирующее поведение
Данный вид дублирования сложнее всего уловить в коде. Чтобы его успешно избегать, требуется опыт. В паттерне проектирования “Шаблонный метод” представлен замечательный способ, которым можно бороться с дублирующим поведением, почитайте про него. В этой статье я не буду ставить перед собой задачу пересказать реализацию этого шаблона проектирования, а просто расскажу о проблеме дублирующего поведения, и как ее можно решить данным способом.
Каждая из создаваемых нами процедур может иметь определенные этапы, которые мы создаем, руководствуясь принципом разделения ответственности. Создавая следующую процедуру, нужно подумать, не имеет ли она схожих этапов с уже созданными процедурами. Если это так, то мы можем определить абстрактный базовый класс для классов наших процедур и обозначить в нем некоторые этапы и порядок их выполнения. К примеру, для записи данных в файл и записи данных в базу, мы могли бы создать общие классы.
Здесь две процедуры не только имеют общую стратегию поведения, но также имеют один общий этап. Реализовав поведение этих процедур в абстрактном базовом классе, мы вполне можем переместить в него код их общих этапов, наподобие этапа “Оповещение” в табличке, что будет удобно для совместного использования этого кода. А выделение основных схожих этапов в базовом классе упростит создание новых процедур.
Если вы видите, что создаваемые вами процедуры имеют схожее поведение, то попробуйте определить его в родительском (базовом) классе данных процедур
Автор статьи может стать твоим ментором и научить тебя программировать. Нанять
Заключение: Рефакторинг
“God is in the details”.
— Людвиг Мис ван дер Роэ и другие
Если вы дочитали до этой строки, то уже знаете несколько основных моментов, на которые стоит обратить внимание, анализируя код. По сути, анализ и переработка кода — это и есть части рефакторинга. А одна из главных его целей — сделать код более понятным для чтения, а значит и более логичным, и более качественным.
Неважно, работаете вы со своим кодом или с чужим, не жалейте времени на рефакторинг, это время окупится. Вместе с развитием приложения переработка его кода всегда становится необходима. А изменение отдельных его частей всегда будет затрагивать другие части, а иногда и структуру в целом. Именно поэтому рефакторинг всегда был и будет частью рабочего процесса. В этой статье я постарался обозначить несколько направлений, придерживаясь которых можно сделать рефакторинг, свести к минимуму необходимость рефакторинга в будущем и облегчить себе анализ и переработку чужого кода.
Но знать эти правила часто оказывается недостаточным. Создавая код, требуется много времени, чтобы он не просто работал, но и выглядел хорошо. Даже очень опытные разработчики часто переписывают свои функции много раз перед тем, как предоставить стабильную версию кода.
Недавно я разговаривал с художником, великолепно написавшим портрет моей знакомой. Я выразил восхищение и спросил, как ему удалось добиться такого сходства? Ответ был прост: “Я переписывал ее лицо снова и снова: три, четыре, пять раз, пока результат меня не начал устраивать”.
Создавая код, стремитесь к простоте и выразительности
Используйте приемы, описанные в этой статье. Изобретайте свои. Помогайте другим разработчикам сделать их код понятнее, ведь часто виднее со стороны. Относитесь к своему коду как к произведению искусства, и тогда он будет работать по-настоящему хорошо!
© Copyright 2014 — 2023 mkdev | Privacy Policy
Как читать чужой код: 6 правил, которые стоит помнить разработчику
Каждому программисту рано или поздно предстоит разобраться в чужом коде, однако не все это делают правильно. Мы перевели статью разработчика Уильяма Шона и узнали, как читать чужой код так, чтобы понимать его и выносить из этой практики что-то новое.
Вы читаете обновленную и улучшенную версию нашей старой статьи
Почему разработчики не любят разбираться в чужом коде
«Ненавижу читать чужой код», — такую фразу можно часто услышать от программистов. Причина их ненависти в том, чужой код пишут не они. Это не значит, что каждый разработчик страдает манией величия, все гораздо проще: читатель никогда не испытает того потокового состояния, в котором находился программист, когда создавал свой код. Поэтому пассивное чтение иногда бывает скучным.
Читатель может не осознавать, что видит на экране труд нескольких разработчиков. Возможно, они спорили во время кодинга, и он дался им нелегко. Возможно, разработчикам потребовались недели, чтобы выдать код, который обходит недокументированные ограничения. Читатель имеет дело с законченным продуктом и даже не догадывается, что стоит за многократно выверенными строками кода.
Рано или поздно у разработчика наступает момент, когда ему предстоит читать чужой код. Например, когда программисту нужно изменить или обновить существующий код, провести код-ревью, разобраться в работе программного интерфейса. Для этого нужно знать, как читать и понимать чужой код. Это умение полезно и тем, кому только предстоит освоиться в кодовой базе. Разберемся, на что обратить внимание при чтении чужого кода, чтобы понять его и, возможно, чему-то научиться.
Как правильно читать код
Научитесь проводить «раскопки» в коде
При первом знакомстве с серьезной кодовой базой вы будете ощущать себя не разработчиком, а археологом, частным сыщиком или исследователем религиозных книг. Вам придется проводить «раскопки» в чужом коде, чтобы понять, как он создавался.
Если вы работаете над кодовой базой, в которой разработчики использовали контроль версий, то у вас есть доступ к метаданным. Изучите следующие команды для Git, чтобы узнать, как изменялся код (они подойдут и для SVN):
git blame
С помощью этой команды вы узнаете имя автора кода, дату последних изменений и хэш коммита (зафиксированного изменения в коде) для каждой строки. Так можно найти историю кода и понять, какой именно код был внесен в репозиторий, как это было сделано и по какой причине. Если это возможно, познакомьтесь с авторами кода: они постараются ответить на ваши вопросы.
Читая код, убедитесь, что вы понимаете, где он начинает выполняться и что происходит в процессе его запуска. Посмотрите, какие файлы подключаются, какие классы используются, какие опции конфига устанавливаются. Скорее всего, вы будете постоянно сталкиваться с ними во всей кодовой базе.
Некоторые модули могут выделяться из остального кода и иметь очень общее назначение. Выполните git blame и посмотрите, какие части основного файла недавно изменяли. Так вы узнаете проблемы, которые решала команда в последнее время. Возможно, разработчики долго пытались наладить библиотеку, которая не слишком хорошо работала. Может, там просто шаблонный код, который нужно регулярно обновлять.
Попробуйте найти примеры таких выделяющихся модулей в других частях кода, чтобы узнать, как и когда они используются. Это поможет вам понять место и роль модулей в основном приложении.
git log и git grep
Используйте команду git log , чтобы увидеть историю коммитов по всему репозиторию. Команда git grep поможет вам найти в коммитах конкретный текст, например, название функции someFunction: git log | grep someFunction -C 3 . Последние флаги покажут вам найденные выражения с тремя строками окружающего контекста.
Также git log может показать вам историю отдельного файла. Чтобы ее посмотреть, используйте флаг -p: git log -p index.js . Обращайте внимание на имена авторов коммитов, чтобы знать, кому в будущем адресовать вопросы.
Переключайтесь между коммитами и изучайте историю кода
Вы можете переключиться на любой коммит и запустить проект так, будто этот коммит был последним. Как правило, это делают для того, чтобы выявить сложно отслеживаемую проблему. Также коммиты переключают, чтобы увидеть историю кода.
Если проект хранится на GitHub или подобном сервисе, вы можете узнать много нового, читая пулл-реквесты и код-ревью. Обращайте внимание на тикеты — карточки-задачи для отслеживания работы над багами, внедрения функций. Читайте обсуждения в тикетах: там могут быть «болевые точки», с которыми вы можете столкнуться в будущем, поэтому лучше иметь представление о них заранее.
Читайте спецификации
Specs или спецификации — это новые комментарии к коду. Читайте unit specs, чтобы выяснить предназначение функций, модулей и возможные пограничные случаи (edge-cases), которые они обрабатывают.
Также читайте интеграционные спецификации, чтобы понять, как пользователи будут взаимодействовать с вашим приложением и какие процессы оно поддерживает.
Воспринимайте комментарии как подсказки
Если в процессе изучения кода вы наткнулись на непонятную функцию и прочли комментарий к ней, который еще больше вас запутал — возможно, он просто устарел. Держите это в голове: если комментарий к функции давно не обновлялся, вероятно, она исчезла уже много месяцев назад, и кроме вас это никто не заметил.
Обращайте внимание на стиль написания кода
Читая чужой код, посмотрите, соблюдены ли стандарты его оформления, есть ли именования, пробелы, скобки. Обратите внимание на общий уровень абстракции кода. Если у него много уровней абстракции, то вам следует их использовать и в своем коде.
Если вы хорошо провели «раскопки», то нашли момент, когда один из разработчиков решил абстрагировать часть кода. Вспомните, как код выглядел до этого изменения и задумайтесь, что с ним стало после выноса на новый уровень абстракции.
Работая над проектом, посмотрите, какие конструкции используют разработчики из вашей команды. Если они отдают предпочтение циклам, а не функции map , то и вам следует их использовать. Если вам не нравится стиль оформления кода в проекте, обсудите это с командой — это лучше, чем смешивать разные стили в одном файле. Хороший код выглядит так, будто он написан одним человеком.
Избавляйтесь от «мусора» в коде
Пока вы читаете код, вам могут встретиться функции и целые файлы, которые разработчики никогда не используют, и комментарии, на которые никто не отвечал несколько лет. Не тратьте на разбор всего этого много времени — избавьтесь от «мусора». Если этот код все еще нужен, кто-нибудь отметит это на код-ревью. Удалив ненужное, вы сбережете силы и время того, кто будет читать этот код после вас.
Итог
Не падайте духом, если чувствуете, что вы совсем запутались в чужом коде. Изучение кода — это не линейный процесс. Не ждите, что сразу поймете все на 100%. Обращайте внимание на важные детали, проводите «раскопки», чтобы найти ответы на вопросы, и, надеемся, все станет понятнее.
Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях
Можно ли научиться быстро разбираться в чужом коде?
Очень часто слышу о таком скиле как «умение быстро разбираться в чужом коде». Но у меня при виде чужого кода мозги вскипают и в сон клонит. Особенно какой-нибудь джаваскрипт — это вообще жесть. Сейчас разбираю — в одном файле создание объектов через замыкания, через new и через Object.create. Нафига? Показать знание языка?
Главное при приеме на работу обязательно спросят о паттернах, ооп и т.п. А в код заглянешь — пардон, блевать тянет. В одном классе куча методов по одной строчке, в другом каждый метод на тысячи строк. Каждый колхозит как может. Хуже всего, что большая часть кода глубокого смысла не имеет — просто костыли и быстрофикс мелких багов, сделано «как получилось». И как в этом разбираться?
- Вопрос задан более трёх лет назад
- 1479 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 4
Full-stack developer (Symfony, Angular)
Сейчас разбираю — в одном файле создание объектов через замыкания, через new и через Object.create. Нафига?
Создание объекта через замыкание — модуль. Нужно потому что в JS нет модификаторов доступа и все приватное должно быть сокрыто в изолированной области видимости. Это шаблон.
Создание объекта через new — а вы как объекты создаете? Не пользуетесь объектами вообще?
Object.create — это уже для наследования применяется. Да, конечно если вооружиться каким ES6 все будет делать сам JS или трансляторы ES6 — ES5. Но знать об этом нужно.
Как разбираться в чужом коде? Нужно уметь писать свой для начала. Описанные вами проблемы решает периодический код ревью и т.д. А среди фронтэндщиков писать говнокод так же популярно как и среди других разработчиков. Возможно только в PHP комьюнити процент говнокода больше. Это проблема отсутствия образования и понимания тех самых паттернов и т.д. Заучат для собеседования и все.
Ответ написан более трёх лет назад
Нравится 6 6 комментариев
lugger @lugger Автор вопроса
Object.create — это уже для наследования применяется. Да, конечно если вооружиться каким ES6 все будет делать сам JS или трансляторы ES6 — ES5. Но знать об этом нужно.
А что мешает относледоваться через prototype в случае с new?
Этот пример я привел для иллюстрации своего вопроса. Каждый программист дописывал код как он привык. При этом даже функции-конструкторы написаны иногда с маленькой буквы и приходиться запоминать как создавать объект.
Описанные вами проблемы решает периодический код ревью и т.д.
Это организационные вопросы. На них обычный программист не может существенно повлиять.
lugger: сейчас рекомендованный подход по работе с объектами — Object.create. Смиритесь. Через new — старый подход, если вам нельзя использовать ES5. Вопрос совместимости. Благо нынче есть полифилы.
По поводу организационных вопросов — если нельзя повлиять — жаль.
Как разобраться в чужом коде c
«Как ты понимаешь чужой код? Я хорошо разбираюсь в своём собственном коде, но всякий раз, когда мне нужно понять чужой, — я теряюсь. Чувство потерянности преследует меня все время, особенно, если код плохо задокументирован. Я до сих пор не представляю, с какой стороны нужно подступиться, чтобы работать с чужим кодом более эффективно. Было бы хорошо, если бы ты дал мне парочку советов.»
Мне понравился этот вопрос по нескольким причинам:
- Он проливает свет на один из самых важных аспектов приобретения новых навыков в программировании: учиться нужно часто и регулярно, используя большое количество примеров хорошего качества.
- Советы, которые я дам, помогут вам лучше читать и понимать чужой код.
Итак, давайте пойдём по порядку.
Как лучше всего читать и понимать чужой код?
1. Найдите ту часть кода, которую понимаете, а дальше попытайтесь распутать логическую цепочку из вызовов методов, классов и переменных в обратном направлении.
Например, вы точно знаете, что кусок кода, который вы просматриваете, создает файл с заголовками фильмов. Сначала выясните, где конкретно находятся строчки, которые создают этот файл на диске. Далее, найдите место в коде, в котором в файл добавляется информация. Двигаясь в обратном направлении, найдите место откуда берется эта информация. И так далее…
Давайте назовем эти связанные между собой куски кода «Цепочкой действий».
Используя этот подход, вы неизбежно будете двигаться от одного участка кода к другому. И это, вероятно, поможет вам получить представление о следующем:
- Как этот код устроен (где определяются переменные, где хранятся те или иные методы и т. д.).
- Стиль, в котором написан код.
- Как программист, написавший этот код, думает и решает те или иные задачи (это сложно объяснить, но интуитивное понимание таких вещей приходит только с опытом).
Делая так, вы постепенно будете всё лучше и лучше понимать чужой код. И вскоре в больших кусках кода, в которых вы ранее не могли ничего понять, вам станут «открываться» отдельные части. И постепенно будет приходить понимание все большего и большего количества строк кода. Это примерно как стоять в большой, абсолютно тёмной комнате, в которой постепенно зажигается свет, и вы со временем начинаете различать всё больше и больше предметов, находящихся в ней.
Используйте подход «Цепочка действий» чтобы постепенно начать разбираться в ранее незнакомом коде
2. Повторяйте данные действия снова и снова.
Применяйте данный способ изучения кода множество раз, и вы быстрее сможете разобраться в непонятных ранее участках программы.
Данный подход позволяет декомпозировать задачу, выделив в ней отдельные части, которые можно понять без труда. В этом и заключается секрет эффективности данного метода. Через какое-то время вы обнаружите, как легко вам стало читать и понимать весь код.
Данный вывод подводит нас к первой причине, по которой мне понравился заданный вопрос: к важности учиться часто, регулярно и на хороших примерах. В данном случае, под хорошими примерами подразумеваются примеры кода, которые пишут более опытные программисты — эксперты в своей области.
О важности регулярного обучения на примерах высокого качества
В своей новой книге «Badass: Making Users Awesome» Кэти Сьерра заявляет, что регулярное обучение на примерах высокого качества является одним из двух основных факторов, влияющих на то, как быстро и эффективно люди приобретают новые навыки (второй фактор — это целенаправленная практика).
«Чем больше вы смотрите (или слушаете) примеры от экспертов своего дела, тем лучше вы становитесь. Чем меньше вы прислушиваетесь к советам экспертов или к результатам их работы, тем меньше у вас шансов самому стать экспертом и развить экспертные навыки.»
Взглянем на первый пример, который сразу приходит в голову: определение пола у цыплят. Звучит как шутка, однако этот пример отлично демонстрирует озвученную выше концепцию.
Изучаем, как определить пол цыпленка
Как эксперты используют бессознательные перцептивные знания
Кэти объясняет, какое отношение определение пола цыпленка имеет к нашему разговору:
«Общеизвестно, что определение пола недавно вылупившегося цыплёнка является очень не простой задачей. Однако, для крупных коммерческих птицеферм крайне важно как можно раньше разделять цыплят по половому признаку. В 1900-х годах, в Японии был разработан особый метод для определения пола, а также появилась группа экспертов в этом деле.
Отлично, скажете вы! Теперь эти эксперты смогут научить остальных, верно? Не совсем, есть одна проблема: они не знали, как им это удается. «Я просто знаю пол и всё» — отвечали они.
Так как же они проходили обучение? Предположим, вы один из новобранцев в ряды определителей пола цыплят. Вы встаете перед ящиком с цыплятами. Проблема в том, что для вас они ничем друг от друга не отличаются. Но вам сказали просто брать одного и делать предположение о поле цыплёнка. Вам кажется, что ваши предположения полностью случайны.
После каждого вашего предположения наставник проверяет вашу работу и говорит либо «верно», либо «неверно». Вы до сих пор понятия не имеете, как эти эксперты это делают, но вы продолжаете делать это снова и снова. Через какое то время что-то происходит, и вы начинаете определять пол лучше, чем если делали бы это наугад, однако, вы все еще не имеете понятия почему. У вас складывается ощущение, будто какая-то «мистическая сила» помогает вам делать правильный выбор.»