<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Кодстайл</title>
    <description>Статьи, которые помогут вам перестать писать код в одну сплошную строку и научат следовать официальным правилам оформления кода.</description>
    <link>https://tproger.ru/tag/code-style</link>
    <atom:link href="https://tproger.ru/tag/code-style/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Mon, 28 Sep 2026 22:13:54 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Кодстайл</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Как читать чужой код и понимать его: гайд, как не разбить экран компьютера</title>
      <link>https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera</link>
      <comments>https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera</guid>
      <description><![CDATA[<p>Как читать не свой код. Показываем, как правильно понимать и разбираться в чужом коде. Рассматриваем пошаговую инструкцию и основные нюансы ✔ Tproger</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera">Как читать чужой код и понимать его: гайд, как не разбить экран компьютера</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 31 Jan 2025 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Представьте себе ситуацию: вы пришли в новую компанию, и вам сказали переписать чужой код. Ну, по крайней мере, сделать так, чтобы он работал. И вот вы сидите, ухватившись руками за голову, и пытаетесь понять, что делает эта функция и зачем нужна эта кнопка. Еще хуже — если нет документации. Рано или поздно с этим сталкиваются почти все прогеры, но без паники: прочесть, а, главное, понять чужой код — задача сложная, но выполнимая.</p><p>Разбираться в чужом коде — очень крутой навык, поскольку в нем вы можете найти новые приемы и подходы, посмотреть на логику решения конкретной задачи (можете сравнивать со своей), плюс быстрее адаптироваться к процессам в компании.</p><p>В статье расскажем, как читать чужой код без стресса, а еще рассмотрим типичные ошибки и посоветуем крутые лайфхаки.</p><h2>Разбираемся на практике</h2><p>Поскольку автор этой статьи — филолог по образованию и айтишник в душе, мы не придумали ничего лучше, чем создать код для библиотечной системы. Проект довольно сложный, поскольку в нем много файлов. В общем, давайте копаться.</p><h4>Структура проекта:</h4><p>Library_project/</p><p>├── Library/</p><p>│   ├── models/</p><p>│   │   ├── book.py</p><p>│   │   └── catalog.py</p><p>│   ├── utils/</p><p>│   │   ├── search.py</p><p>│   │   └── reports.py</p><p>│   └── tests/</p><p>│       └── test_catalog.py</p><p>└── main.py</p><h4>Код проекта:</h4><p>Представление о проекте есть, а теперь давайте по шагам читать чужой код.</p><h2>Шаг 1: Поймите, что в принципе делает код</h2><p>Первое, что нужно сделать при анализе чужого кода — понять его цель. Вместо того, чтобы сразу погружаться в реализацию, начните с конца: что делает программа и какую проблему она решает?</p><p>Давайте посмотрим на файл main.py:</p><p>Из него понимаем, что:</p><ol><li>Проект связан с библиотекой (судя по названию модуля);</li><li>Есть тестовый сценарий, в котором видно основную функциональность;</li><li>Код организован в пакеты и модули.</li></ol><p>Если запустим тесты, увидим следующее:</p><p>Теперь мы знаем, что система как минимум умеет:</p><ul><li>Выдавать книги;</li><li>Искать книги по названию;</li><li>Показывать статус.</li></ul><h2>Шаг 2: Изучите общую структуру кода</h2><p>Когда вы поняли, что делает программа, нужно разобраться в ее архитектуре, и здесь важно задавать правильные вопросы:</p><p>Вопрос 1: Как организованы данные?</p><p>Помним, что у проекта есть четкая структура:</p><p>Library_project/</p><p>├── Library/</p><p>│   ├── models/</p><p>│   │   ├── book.py         # Данные о книгах</p><p>│   │   └── catalog.py      # Управление каталогом</p><p>│   ├── utils/</p><p>│   │   ├── search.py       # Поиск</p><p>│   │   └── reports.py      # Генерация отчетов</p><p>│   └── tests/</p><p>│       └── test_catalog.py # Тесты</p><p>└── main.py                 # Точка входа в приложение</p><p>Она говорит нам о том, что:</p><ul><li>Данные о книгах и каталоге разделены;</li><li>Дополнительные функции лежат в отдельном модуле;</li><li>Есть модуль для тестов;</li><li>Система в целом следует принципам модульности.</li></ul><p>Вопрос 2: Как взаимодействуют компоненты?</p><p>Посмотрим на импорты в catalog.py:</p><p>Это показывает, что:</p><ul><li>Каталог зависит от класса Book;</li><li>Приложение подтягивает даты (чтобы проверять сроки).</li></ul><p>Вопрос 3: Какие главные операции выполняются в системе?</p><p>В классе LibraryCatalog видим:</p><p>Отсюда понятно, что система может:</p><ul><li>Выдавать книги на конкретный срок;</li><li>Возвращать книги;</li><li>Делать поиск по каталогу.</li></ul><h2>Шаг 3: Изучите документацию и комментарии</h2><p>При чтении чужого кода документация и комментарии — ваши лучшие друзья. Например:</p><p>Здесь мы видим docstring, который кратко описывает назначение класса. Более наглядный пример — метод borrow_book из файла /models/catalog.py:</p><h2>Шаг 4: Проанализируйте главную точку входа в программу</h2><p>Точка входа — место, с которого начинается выполнение программы. В нашем случае это main.py, но давайте посмотрим внимательнее, на что он ссылается:</p><p>Из этого кода видно, что первым делом импортируются классы: LibraryCatalog из файла /models/catalog.py, BookSearch из файла /utils/search.py и класс ReportGenerator из файла /utils/reports.py.</p><p>Далее — функция run_basic_tests, в которой создается экземляр класса LibraryCatalog. В переменную status записывается значение вызова метода borrow_book, который возвращает статус выдачи книги.</p><p>Затем выводится информация о тесте выдачи книги. По аналогии, в переменные search_results, return_status, overdue_report записываются значения вызова методов search_by_title, return_book и generate_overdue_report соответственно.</p><h2>Шаг 5: Определите ключевые функции и классы</h2><p>В любом проекте есть основные компоненты, вокруг которых строится вся логика. В нашем случае это:</p><p>LibraryCatalog — центральный класс. В нем реализованы основные методы управления  библиотекой, такие как: добавление новой книги (add_book), выдача книги читателю (borrow_book), возврат книги в библиотеку (return_book), получение списка всех выданных книг (get_borrowed_books) и поиск книги (find_book).</p><p>BookSearch — утилитный класс. В нем реализованы методы поиска книги по автору и по названию.</p><h2>Шаг 6: Используйте инструменты IDE для навигации и анализа</h2><p>В современных IDE есть мощные инструменты для анализа кода. Рассмотрим несколько основных на примере нашего «чужого» кода.</p><ul><li><b>Find Usages:</b></li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/2d0a67e6-f386-402d-9e21-abada847e66a.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/aaa474da-8e16-4dc9-abd2-318cf3e454be.png" alt="" /></figure><p>Здесь мы ищем метод borrow.book и видим, как он используется в тестах и других частях кода.</p><ul><li><b>Go to Definition</b> — видим, как создается объект:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/df361ff8-07cf-43d7-8dd7-ffb2a04ccf90.png" alt="«Как читать чужой код»" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/bd209a94-69ee-42bb-ba26-27adfc4c20d2.png" alt="" /></figure><ul><li><b>Structure View</b> — позволяет увидеть все методы и свойства классов в одном месте:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/15efccac-3f80-402a-bfc5-be06d3ca692d.png" alt="«Как понимать не свой код»" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/8370982b-aa2d-4f03-adc0-9c586c44e740.png" alt="" /></figure><h2>Шаг 7: Отладка и запуск — пошаговое выполнение кода</h2><p>Один из лучших способов понять, как работает чужой код — пройтись по нему в отладчике.</p><p>С помощью отладчика можно видеть значения всех переменных на момент исполнения, проверять различные условия в реальном времени, а также понимать последовательность выполнения кода.</p><p><b>1. Установим breakpoint в методе borrow_book:</b></p><p>2. <b>Запустим тест и пошагово посмотрим:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/69bfc18f-76ab-411b-b8ed-36e886cf954e.png" alt="" /></figure><p>Этот скриншот показывает значения переменных:</p><p><b>3. Затем можно посмотреть пошаговое выполнение кода с помощью функций Step Over, Step Into, Step Out:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/eee25a30-e18b-492e-838b-d6a70f9cbf74.png" alt="" /></figure><p><b>4. Теперь можно попробовать выдать 2 раза одну книгу разным людям и запустить отладку:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/91018ceb-fcfc-4d2a-a4ed-305a9a650ffe.png" alt="" /></figure><p>На этом скриншоте мы видим, что книга с этим id доступна для выдачи. Продолжим выполнять код, нажимаем на кнопку Resume Program:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/ae92ab74-1d2b-402a-bb2a-c578bd7e8f35.png" alt="" /></figure><p>Теперь мы можем увидеть, что книга уже была выдана. То же самое появляется и в выводе при завершении программы. Так мы пошагово отслеживаем проверку выдачи книги и изменение статуса ее доступности. В общем, полезная штука, если в коде сложная логика, плюс можно найти потенциальные проблемы.</p><h2>Несколько советов, чтобы не сойти с ума, читая чужой код</h2><h4>Рисуйте диаграммы</h4><p>Будущая версия вас обязательно скажет спасибо за то, что этот хаос переменных и циклов вы оформили в виде понятной схемы — что, зачем и куда ведет; а еще оставляли комментарии типа «Вот это не трогай, оно тебя сожрет». На самом деле, визуально представлять чужой код — огромный плюс, особенно если вам потом придется работать над ним вместе с коллегами.</p><h4>Создайте мини-документацию для себя</h4><p>Представьте, что ведете личный дневник по горячим следам. Если в коде вы наткнулись на нечто неочевидное, сделайте краткую запись: что это за модуль, зачем он тут, и как он связан с другими частями. Через неделю, когда вы снова откроете проект, сами себе скажете: «Ого, какой я молодец, всё прописал!».</p><h4>Не пытайтесь понять весь код целиком</h4><p>Если вы считаете, что сядете и поймете весь код за один присест — пересчитайте. Это наш код с библиотекой не такой мудреный, а бывают и проекты, где десятки файлов, подключение API и сотни циклов. Даже опытные разработчики начинают с малого: выбирают один модуль, функцию или файл, и разбираются в них, а уже потом переходят к остальному.</p><h4>Оставайтесь в контексте</h4><p>Если вы изучаете код без понимания, где и как он применяется, это всё равно что настраивать выключенный монитор. Понять контекст можно через вопросы, например: «Что за проект? Какая целевая аудитория? Какие задачи решает этот код?». Например, вы понимаете, что этот модуль связан с оплатами, значит, нужно разобраться, как работает система транзакций.</p><h4>Не забывайте про библиотеки</h4><p>Если в чужом коде много сторонних библиотек и фреймворков, о которых вы могли даже не слышать, обязательно их изучите — именно здесь появляется много багов. И в целом, узнавать новые инструменты — полезно и весело, поскольку они могут выполнять за вас большую часть работы.</p><p>Поздравляем, вы прошли игру. Читать чужой код — практически искусство. Самое важное помнить, что миллионы разработчиков по всему миру с вами в одной лодке. Рассказывайте в комментах, какие проблемы возникали у вас при чтении чужого кода.</p><p>Кстати! Хочешь разбираться в коде быстрее и эффективнее? Собрали для тебя полезные советы <a href="https://t.me/+ySi8k_7h_rxkNzY6">тут</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как senior-программисты пишут код на самом деле</title>
      <link>https://tproger.ru/articles/kak-senior-programmisty-piwut-kod-na-samom-dele</link>
      <comments>https://tproger.ru/articles/kak-senior-programmisty-piwut-kod-na-samom-dele?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дух айтишной эмо школы]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-senior-programmisty-piwut-kod-na-samom-dele</guid>
      <description><![CDATA[<p>На YouTube-канале про IT Healthy Software Developer вышло новое видео, в котором автор рассказывает, как senior инженеры-программисты пишут код на самом деле. </p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-senior-programmisty-piwut-kod-na-samom-dele">Как senior-программисты пишут код на самом деле</a>»</p>]]></description>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 26 Jan 2024 11:36:54 GMT</pubDate>
      <content:encoded><![CDATA[<p>На YouTube-канале про IT Healthy Software Developer вышло новое видео, в котором автор рассказывает, как senior инженеры-программисты пишут код на самом деле.</p><p>Вот, о чём идёт речь в ролике:</p><ol><li>Плохо, когда приходится просить менеджера проекта добавить новую пользовательскую историю для документации, это может привести к микроменеджменту.</li><li>Хорошо написанный код позволяет другим разработчикам легче его понять, что отличает junior разработчика от senior.</li><li>Написание качественного кода сокращает время на поддержку и объяснение кода другим, уменьшая количество перерывов в работе.</li><li>Код, написанный на уровне senior-разработчика, снижает вероятность его переписывания другими и увеличивает ‘срок жизни’ кода.</li><li>Важно завершать работу над кодом до перехода к следующему заданию, чтобы не накапливать технический долг.</li><li>Соблюдение стандартов кодирования и использование автоформатирования улучшают читаемость и согласованность кода.</li><li>Документирование используемых паттернов облегчает работу команды и поддержку проекта.</li><li>При внедрении новых паттернов важно обсудить их с командой и получить обратную связь перед полномасштабным использованием.</li><li>Не следует создавать отдельные задачи для рефакторинга, чтобы избежать их исключения менеджментом, рефакторинг должен быть инкрементным.</li><li>При оценке работы необходимо учитывать дополнительное время на неожиданные встречи по дизайну и написание документации.</li></ol><p>Ниже представлен транскрибированный перевод видео на русский язык.</p><h2>Почему вообще важно писать хороший код как senior</h2><p>Ну, во-первых, это позволяет другим людям понять наш код. Вероятно, вы оказывались в кодовой базе, читая её и просто думали: “Я не понимаю, что здесь вообще происходит”.</p><p>И соблазн часто заключается в том, чтобы просто прыгнуть и переписать все. Но умение писать код, который другие люди могут легко читать, – это то, что другие разработчики в вашей команде действительно оценят. И это часто является разницей между тем, как они смотрят на вас как на младшего разработчика и старшего программиста.</p><p>Вторая причина, почему важно писать хороший код, заключается в том, что это сокращает время, необходимое для его поддержки и объяснения кому-то еще. Я часто работаю с другими разработчиками, которые торопятся и не следуют некоторым из шести вещей, о которых я собираюсь рассказать в конце видео, и потом они раздражены, когда их постоянно прерывают другие разработчики с вопросами о коде, и они говорят: “У меня нет на это времени”.</p><p>Ну, если вы действительно следуете некоторым из вещей, которые я собираюсь поделиться с вами сегодня, это действительно сократит это время и позволит вам просто работать над тем, что вам действительно хочется делать.</p><p>И третья причина, почему важно научиться писать код как настоящий старший программист, заключается в том, что это сокращает вероятность того, что кто-то перепишет ваш код. Я думаю, одна из самых раздражающих вещей для разработчика – это когда вы очень усердно работаете над реализацией функции, а вскоре после этого кто-то приходит и не нравится какой-то аспект или он не понимает его, и переписывает всё.</p><p>Так что, если вы следуете некоторым из вещей, которые я собираюсь поделиться с вами сегодня, я думаю, это действительно увеличит срок службы вашего кода. И это действительно будет намного ценнее для вашей компании, потому что я думаю, что одна из самых больших потерь времени во многих программных проектах – это переписывание кода, который уже работает, просто чтобы удовлетворить чьи-то предпочтения, когда на самом деле нет реальной причины для рефакторинга, которая действительно добавляет ценность проекту.</p><h2>Как писать код как настоящий senior</h2><p>Так какие привычки вы можете внедрить, чтобы писать код как настоящий старший программист? Я думаю, первая привычка, которую вы можете внедрить, – это завершение работы перед переходом к следующей.</p><p>На многих проектах огромное давление, особенно если вы используете скрам или что-то в этом роде, сказать, что вы закончили работу и знать, что, хорошо, я на 85% готов, но осталась небольшая часть кода, и я просто оставлю это на будущее время, я вернусь и исправлю, но по крайней мере, по моему опыту после многих проектов, когда я это делаю, я фактически накапливаю технический долг для себя.</p><p>Теперь, никто другой может не видеть этого. Я могу быть единственным человеком в команде, который об этом знает, но в конечном итоге он там, и кто-то другой это заметит. И часто, когда я сообщаю о статусе менеджерам проекта о том, над чем я работаю, мне нужно быть действительно честным, если я хочу быть действительно профессиональным, и сказать: нет, я не закончил эту задачу. И если остальная часть команды или руководство раздражены, я предпочел бы, чтобы они были раздражены и знали реальное состояние проекта.</p><p>Чем просто лгать им и говорить, что я закончил что-то. Таким образом, иметь самодисциплину действительно смотреть на свой код, как на свой личный бренд. Скотт Нимрод говорил об этом в первом интервью, которое я сделал с ним. Я думал, что это такой отличный момент, что каждый раз, когда мы пишем код, кто-то другой будет смотреть на него в будущем и, в основном, они будут оценивать нас исходя из этого кода.</p><p>Так что иметь некоторую гордость и убедиться, что вы действительно заканчиваете это перед тем, как перейти к следующему, честно, одна из первых вещей, которые вы можете сделать, если вы действительно хотите быть воспринятыми всерьез. Во-вторых, что я вижу, что настоящие старшие программисты делают, – это соблюдение стандартов кодирования.</p><p>К счастью, сегодня у нас есть такие возможности, которых не было 15 лет назад. Если вы используете VS Code или что-то подобное, знаете, что Emacs и Vim и некоторые другие инструменты тоже могут это делать. В большинстве языков есть автоформатирование, поэтому вы пишете свой код, если решите поставить переносы строк и фигурные скобки в разных местах, после сохранения файла он автоматически форматируется в одинаковом стиле.</p><p>Но если у вас нет чего-то подобного, то можно найти сторонний инструмент, если вы используете Visual Studio или тяжелую среду разработки с большим количеством функций. Для этого существуют плагины, которые позволяют выполнять форматирование кода и устанавливать его для вашей команды. Но одни из самых раздражающих кодовых баз, над которыми мне приходилось работать, были те, где у каждого был совершенно разный стандарт форматирования кода.</p><p>Иногда, особенно как консультант, когда я присоединяюсь к существующему проекту, который мне поручают проверить, легко определить, что код написали разные разработчики. И чрезвычайно раздражает читать разные стили кода, когда, честно говоря, у нас уже есть технологии для этого. Тем не менее, я считаю, что имеет смысл написать тему вики или иметь файл в формате Markdown или что-то подобное, куда команда сможет легко получить доступ, где будет описан наш стандарт кодирования.</p><h2>Используйте стандарты</h2><p>И если вы просто используете стандарт, установленный сообществом с открытым исходным кодом или что-то подобное, то это еще проще, потому что вы можете просто сказать, что мы используем этот стандарт, и дать ссылку на этот стандарт для ознакомления.</p><p>Еще одна вещь, которая, я считаю, поможет вам писать действительно высококвалифицированный код, – это быть более дисциплинированным в документировании паттернов. Я вижу много команд, которые начинают новый программный проект. Они обсуждают среди себя, выбирают набор паттернов.</p><p>Некоторые из них просто открытые и очень известные паттерны, а некоторые – нет. Но особенно на проекте React или что-то подобное, где вы используете React только для рендеринга страницы, и есть множество других библиотек и различных паттернов, из которых можно выбирать. Иметь хотя бы одну тему вики или файл в формате Markdown, который говорит, вот все паттерны, на которые мы договорились использовать в проекте, я считаю, действительно ценно, потому что таким образом, если вы проводите код-ревью или что-то подобное, и вы обнаруживаете, что разработчик в вашей команде использует какой-то другой паттерн, это не просто произвольное решение, где вы говорите: “Мы выбрали этот паттерн, но не рассказали вам об этом”.</p><p>Вы можете сказать: “Эй, помните, когда вы присоединились к проекту, мы показали вам эту страницу со всеми паттернами, и этот мы не согласовали”. Если вы используете готовый паттерн, который уже является частью фреймворка или языка, который вы используете, я считаю, что очень хорошей идеей будет просто включить ссылку на документацию где-то онлайн, которая хотя бы имеет учебник или объясняет, как использовать этот паттерн, чтобы облегчить задачу вашей команде, чтобы им не приходилось искать пример, который может не соответствовать тому, что вы хотите, чтобы они рассматривали для уже существующего паттерна.</p><p>Теперь, если у вас есть новый паттерн, который вы создали, чтобы сделать код более сухим или, в общем, чтобы упростить его написание, я часто вижу, что люди представляют паттерн, проводят презентацию или собрание в Slack, и показывают его команде разработчиков, и это последний раз, когда они об этом говорят. Я считаю, что для каждого нового паттерна, для которого существует документация, необходимо создать тему вики или статью в формате Markdown или что-то подобное, которая говорит: “Вот цель этого паттерна. Вот когда его следует использовать. Вот когда не следует использовать.</p><p>И вот несколько примеров фрагментов кода, которые покажут вам, как его действительно применять в некоторых общих сценариях. Как консультант, я скажу вам, что одна из вещей, которую мои клиенты действительно ценят во мне, – это то, что я очень дисциплинирован в отношении моей документации. Я просто нахожу, что замечательно в том, что другие разработчики в моей команде, особенно когда я прихожу и помните, я консультант, я не часть их компании, любят работать со мной, потому что у них есть все эти темы, к которым можно обратиться. Я действительно дисциплинирован в этом.</p><p>Так что, если вы действительно хотите быть воспринятым как старший программист, к сожалению, многие вещи, в которые мы убедили себя, что не очень важны, такие как самодокументирующийся код, вам действительно нужно отказаться от этого и на самом деле иметь зрелость и профессионализм, чтобы действительно отойти назад и потратить время на документирование паттернов и решений, которые вы приняли в своем проекте.</p><h2>Следите за обновлениями паттернов</h2><p>Еще одна вещь, которая действительно поможет вам работать с другими разработчиками, как это делал бы настоящий старший программист, – это просматривать любой новый паттерн, который вы вводите в проект, сразу после его введения. Я бы предложил, если вы собираетесь сделать что-то подобное, изменить паттерн или ввести новый паттерн, добавьте в проект достаточно кода, чтобы продемонстрировать его, а затем обсудите это с вашей командой, покажите им, попросите обратной связи. Они, вероятно, будут иметь свое мнение о том, как вы могли бы сделать это еще лучше. И тогда вы сможете получить одобрение от всех, и они будут на самом деле поддерживать это. И вы можете привлечь всех остальных разработчиков в вашей команде, чтобы помочь вам постепенно добавить этот паттерн в код, вместо того чтобы все делать самому.</p><h2>Проводите постепенный рефакторинг</h2><p>Еще одна вещь, которую вы можете сделать, чтобы действительно помочь вам писать код, как это делают настоящие старшие программисты, с которыми я работал, – никогда не создавайте пользовательскую историю или задачу, представляющую рефакторинг.</p><p>Почему я говорю это? Ну, все, что вы вводите как отдельный элемент, который ваше руководство может увидеть, – это что-то, что они могут убрать. И я просто считаю, что внедрение качества в код – это что-то, за что мы, как разработчики, должны взять на себя ответственность. И как профессионалы, нам действительно нужно предотвратить наше руководство от принятия плохих решений, которые могут уничтожить их проект, будь то технический долг или просто невыполнение вещей, которые можно было бы расширить по мере развития проекта.</p><p>Поэтому, когда я нахожусь в проекте и понимаю, что нужно провести рефакторинг, я никогда не создаю задачу или пользовательскую историю или оцениваю усилия по рефакторингу. Вместо этого я обсуждаю это с остальными разработчиками, и мы разрабатываем план по тому, как распределить это усилие по команде, чтобы мы могли постепенно провести рефакторинг.</p><p>Теперь, пошаговый рефакторинг – это действительно ценный навык. И я встречаю много разработчиков, которые не знают, как это делать. Они смотрят на это так, будто, хорошо, если мы собираемся изменить, скажем, паттерн базы данных, или мы собираемся изменить способ управления состоянием в React, мы собираемся использовать Redux или что-то в этом роде, – теперь нам нужно взять две недели или месяц и провести рефакторинг всего кода для этого.</p><p>Гораздо умнее просто решить в команде разработки, что каждый раз, когда мы получаем функцию, мы в основном добавляем некоторое время, чтобы создать эту новую функцию, используя новый паттерн, и мы также возвращаемся к одной или двум другим функциям и обновляем их, чтобы использовать этот новый паттерн, на который мы договорились.</p><p>Главное – не называть это отдельным элементом, потому что снова руководство будет искушено убрать это, и я считаю, что как профессионалы мы не можем позволить этому произойти.</p><h2>Выделяйте дополнительное время на задачи</h2><p>И последнее, что, я считаю, действительно поможет вам писать код, как это делают настоящие старшие программисты, и я люблю, когда люди делают это в моих командах, – в любое время, когда вас просят оценить работу, вам нужно добавить дополнительное время на непредвиденные проектировочные встречи и документацию, которую вам, возможно, придется написать.</p><p>Так часто, когда я нахожусь в проектах, я пишу код, начинаю реализовывать функцию, и выясняется, что здесь есть некоторая неопределенность. И чтобы соответствовать требованиям, теперь мне нужно добавить новую документацию.</p><p>И самое худшее – приходится вернуться к менеджеру проекта или скрам-мастеру и сказать: “Эй, мне нужно добавить новую пользовательскую историю для этого нового документа, который мне нужно написать.”  Я имею в виду, вы почти гарантируете, что вас будут микроменеджить, если вы делаете такие вещи.</p><p>Поэтому я всегда говорю людям, давайте себе дополнительное время, не только для встреч и неопределенности, но и для написания документации.</p><p>Если вы действительно хотите поддерживать высокое качество кода и сохранить команду максимально продуктивной, вам нужно защищать свои обязательства дополнительным временем, которое требуется для написания действительно отличного профессионального кода.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как я пытался писать красивый код</title>
      <link>https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod</link>
      <comments>https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Intergalactic]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod</guid>
      <description><![CDATA[<p>Недавно прошёл конкурс красоты кода. Участие по направлению Android в этом конкурсе было интересным опытом, которым я поделюсь в статье.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod">Как я пытался писать красивый код</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 05 Oct 2023 10:08:06 GMT</pubDate>
      <content:encoded><![CDATA[<p>Недавно прошёл конкурс красоты кода. Участие по направлению Android в этом конкурсе было интересным опытом, которым я поделюсь в статье.</p><p>Содержание:</p><ul><li><a href="https://tproger.ru/#one">О конкурсе</a></li><li><a href="https://tproger.ru/#two">Задание по направлению Android</a></li><li><a href="https://tproger.ru/#three">Моё решение</a></li><li><a href="https://tproger.ru/#four">Решение ChatGPT</a></li><li><a href="https://tproger.ru/#five">Звонок другу</a></li><li><a href="https://tproger.ru/#six">Комментарий победителя в номинации «Изящный код» и его решение</a></li></ul><h2>О конкурсе</h2><blockquote>Компьютерный код может написать любой разработчик. Красивый код пишут лишь единицы. Чистый, изящный, лаконичный, читаемый и понятный код, который работает без багов — это настоящее произведение искусства в сфере разработки.</blockquote><p>Для участников стояла задача написать красивый код по одному из пяти направлений (Python, Java, Data Science, Front-end, Android).</p><p>Каждое направление предусматривало 3 номинации:</p><ul><li>Краса кода — решение, признанное максимально эффективным по мнению жюри;</li><li>Изящный код — самое лаконичное решение, соответствующее поставленной задаче;</li><li>Звезда кода — самое неординарное решение по общей оценке жюри.</li></ul><p>Призы конкурса: iPhone 14, умная колонка и приглашение на вечеринку в честь Дня программиста.</p><h2>Задание по направлению Android</h2><p>Вводные данные:</p><h2>Моё решение</h2><p>Итак, нам нужно вывести список категорий и характеристик. При этом элементы в списке должны находиться разные типы элементов: категория, характеристика, концевик категории (её ID).</p><p>Первое, что пришло на ум — List. Это плохое решение, ведь так в этот список можно положить вообще всё, что угодно.</p><p>Я посмотрел, что объединяет входные дата-классы. Воспользовавшись nullable-свойствами, я создал общий дата-класс. В названии его я буквально написал, что он содержит.</p><p>Объекты этого класса будут наполнять результирующий список.</p><p>Дальше ничего не интересного: я просто воспользовался вложенными циклами.</p><p>С помощью именованных аргументов конструктора класса, в список сначала добавляется категория, потом все соответствующие характеристики, затем ID категории. Такое довольно простое решение.</p><p>Небольшая оптимизация:</p><p>В данном случае после добавления характеристики (feature) в итоговый список (categoriesWithFeatures), она удаляется из списка характеристик (mutableFeatures), поэтому следующая итерация цикла пройдёт быстрее, так как в списке будет меньше элементов.</p><p>Однако в данном случае необходимо создавать mutableFeatures (изменяемый дупликат списка features), что может быть неэффективно по памяти, если начальный список достаточно большой.</p><p>Эта оптимизация подходила бы, если входная функция возвращала изменяемый список:</p><p>После участия в конкурсе я нашёл конструкции языка и методы, которые позволяют улучшить код. Например, вместо моего дата-класса больше подошёл бы Sealed Class с тремя потомками: Категорией, Характеристикой и ID категории.</p><h2>Решение ChatGPT</h2><p>Я попросил ChatGPT решить поставленную задачу, и вот что он написал:</p><p>Моё решение лучше этого, потому что оно, как минимум, работает. Ура, моё решение лучше решения ChatGPT, плюс самооценка!</p><p>Что же делает наш умный товарищ:</p><ul><li>Пытается добавить элемент к неизменяемому списку (currentCategory?.features?.add(feature));</li><li>Пишет комментарии в решении, которое должно читаться без комментариев.</li></ul><p>Хорошо, давайте закроем на это глаза. Закрыли, но решение всё ещё плохое: оно не соответствует поставленной задаче:</p><ul><li>Основная функция в итоге возвращает список объектов CategoryWithFeatures. Этот класс содержит данные категории и список характеристик. Всё это он запихал в один класс. Теперь нет отдельных элементов категории, характеристики и ID категории, которые должны быть в результирующем списке по условию задачи.</li><li>Его цикл работает только, если во входных данных характеристики идут строго по порядку: сначала характеристики одной категории, потом другой. В противном случае в цикле создаются дубликаты категорий.</li></ul><p>Вот, что мы в итоге получаем:</p><figure><img src="https://media.tproger.ru/user-uploads/73470/2023-10-04/5e041999-6656-43ee-990c-fd8869c18180.jpeg" alt="" /><figcaption>Входные и выходные данные, дублирование категорий</figcaption></figure><p>Я также показал своё решение chatGPT и попросил его улучшить. Вот его версия моего решения:</p><p>Мой дата-класс он оставил без изменений и поменял саму функцию. Теперь сначала с помощью функции groupBy создаётся Map&gt;, где ключи — ID категории, значения — списки характеристик. Потом всё те же вложенные циклы, только теперь нужные характеристики не нужно искать, а просто брать из созданного Map.</p><p>В итоге:</p><ul><li>Результат работы такой же;</li><li>Вложенные циклы остались;</li><li>Перед вложенными циклами появились: ещё один цикл от функции groupBy и дополнительная переменная;</li><li>Код стал короче, но, как по мне, его читаемость не изменилась.</li></ul><h2>Звонок другу</h2><p>Не получив фидбека от организаторов конкурса, я попросил его у друга. Вместе с фидбеком я получил ещё один вариант решения:</p><blockquote>Я попытался переписать код, но в итоге сложность по времени получилась такая же. Пока что не придумал другого варианта.</blockquote><p>Действительно, во втором цикле из-за функции addAll (которая циклически добавляет все элементы списка featuresFromMap) у нас снова получаются вложенные циклы. При этом читаемость кода снизилась.</p><p>К слову, весь первый цикл делает почти то же самое, что и функция groupBy. Разница в том, что groupBy вернёт Map&gt;, а цикл — MutableMap&gt;.</p><blockquote>Мне не нравится моя мапа на самом деле. Я добавил список не фичей, а этого класса только из-за того, что не хотел дополнительно забивать память потом. Хотя мб я, кстати, неправильно посчитал, и такой вариант ничем не отличается. Короче, в промышленном коде так делать не стоит.</blockquote><h2>Комментарий победителя конкурса и его решение</h2><p>Давид Жубрёв, победитель в номинации «Изящный код», разрешил опубликовать его решение:</p><p>Рассмотрим, что здесь происходит. Метод flatMap в соответствии с лямбда-функцией преобразует каждый элемент списка категорий в List, где первый элемент — объект категории. Список характеристик фильтруется по ID категории и преобразовывается в массив. С помощью оператора * каждый элемент массива вкладывается в упомянутый List. Последний элемент List — ID категории.<br />После этого flatMap избавляется от вложенных списков и возвращает одномерный список всех элементов.</p><p>Хоть в результате и получается List, решение очень лаконичное и понятное, что идеально соответствует номинации. По временной сложности всё остаётся так же, но выглядит лучше. Если добавить сюда другую структуру данных, например, тот же Sealed Class, то будет, возможно, лучшее решение поставленной задачи.</p><p>Победитель прокомментировал конкурс и своё участие в нём:</p><blockquote>Я не возлагал больших надежд на победу, для меня это был, скорее, небольшой фан. Я был очень удивлен, когда мне написали о победе, но было крайне приятно)</blockquote><p>Спасибо за прочтение данной статьи! Буду рад узнать ваше мнение о конкурсе и представленных решениях ?</p>]]></content:encoded>
    </item>
    <item>
      <title>10 фишек Python, которые поднимут ваш скилл на новый уровень</title>
      <link>https://tproger.ru/articles/tryuki-python-kotorye-podnimut-tvoj-skill-na-novyj-uroven</link>
      <comments>https://tproger.ru/articles/tryuki-python-kotorye-podnimut-tvoj-skill-na-novyj-uroven?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Лена Капаца]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/tryuki-python-kotorye-podnimut-tvoj-skill-na-novyj-uroven</guid>
      <description><![CDATA[<p>Составили подборку из 10 фишек языка Python, которые упростят разработку, но о которых вы могли не слышать.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/tryuki-python-kotorye-podnimut-tvoj-skill-na-novyj-uroven">10 фишек Python, которые поднимут ваш скилл на новый уровень</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Обучение программированию]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 19 May 2023 12:10:33 GMT</pubDate>
      <content:encoded><![CDATA[<p>Когда-то на первых курсах по программированию нас в игривой манере сталкивали лбами: кто напишет код короче? И самые азартные принимались соревноваться за лаконичность сниппета. Выиграть у одногруппника было бодрящим чувством.</p><p>Борьба же за самый короткий код на проде обретает новый смысл. Чем меньше символов разработчику поглощать, тем больше выработка к концу дня, тем быстрее исполняется задача.</p><p>Моей первой группе Python точно показывали такие фишки. Но использовать сразу удалось не все, потому забылись они легко и непринужденно. Лишь спустя несколько лет к ним возвращаешься с энтузиазмом: «А действительно ли будет короче? Запомню ли теперь, когда есть зачем?»</p><p>Создатели языка ради таких фичей потратили сотни часов. Все, чтобы ваш код стал качественнее.</p><p>Заблаговременно привожу аналог термина на английском, чтобы упростить ваш гуглинг.</p><h2>Генераторы списков (List Comprehension)</h2><p><b></b>Для создания нового списка, где к каждому элементу применена функция. Это обеспечивает читаемость и отрабатывается компилятором быстрее.</p><h2>Перечисления (Enumeration)</h2><p><b></b>Используйте enumerate() для перебора списка как с индексом, так и со значением. Это элегантный способ отслеживать индекс того или иного элемента, не просто его значение.</p><h2>Лямбда-функции (Lambda Functions)</h2><p><b></b>Создавайте небольшие анонимные функции с ключевым словом lambda. Лямбды просто созданы для того, чтобы их использовали в функциях высшего порядка в качестве аргумента. Это, безусловно, позволяет добиться более короткого кода.</p><h2>Множественное назначение (Multiple Assignment)</h2><p><b></b>Назначьте несколько переменных в одной строке, используя распаковку кортежа. Это невероятно удобный способ разложить любой сложный объект на независимые переменные.</p><h2>Извлечение части списка (Slicing)</h2><p><b></b>Используйте извлечение части списка – слайсинг с указанием индексов начального и конечного элементов. Вместо того, чтобы создавать копию my_list, в примере ниже мы напрямую обращаемся к этому объекту. Это рациональное расходование памяти, и на больших объемах данных вы точно оцените эту фичу.</p><h2>Включение (Dictionary Comprehension)</h2><p>Позволит лаконично сгенерировать словари в сравнении с той же for loop, занимающей как минимум две строки.</p><h2>«Моржовый» оператор (Walrus Operator)</h2><p><b></b>:= присвоит значение переменной как части выражения.</p><h2>F-строки (F-strings)</h2><p>Само олицетворение <i>интерполяции</i>, то есть включения переменных в строковые выводы.</p><h2>any() и all()</h2><p>Функции проверят, удовлетворяют ли элементы объекта условию.</p><p>any() принимает итерируемый объект (например, список nums) в качестве аргумента и возвращает True, если хотя бы один элемент в списке считается True. Если все элементы ложные или nums пуст, то any() возвращает значение False.</p><p>all() тоже принимает такой объект в качестве аргумента и возвращает значение True, если все элементы в нем считаются истинными, или если итерируемый объект пуст. Если там есть хотя бы один элемент, который считается False, то all() вернет False.</p><h2>zip()</h2><p>Функция создаст парные строки с именем и возрастом. Что может быть лучше, чем одновременная обработка сразу нескольких составных объектов, вроде списков? Более того, это открывает прекрасные возможности для манипуляции с данными. Вы можете, например, превратить столбцы таблицы в строки, если пожелаете.</p><p>В английском есть такой фразеологизм: ‘use it or lose it’ («применяй, а то потеряешь [этот навык]»). Пускай это будет игрушечный проект, но нейронные связи в мозгу образуются. И вскоре на митапе с парным программированием или на собеседовании вы сможете пощеголять тем или иным приемчиком.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как не допустить свалки в Django-проекте: MTV, services.py, новые приложения</title>
      <link>https://tproger.ru/articles/kak-ne-dopustit-svalki-v-django-proekte-mtv-services-py-novye-prilozheniya-239596</link>
      <comments>https://tproger.ru/articles/kak-ne-dopustit-svalki-v-django-proekte-mtv-services-py-novye-prilozheniya-239596?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Илья Осипов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ne-dopustit-svalki-v-django-proekte-mtv-services-py-novye-prilozheniya-239596</guid>
      <description><![CDATA[<p>В этом материале мы обсудим, как писать чистый код, и какие концепции и типовые ошибки превращают утончённые проекты в заросли и свалки.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ne-dopustit-svalki-v-django-proekte-mtv-services-py-novye-prilozheniya-239596">Как не допустить свалки в Django-проекте: MTV, services.py, новые приложения</a>»</p>]]></description>
      <category><![CDATA[Архитектура ПО]]></category>
      <category><![CDATA[Django]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 13 Apr 2023 13:31:38 GMT</pubDate>
      <content:encoded><![CDATA[<p>Привет! Меня зовут Илья Осипов, я методист курса программирования на Python «Девман» и больше пяти лет пишу код на этом языке. В этом материале мы обсудим концепции и типовые ошибки, которые превращают утончённые и «правильные» проекты в заросли и свалки.</p><h2>Когда вскрывается проблема</h2><p>Представьте, вы пишете проект на Django в команде из пяти человек. На старте все замотивированы «сделать хорошо», ведь это шанс сделать проект «идеальным» с самого начала. Но проходит год или два, проект обрастает парой десятков тысяч строк кода. Разрабатывать становится всё сложнее: файлы ломятся от кода, навигироваться по проекту без продвинутых инструментов из IDE просто невозможно.</p><p>В этот момент разработчики обычно говорят, что причина возрастающей сложности — рост проекта. Или грешат на «коллег-говнокодеров» / «плохой фреймворк». Хотя с ростом проекта навигация действительно естественным образом усложняется, чаще всего виноваты отнюдь не фреймворки или количество строчек, а плохие решения.</p><p><b>Основная цель фреймворка</b> — задать «фреймы», то есть «границы», в рамках которых будет работать программист. Для этого внутри Django предусмотрено множество механизмов, и многие из них описаны в документации. Некоторые — прямо в исходниках фреймворка. А какие-то детали разработчики Django не предусмотрели, и программистам приходится придумывать новые границы самостоятельно.</p><p>Зачем нужны эти границы? Разве без них не лучше?</p><p>Ответ на этот вопрос сходу поймёт любой пользователь фреймворка: не лучше. Границы пусть и создают дополнительные «препятствия», но взамен они обеспечивают понятное пространство для работы: сюда писать такой код, а сюда – вот такой, и всё будет работать. Не нужно каждый раз «изобретать велосипед» и пытаться придумать, как будет работать ваш сайт. За вас уже подумали и оставили «места для дописывания кода». Вот эти места для вашего кода — это и есть <b>фреймы</b>.</p><h2>Архитектура MTV</h2><p>Самый «высокоуровневый» фрейм в Django — это архитектурное разделение логики на Model, View и Template.</p><p><i>Да, архитектура Django называется именно MTV, а не MVT. Разработчики используют в документации именно такую аббревиатуру. По сути, архитектура почти полностью повторяет другой подход — MVC, Model-View-Controller (Модель-Представление-Контроллер).</i></p><p>Суть такая:</p><ul><li>в Model хранят данные сервиса;</li><li>View отвечает за отображение данных пользователю;</li><li>Controller отвечает за то, чтобы сообщать Model, когда пора менять данные.</li></ul><p>В Django же отошли от этой концепции и использовали архитектуру Model, View и Template. Сами разработчики Django <a href="https://docs.djangoproject.com/en/4.1/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names">пишут</a>, что не видят никакого конфликта с MVC. Model по-прежнему отвечает за хранение данных и работу с ними. View — за «отображение» данных. Просто этот слой они разделили на два: View отвечает за то, чтобы решить, какие данные отображать, а Template — как отображать. Куда делся Controller из MVC? В аббревиатуре MTV он пропал.</p><p>Разработчики считают, что это сам фреймворк.</p><p>Возможно, вы хотите спросить, зачем я об этом рассказываю. Разве возможно накосячить на этом уровне? Вообще-то, да.</p><h2>Бизнес-логика, или слой Services</h2><p>Многие разработчики пытаются переизобрести MTV и добавляют в Django дополнительный слой: Services. Вы найдёте файл serivces.py во многих туториалах и видео по Django.</p><p>Необходимость добавления этого слоя обычно объясняют так:</p><ul><li>В моём проекте появились функции, которые не укладываются ни в Model, ни во View;</li><li>Я хочу сделать «бизнес-логику» реюзабельной между приложениями, и, чтобы не импортировать функции из одного View в другой, храню их отдельно.</li></ul><p>Эти проблемы действительно существуют. Зачастую в проекте появляются вспомогательные функции, которые не принадлежат стандартным сущностям Django, вроде Model или View.</p><p>Но решение складывать весь этот код в файл services.py, на мой взгляд, плохое. Вот почему:</p><p><b>Слой Services слишком широкий, это плохая рамка.</b> При определении рамок важно не определить, какой код можно класть в этот файл, а решить, какой код в этот файл класть нельзя. Для сравнения, Model хорошо справляется с этой задачей: если код не относится к работе с БД, то ему не место в файле models.py. А в services.py часто кладут всё, что не влезло в остальные.</p><p><b>Файл становится свалкой.</b> Это ожидаемое следствие плохой рамки. Я часто интересуюсь у друзей и у кандидатов на собеседованиях, есть ли в их текущих или прошлых проектах такая проблема: в services.py более 2 тысяч строк кода и по нему тяжело навигироваться. Если в проекте более 10 тысяч строчек кода, разработчики почти единогласно говорят, что файл превращается в свалку.</p><p><b>Файл размывает слой View.</b> Есть мнение, что в файл services.py нужно выносить бизнес-логику. Термин «бизнес-логика» кажется конкретным — это всё, что определяется правилами бизнеса. Но на поверку он размыт куда сильнее, чем кажется. Разработчики, глядя на функцию, иногда не могут сказать, бизнес-логика это или нет.</p><h3>Куда девать общий код?</h3><p>Альтернативное решение — оставить фреймворк в покое и не добавлять в него новый слой. Если появилась новая логика, то создать файл с говорящим названием и положить код в него. Если логики вынести нужно много — создайте несколько файлов. Искать нужную функциональность проще в одном мегафайле на тысячу строк или в пяти небольших по двести строк? Так будет куда понятнее, где, например, искать функцию, которая форматирует дату или преобразует цену товара:</p><figure><img src="https://media.tproger.ru/uploads/2023/04/61bf9f7a-76ed-4de0-b53b-b63c82ccc89f.png" alt="" /></figure><h2>Писать запросы в слое View — это нормально</h2><p>Я так и не разобрался, откуда взялся миф о том, что во View нельзя писать запросы в БД, и в чём аргументация его сторонников. Это правило просто откуда-то «взялось», и теперь в него верят как в аксиому.</p><p>Тем не менее в документации Django для слоя View очень <a href="https://docs.djangoproject.com/en/4.1/topics/http/views/">простое определение</a>:</p><blockquote>The view itself contains whatever arbitrary logic is necessary to return response.</blockquote><p>Соответственно, в этом слое можно делать ORM-запросы, если это нужно для ответа. Не обязательно пытаться «прятать» этот код куда-то ещё.</p><p>Часть запросов будут нести бизнес-смысл, то есть они станут частью бизнес-логики. Иногда это будет даже не один запрос в БД, а несколько, или даже пара строк кода между ними.</p><p>По принципу MVC «Fat models, skinny controllers, simple views», большую часть такого кода стоит стараться класть в слой Model. Один из самых недооценённых, на мой взгляд, способов — <a href="https://docs.djangoproject.com/en/4.1/topics/db/managers/">переопределение QuerySet</a>. Этот способ позволяет взять здоровый запрос на 10 вызовов методов ORM и дать ему простое, бизнесовое название.</p><p>Со слоем Services получается «Skinny Models, Skinny Controllers, Fat Services». На мой взгляд, это очевидное отхождение от принципов, которые изначально закладывались в фреймворк.</p><h2>Приложения (app)</h2><p>Сейчас эпоха популярности микросервисов над монолитами. Из-за этого сама архитектура Django-монолита стигматезируется, некоторые мои знакомые даже не пытаются пилить Django-монолиты на приложения. Но ведь «монолит» не равно «свалка»! За ним всё ещё стоит ухаживать.</p><p><b>Приложения </b>— это следующий уровень абстракции в фреймворке, который тоже отвечает за разделение кода на кучки, но уже по другому признаку.</p><p>Можно представить, что MTV разделяет код на «красное», «синее» и «зелёное», а приложения — это разделение на «круглое», «квадратное» и «треугольное». Важное правило в делении логики на приложения — <a href="https://enterprisecraftsmanship.com/posts/cohesion-coupling-difference/">Cohesion and Coupling</a>. Если коротко, это о связности между приложениями: нужно добиваться состояния, когда у вас мало связей между приложениями и много внутри них.</p><p>Вот к этому нужно стремиться:</p><figure><img src="https://media.tproger.ru/uploads/2023/04/b8a91d86-4da4-4fb8-8f8e-bbbc99f3a98f-autoconverted.jpeg" alt="" /><figcaption>Картинку взял из всё той же статьи</figcaption></figure><p>Между «разделёнными группами» связей мало, почти все связи спрятались внутри групп. Кружочки одного цвета — это части кодовой базы, которые сильно связаны друг с другом.</p><p>А вот такого стоит избегать:</p><figure><img src="https://media.tproger.ru/uploads/2023/04/a1b8ddf4-03f8-4ef5-af1e-1b917466dfe2-autoconverted.jpeg" alt="" /></figure><p>В первом случае связи хороши, но связанный код разбросан между «приложениями». Придётся часто заходить в разные приложения, чтобы внести правку в логику «жёлтых кусочков кода», например.</p><p>Справа совсем всё плохо: код разделён на такие маленькие группы, что каждый кусочек кода сам по себе стал «группой». Это называется ‘Destructive decoupling’.</p><p>Чтобы не попасть в одну из ситуаций выше, логику приложения нужно <b>группировать по юзкейсам, а не по сущностям</b>. Часто эти два способа дают одинаковые результаты, но так происходит не всегда.</p><p>Когда вы группируете логику в приложения, в первую очередь смотрите, какая логика постоянно совместно используется. Переводя в идею про Cohesion and Coupling — какие из кружочков связаны большим количеством стрелочек.</p><p>Если смотреть на разделение по приложениям так, то, если потянуть за одну функцию, за ней подтянутся и другие, сильно с ней связанные. Иногда часть связей этих функций будет неожиданной, хотя будет казаться, что складывать их вместе «нелогично».</p><p>В такой ситуации советую задуматься: а почему они оказались связанными? Может, вы неправильно выбрали название для приложения и оно должно включать в себя больше.</p><p><b>Не стесняйтесь создавать новые приложения.</b></p><p>Что делать, если одна модель не помещается ни в одно из приложений? Создайте для неё отдельное!</p><p><i>А что, так можно? В целом ПРИЛОЖЕНИИ будет всего одна жалкая моделька?!</i></p><p><b>Да, можно. Даже нужно.</b></p><p>Лучше создавать приложение сразу, как только стало заметно, что оно понадобится. Ведь когда у вас наберётся много логики, разбросанной по разным приложениям, будет уже поздно.</p><p>Процесс выделения этой логики в новое приложение будет болезненным, и, делая это, вы будете задаваться вопросом: «какой м**ак раскидал эту логику по приложениям?».</p><p>Очевидно, слишком увлекаться тоже не стоит. Иначе столкнётесь с Destructive decoupling. Но и бояться создания приложений не нужно.</p><h2>Файлы</h2><p>Ещё один слой разделения логики по фреймворкам — это файл. Мы касались темы файлов выше, давайте резюмируем уже сказанное:</p><ol><li>Свалка в файлах вредит навигации по проекту.</li><li>Cohesion and Coupling поможет разложить логику по файлам.</li><li>Не стесняйтесь создавать файлы, даже если кода внутри будет мало. Это поможет потом не страдать, выкорчёвывая функции из кода.</li><li>Название файла должно задавать чёткую однозначную границу, говорить о том, какому коду здесь не рады. Иначе свалки не миновать.</li></ol><p>На третьей мысли хочется остановиться подробнее. Страх создания файлов зачастую иррационален. У разработчиков редко бывает страх создания новой функции: если это нужно, вы без проблем вынесете кусок логики в новый, небольшой «контейнер» — функцию.</p><p>С файлами аналогично, это тоже контейнер для кода. Просто функции хранят в себе строчки кода, а файлы хранят в себе функции.</p><p>У ситуации «переборщили с количеством файлов» есть надёжный симптом — читая интересующий код, вы не задерживаетесь в одном файле больше, чем на 30 секунд. Всё время приходится двигаться по файлам туда-сюда. А это и есть нарушение принципа Cohesion and Coupling.</p><h2>Итоги</h2><p>Если во время чтения статьи вы успели потерять основные тезисы, то вот небольшой конспект. ?</p><ol><li>Services – не часть MTV;</li><li>Плохое название файла приведёт к свалке;</li><li>Можно писать запросы в слое View, не бойтесь этой практики;</li><li>Монолит – не повод сваливать всё в кучу;</li><li>Группировать по юзкейсам лучше, чем по сущностям;</li><li>Не стесняйтесь создавать новые файлы и приложения, даже если кода в них мало;</li><li>Разложить логику по файлам поможет Cohesion and Coupling.</li></ol>]]></content:encoded>
    </item>
    <item>
      <title>5 принципов читаемого кода: KISS, YAGNI, DRY, BDUF и Бритва Оккама</title>
      <link>https://tproger.ru/articles/5-principov-chitaemogo-koda-kiss-yagni-dry-bduf-i-britva-okkama</link>
      <comments>https://tproger.ru/articles/5-principov-chitaemogo-koda-kiss-yagni-dry-bduf-i-britva-okkama?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Сообщество IW]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/5-principov-chitaemogo-koda-kiss-yagni-dry-bduf-i-britva-okkama</guid>
      <description><![CDATA[<p>Описываем 5 принципов, которые позволят сделать ваш код чистым и читабельным: KISS, YAGNI, DRY, BDUF и Бритва Оккама.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/5-principov-chitaemogo-koda-kiss-yagni-dry-bduf-i-britva-okkama">5 принципов читаемого кода: KISS, YAGNI, DRY, BDUF и Бритва Оккама</a>»</p>]]></description>
      <category><![CDATA[Организация разработки]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Гостевая публикация]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 01 Dec 2022 09:56:11 GMT</pubDate>
      <content:encoded><![CDATA[<p>Данная статья предназначена для понимания основных принципов написания читаемого кода. Для некоторых принципов будут приведены примеры React и JavaScript.</p><p>Во многих проектах идет слепое следование SOLID принципам (которые являются <b>не менее важными!</b>), при этом нарушаются и не берутся во внимание многие другие стандарты написания кода. Не нужно впадать в крайности — необходимо соблюдать баланс. Итак, к основным принципам разработки и написания чистого когда относятся:</p><h2>KISS — Always Keep It Simple, Stupid (будь проще)</h2><ol><li>Ваши методы должны быть небольшими (40-50 строк).</li><li>Каждый метод решает одну проблему.</li><li>При модификации кода в будущем не должно возникнуть трудностей.</li><li>Система работает лучше всего, если она не усложняется без надобности.</li><li>Не устанавливайте целую библиотеку ради одной функции из неё.</li><li>Не делай того, что не просят.</li><li>Писать код необходимо надежно и «дубово».</li></ol><p>Как это можно реализовать в React? С приходом хуков основной единицей построения веб-приложения становится функциональный компонент. Например, можно создавать компоненты небольшого размера. Логику необходимо выносить во вспомогательные функции. Если это работа с использованием состояния — создавать кастомные хуки. В итоге получаем компонент небольшого размера (функция), вспомогательные функции малого размера, пользовательские хуки (так же являются функциями). Вся логика вынесена в небольшие функции, которые в дальнейшем будет удобно покрыть unit тестами.</p><p>В целом, для упрощения и сокращения кода, необходимо использовать стрелочные функции, значения для параметров функции по умолчанию, деструктуризацию, async/await синтаксис, обязательно использование блоков try/catch для надежности. Взгляните, как усложнен код ниже:</p><p>Как выглядит это проще при использовании стрелочных функции и параметров по умолчанию:</p><p>В целом, это касается не только кода. При создании архитектуры проекта, структуры директорий не изобретайте очередной велосипед. Уделите хотя бы 5 минут и поищите примеры решения, спросите у коллег, почитайте про минусы и плюсы данного подхода и выбирайте наиболее подходящий. Ниже пример очередного идеального «своего решения ? «.</p><h2>YAGNI — You are not gonna need it (Вам это не понадобится)</h2><ol><li>Реализуйте только то, что нужно здесь и сейчас, а не в теории, что оно пригодится в будущем.</li><li>Подчищайте ненужный код (найдите через Git историю при надобности).</li><li>Программист не должен добавлять новый функционал, о котором его не просят (благими намерениями без должной проверки вы только добавите багов).</li></ol><h2>DRY — Don’t Repeat Yourself (Не повторяйся)</h2><ol><li>Избегайте копирования кода.</li><li>Выносите общую логику.</li><li>Прежде чем добавлять функционал, проверьте в проекте, может, он уже создан.</li><li>Константы.</li></ol><p>В React этот принцип можно выразить через переиспользуемые компоненты. В целом, на этом и базируется принцип React. UI необходимо создавать из переиспользуемых блоков.</p><p>Создайте кнопку или поле ввода и подключайте их, где и сколько раз необходимо. В плане логики здесь конечно также на помощь приходят вспомогательные функции (утилиты или хелперы) и хуки. В примере ниже api запрос, взаимодействие с селектом, полем ввода вынесенно в отдельные хуки, которые можно в дальнейшем переиспользовать.</p><p>В целом код должен пройти через следующие стадии:</p><figure><img src="https://media.tproger.ru/uploads/2022/11/54245794-8028-483d-b3b2-378b8e14d7aa.jpeg" alt="" /></figure><p>Дополнительно можно придерживаться правил, представленных ниже.</p><h2>Бритва Оккама</h2><ol><li>Не нужно создавать лишние сущности без необходимости в них.</li><li>Всегда начинайте с максимально простого кода, затем увеличивайте сложность по мере необходимости.</li></ol><h2>BDUF — Big Design Up Front (Сначала большое проектирование)</h2><ol><li>Прежде чем переходить к реализации, убедитесь, что все продумано.</li><li>Разработчик должен сначала завершить проектирование. После этого проект можно реализовать.</li><li>Разделите требования на несколько этапов, определите приоритеты, начинайте с этапа с наивысшим приоритетом.</li><li>Обсудите архитектуру проекта с командой и другими людьми, которые участвуют в проекте до старта.</li></ol><p>Итак, выше были перечислены основные принципы написания хорошего кода. При этом важно помнить, что для каждой задачи эти принципы применяют по мере необходимости, а <b>не для того, чтобы просто применить. </b></p><p>Придерживайтесь их, и в будущем вам благодарны будете и вы сами, и ваши коллеги.</p>]]></content:encoded>
    </item>
    <item>
      <title>8 признаков плохого кода</title>
      <link>https://tproger.ru/translations/8-priznakov-plohogo-koda</link>
      <comments>https://tproger.ru/translations/8-priznakov-plohogo-koda?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Олег Борисенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/8-priznakov-plohogo-koda</guid>
      <description><![CDATA[<p>Разбираем признаки плохого кода, которые сигнализируют о необходимости рефакторинга.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/8-priznakov-plohogo-koda">8 признаков плохого кода</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 22 Jun 2021 13:50:48 GMT</pubDate>
      <content:encoded><![CDATA[<p>Порой для того, чтобы определить, что перед вами плохой код достаточно одного взгляда на него: форматирование и регистр имён сущностей сразу бросаются в глаза. В этой статье перечислены признаки, которые помогут вам понять, что перед вами действительно плохой код.</p><h2>Загадочные имена</h2><p>Одна из основных особенностей плохого кода — стратегия именования сущностей. Если в команде отсутствуют соглашения об именовании, их следует принять. С ростом приложения правильное именование становится критически важным.</p><p>Общие принципы именования помогут команде (особенно если в ней есть разработчики разного уровня) находить общий язык и лишний раз не ломать голову в попытках понять\придумать имя для переменной.</p><p>Вот принципы которые вы можете использовать:</p><ul><li>Имя должно описывать цель существования переменной:</li></ul><ul><li>Всеми силами избегайте непонимания:</li></ul><ul><li>Имена должны быть произносимыми:</li></ul><ul><li>Имя должно быть удобно искать:</li></ul><ul><li>Стратегия именования должна быть согласованной:</li></ul><h2>Огромные методы</h2><p>Слишком большие методы являются источником ошибок и сложны для понимания. Есть правило: функция должна выполнять одну задачу и выполнять её хорошо.</p><h2>Божественный объект</h2><p>Так называют огромный класс, который делает слишком много разных вещей. Класс, как и функция, должен иметь одну цель существования. Поэтому божественный объект должен быть разделён на несколько сущностей, каждая из которых имеет только одну задачу.</p><h2>Дублирующийся код</h2><p>Идентичный код, который разбросан по всему приложению. Он увеличивает сложность поддержки и тестирования системы. Повторяющиеся куски кода являются признаком того, что вам пора задуматься о рефакторинге.</p><h2>Избыток параметров</h2><p>Длинный список параметров усложняет чтение, вызов и тестирование функций. Уменьшение числа параметров позволит вам сократить время на изучение и тестирование кода.</p><h2>Неуместная сложность</h2><p>Принудительное использование чрезмерно сложных шаблонов проектирования там, где более простой архитектуры было бы достаточно.</p><p>Использование сложных паттернов без необходимости показывает не ваш скилл, а неспособность увидеть картину целиком и избежать излишней сложности.</p><h2>Хирургия дробовиком</h2><p>Термин shotgun surgery используется для случая, когда одно изменение в коде влечёт за собой множество других изменений.</p><figure><img src="https://media.tproger.ru/uploads/2021/06/Shotgun_Surgery.png" alt="" /><figcaption>Изменения в классе A требуют множества незначительных изменений в других классах</figcaption></figure><h2>Изменяемость переменных</h2><p>Код, переменные в котором изменяются непредсказуемо, сложно отлаживать и проводить рефакторинг.</p>]]></content:encoded>
    </item>
    <item>
      <title>Делаем код чище с помощью деструктуризации объектов в JavaScript</title>
      <link>https://tproger.ru/translations/delaem-kod-chishhe-s-pomoshhju-destrukturizacii-obektov-v-javascript</link>
      <comments>https://tproger.ru/translations/delaem-kod-chishhe-s-pomoshhju-destrukturizacii-obektov-v-javascript?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Олег Борисенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/delaem-kod-chishhe-s-pomoshhju-destrukturizacii-obektov-v-javascript</guid>
      <description><![CDATA[<p>Деструктуризация объектов и массивов в JavaScript уменьшает объём кода и упрощает работу с данными при написании приложений.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/delaem-kod-chishhe-s-pomoshhju-destrukturizacii-obektov-v-javascript">Делаем код чище с помощью деструктуризации объектов в JavaScript</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 17 Jun 2021 14:55:39 GMT</pubDate>
      <content:encoded><![CDATA[<p>В этой статье мы сравним традиционный подход и использование нового синтаксиса деструктуризации объектов в JavaScript стандарта <a href="https://tproger.ru/translations/wtf-is-ecmascript/">ES6</a>. Этот синтаксис позволяет распаковать значения из сложных объектов и массивов. Его можно использовать для того, чтобы сделать код чище и лаконичнее.</p><p>Сначала мы обсудим деструктуризацию объектов, а затем перейдём к массивам.</p><h2>Деструктуризация объектов в JS</h2><p>Для примера возьмём объект, содержащий простые свойства и вложенные объекты, с данными о покупателе:</p><h3>Базовое присваивание</h3><p>Традиционный подход для получения данных объекта — использовать точку или квадратные скобки:</p><p>Это можно сделать одной строкой кода:</p><p>Мы также можем изменить имя переменной:</p><h3>Присваивание объявленным переменным</h3><p>Для этого нужно использовать круглые скобки:</p><p>Круглые скобки в данном случае нужны потому, что { слева воспринимается как блок, а не литерал объекта. Без скобок мы получим ошибку:</p><h3>Вложенные объекты</h3><p>Мы можем получать вложенные свойства по одному:</p><p>С помощью деструктуризации объекта в JS этот код можно записать в одну строку:</p><h3>Деструктуризация со значениями по умолчанию</h3><p>Допустим, у объекта customer есть булево поле married, которое может не иметь значения. Без деструктуризации проверка на наличие значения может выглядеть так:</p><p>С помощью деструктуризации можно сделать это в одну строку:</p><h3>Оставшиеся параметры</h3><p>С помощью многоточия и любого имени переменной мы можем получить оставшиеся параметры, которые не были указаны. Для них обычно используют имя rest:</p><h3>Обработка null-объектов</h3><p>Если мы попытаемся деструктурировать <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/null">null-объект</a>, то получим ошибку. Этого можно избежать:</p><p>С помощью оператора ИЛИ мы заменили null пустым объектом.</p><h3>Деструктуризация аргументов функции</h3><p>Мы можем деструктурировать объекты, переданные в функцию. Сначала посмотрим, как это работает без деструктуризации:</p><p>А так выглядит деструктуризация параметров функции:</p><h2>Деструктуризация массивов в JS</h2><p>Синтаксис, который мы использовали для деструктуризации объектов, можно применять и к массивам. Кроме того, деструктуризация массивов имеет интересные особенности. Для их демонстрации будем использовать массив фруктов:</p><p>Доступ к элементам массива через деструктуризацию будет выглядеть так:</p><h3>Пропуск и получение остальных элементов</h3><p>Чтобы пропустить ненужный элемент массива используется запятая:</p><h3>Деструктуризация в JS с заменой элементов</h3>]]></content:encoded>
    </item>
    <item>
      <title>Точка с запятой в JavaScript/TypeScript: за и против</title>
      <link>https://tproger.ru/articles/tochka-s-zapjatoj-v-javascript-typescript-za-i-protiv</link>
      <comments>https://tproger.ru/articles/tochka-s-zapjatoj-v-javascript-typescript-za-i-protiv?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Олег Борисенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/tochka-s-zapjatoj-v-javascript-typescript-za-i-protiv</guid>
      <description><![CDATA[<p>Автоматическая вставка точки с запятой работает не всегда, и её пропуск в отдельных случаях приводит к неожиданным ошибкам выполнения.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/tochka-s-zapjatoj-v-javascript-typescript-za-i-protiv">Точка с запятой в JavaScript/TypeScript: за и против</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 18 Mar 2021 08:50:29 GMT</pubDate>
      <content:encoded><![CDATA[<p>Необходимость использования точки запятой в JavaScript и ему подобных языках это предмет горячих обсуждений. В этой статье я попытаюсь разобрать все плюсы и минусы использования точки с запятой.</p><h2>ASI (Автоматическая вставка точки с запятой)</h2><p>Использование точки с запятой в JavaScript необязательно благодаря существованию ASI. TypeScript также использует ASI. Однако, ASI не всегда отрабатывает правильно, и есть несколько ситуаций, когда пропуск точки с запятой приведет к неожиданной ошибке выполнения.</p><p>В JavaScript есть несколько тупиковых случаев, которые устраняются системой типов TypeScript. Например:</p><p>Массив цветов будет интерпретирован как выражение с запятой. В JS это вызовет ошибку времени выполнения — «Uncaught TypeError: Cannot read property ‘blue’ of undefined”». В TS ошибка произойдет ещё на стадии компиляции — «Left side of comma operator is unused and has no side effects».</p><p>Есть ещё один подобный пример. В этом случае ошибка возникнет в обоих языках только во время выполнения:</p><p>Если вы пользуетесь линтером, то флаг no-unexpected-multiline позволит обнаружить такие ошибки на этапе компиляции.</p><h2>Причины использовать точку с запятой</h2><ul><li>Привычка — зачем что-то менять, если и так всё устраивает.</li><li>Разные языки программирования — проще придерживаться схожих принципов на разных языках.</li><li>Читаемость — это дело вкуса.</li><li>Избавление от неоднозначностей.</li><li>Нежелание пользоваться линтером.</li></ul><h2>Причины не использовать точку с запятой</h2><ul><li>Лишний символ — экономия времени и места.</li><li>Код становится чище.</li><li>Легче попадать мышью в конец строки.</li><li><a href="https://eslint.org/">Линтер</a> — позволяет выявлять ошибки на стадии компиляции.</li><li>Новичкам проще не отвлекаться на точку с запятой.</li><li>Больше никаких warning`ов об отсутствии точки с запятой (особенно при переходе с языка, который их не использует).</li><li>Использование точки с запятой в JavaScript и TypeScript полностью не избавляет от неоднозначных ситуаций.</li></ul><p>Читайте нашу статью о том, <a href="https://tproger.ru/translations/setting-up-eslint-and-prettier/">как пользоваться линтером и другими подобными средствами</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>10 принципов хорошего кода и хорошего программиста</title>
      <link>https://tproger.ru/translations/10-principov-horoshego-koda-i-horoshego-programmista</link>
      <comments>https://tproger.ru/translations/10-principov-horoshego-koda-i-horoshego-programmista?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Мария Кривоченко]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/10-principov-horoshego-koda-i-horoshego-programmista</guid>
      <description><![CDATA[<p>Спагетти-код, длинные цепочки if-else и функции на сотни строк мешают поддержке — принципы написания ремонтопригодного и понятного кода.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/10-principov-horoshego-koda-i-horoshego-programmista">10 принципов хорошего кода и хорошего программиста</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 05 Jan 2021 13:06:51 GMT</pubDate>
      <content:encoded><![CDATA[<p>Спагетти-коды, огромные цепочки «if-else» и программы, которые ломаются после изменения переменной, функции размером в сотни строк и раздражающие имена переменных и классов? Это лишь некоторые из постоянно встречающихся в работе недочётов. И результат того, что будет, если попытаться превратить надвигающийся дедлайн в готовый продукт, внутри которого скрывается проблемный и перегруженный код.</p><p>Попробуем написать код, думая о его ремонтопригодности, а не только о том, чтобы он «работал!». Код, который поймёт и сможет поддерживать любой (разумеется любой, кто знаком с программированием). Будем следовать 10 принципам хорошего программиста, которые выведут вашу работу на новый уровень!</p><h2>KISS</h2><p>KISS расшифровывается как «чем проще — тем лучше». Этот принцип стоит использовать для решения разных жизненных задач, и он очень помогает в написании кода.</p><p>Например, вы собираетесь <a href="https://tproger.ru/articles/6-advices-about-userexperience/">разработать мобильную игру</a> — и у вас появился шанс это сделать. Не факт, что вы создадите следующую Candy Crush или Clash Royale. Поэтому постарайтесь оставить проект маленьким и простым. А если он уже прост — сделайте его ещё проще. Дополнительные функции появятся, когда вы сделаете стабильно работающую базу.  Впрочем, можете не придерживаться этого правила, перегрузить софт функциями и «взорвать» весь проект.</p><p>Во время работы старайтесь сделать код простым, потому что сложный быстро становится трудоёмким. Чем больше времени вы тратите на одну программу — тем больше багов и ошибок получите. И в конечном итоге это приведёт к трудностям, если вы захотите изменить что-то в проекте позже.</p><h2>DRY</h2><p>DRY означает «не повторяйся», и это следует понимать буквально. Если ваш код повторяется и повторяет одни действия, вы нарушаете это правило. Несколько функций делают одно и то же? Рефакторинг в одну функцию. Содержат ли несколько переменных одни и те же данные? Рефакторинг в одну переменную.</p><p>Против принципа DRY выступает WET: «пиши всё дважды» или «потрать время зря». Основной вопрос для определения нарушителей правил заключается в следующем: сколько мест необходимо изменить, чтобы пофиксить программу? Если ваш ответ «больше одного», значит, вы действовали вопреки принципу DRY.</p><p>Представьте, что вы разрабатываете музыкальное приложение с тремя страницами: альбомы, названия и плейлисты. Для каждой из этих страниц существует собственный класс, а для каждого класса — своя функция «fetchMusic= ()». Так почему же в коде есть три места, которые ведут себя одинаково? Извлеките эту функцию и не действуйте против принципа DRY.</p><h2>Открытый/Закрытый</h2><p>Этот принцип хорошего программиста означает, что уже реализованные логические функции должны оставаться таковыми, и их нет смысла переписывать. В то же время новые требования или элементы можно добавлять к существующим классам, и расширять эти самые классы, а не менять. Так что они «открыты» для расширений, но «закрыты» для модификаций.</p><p>Это — ключ к созданию хорошего API, особенно если вы хотите выпустить библиотеку. Не соблюдайте этот принцип, и пользователи будут использовать вашу библиотеку «как есть», либо не использовать её вообще. И если вы захотите дать им возможность расширять её, они смогут менять ваш код в соответствии со своими потребностями. Вряд ли это то, чего вы добивались.</p><p>Если во время основного релиза кто-то серьёзно модифицирует код, требуется слияние всех изменений. Это занимает много времени и может привести к появлению багов. Не говоря уже о том, что те, кто переписывал код, наделают своих ошибок. Следование принципу «открытый/закрытый» защищает ваш софт от таких проблем, потому что простые расширения не могут взломать ни один существующий код.</p><h2>Построение, а не наследование</h2><p>Это означает, что поведение программ надо прописывать, а не брать со стороны. Почему? Потому что по мере роста древо наследования становится всё более запутанным, и каждая его «ветвь» получает свой собственный набор поведений. И попытки перенести модель поведения из одной «ветви» в другую могут оказаться трудными.</p><p>Прописанное с нуля поведение легче обрабатывать и поддерживать. Таким образом, также можно производить бесконечное количество моделей поведения. И из каждой комбинации можно получить свой класс.</p><p>Одним из примеров могут быть враги в видеоигре. На первом уровне они могут только бить. На следующем уровне — бить и пинать или бить и плеваться, но не пинать. Или плевать ядом и бить ногами, но не кулаком. Теперь представьте себе, что этот набор навыков растёт для каждого уровня. Попробуйте нарисовать дерево наследования, и вы скоро увидите, что построение с нуля гораздо удобнее.</p><h2>Отдельная ответственность</h2><p>Этот принцип хорошего программиста гласит, что каждый класс должен заботиться о предоставлении только одного бита.</p><p>Если вы придерживаетесь принципа KISS или у вашего проекта мало фишек, то большинство классов просто и без ошибок выполняют один тип работы за раз. Но с ростом требований к коду и приближением дедлайна большинство классов начинают делать по несколько вещей и нарушают этот принцип.</p><p>Чтобы придерживаться пятого правила, задайте себе вопрос, где и когда меняется каждая функция? Если ответ будет «более чем в одном месте и более чем по одной причине», вы нарушаете этот принцип.</p><h2>Разделение задач</h2><p>Этот принцип похож на предыдущий, но его стоит рассматривать на более высоком уровне абстракции. Программа состоит из нескольких частей, которые в лучшем случае не связаны друг с другом.</p><p>Хорошо известен пример MVVM-Pattern (Модель, Представление и Модель представления), где приложение разбивается на три не пересекающихся части. Модель данных содержит необработанные данные и выполняет некоторый алгоритм. Модель представления содержит агрегированные данные, которые должны отображаться, но не знает, как отобразить их. А Представление отображает эти данные наилучшим образом. Кроме того, только у него есть возможность взаимодействовать с пользователем и реагировать на него напрямую.</p><p>Таким образом, Модель представления и Модель не знают, на какую кнопку или область нажал пользователь. Представление обрабатывает действия человека и доставляет данные в Модель представления, которая выполняет собственные алгоритмы, не контактируя с пользователем. Это даёт возможность создавать модульные коды и параллельно разрабатывать каждую его часть.</p><h2>YAGNI</h2><p>Принцип хорошего программиста «Тебе это не нужно» хочет, чтобы вы не прописывали функции, которые могут и не понадобиться в будущем. Потому что велика вероятность, что они вам вообще не понадобятся. Зато усложнят код.</p><p>Можете рассматривать это как строгое соблюдение принципов DRY и KISS. В основном его нарушают неопытные разработчики. Они пишут очень абстрактный код и в итоге получают нечто раздутое и невозможное в использовании.</p><h2>Избегайте преждевременной оптимизации</h2><p>Смотрите на это как на противоположность принципа YAGNI. Первый призван, чтобы избежать реализации ненужных фрагментов кода, второй нужен, чтобы предотвратить слишком раннюю оптимизацию.</p><p>Вы не можете обнаружить недоработку, пока она не обнаружит вас! Программа должна сама показать вам «узкое место», потому что вы не найдете его, изучая код самостоятельно.</p><h2>Рефракторинг, рефракторинг, рефракторинг</h2><p>Многие знакомы с этим принципом хорошего программиста, но принимают не все: «код редко получается совершенным с первого раза» — Роберт К. Мартин.</p><p>Лучше ещё раз просмотреть и переработать сделанное ранее, потому что это помогает убедиться в правильности кода.Это нормально, такова природа вещей.</p><p>Если же вы посмотрели на старый код и поняли, что не можете его улучшить, есть только 2 варианта:</p><ol><li>Вы настоящий мастер, и сделали всё идеально;</li><li>Вы ещё недостаточно прокачались.</li></ol><p>Я очень сомневаюсь, что кто-то может когда-либо прийти к варианту 1.</p><p>Поэтому возвращаться к старым участка кода и улучшать их — нормально. Особенно учитывая тот факт, что кодовые базы постоянно расширяются. Относитесь к этому принципу как к «правилу большого пальца» или как к рутине, но не забывайте совершенствовать свой код.</p><h2>Чистый код лучше, чем «умный» код</h2><p>Оставьте музу дома и напишите чистый код вместо шедеврального. Потому что шедевральный код — это загадка, которую будут решать ваши товарищи! Раскрою небольшой секрет: «умный код» довольно быстро станет загадкой и для вас. Никому нет дела до «умного» когда, если его невозможно прочесть.</p><p>«Умный код» делает как можно больше в одной строке вместо того, чтобы разбить всё для лучшего восприятия. Или содержит странные имена переменных/методов/классов вместо выразительных. Всё, что заставляет кого-то сказать «Подождите, что?», можно идентифицировать как «умный код».</p><p>Хороший программист пишет читаемый код и оставляет комментарии, если это действительно необходимо. Комментарии, которые объясняют, почему, а не как всё делается. Придерживайтесь руководств по стилю и пишите код, соответствующий языку.</p><p>Наконец, упомяну, что каждый разработчик программного обеспечения должен прочитать две книги, чтобы прокачать себя. Это «Чистый код» Роберта К. Мартина и «Совершенный код» Стива МакКоннелла. Прочитав их, я почувствовал себя заново рождённым в мире программирования, но сохранил опыт своей прежней жизни.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как влюбить в себя своего код-ревьюера: правила подготовки к code review</title>
      <link>https://tproger.ru/translations/kak-vljubit-v-sebja-revjuera</link>
      <comments>https://tproger.ru/translations/kak-vljubit-v-sebja-revjuera?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Олег Борисенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/kak-vljubit-v-sebja-revjuera</guid>
      <description><![CDATA[<p>Рассказываем про техники подготовки к code review, которые помогут получить от него максимальную пользу и порадуют ревьюера.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/kak-vljubit-v-sebja-revjuera">Как влюбить в себя своего код-ревьюера: правила подготовки к code review</a>»</p>]]></description>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 03 Dec 2020 12:32:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>Под подготовкой к code review обычно понимают подготовку самого код-ревьюера. Но вклад разработчика тоже важен. Однако если вы постараетесь следовать всем советам из этой статьи, ваш ревьюер может и не влюбится в вас, но будет доволен.</p><h2>Как улучшить code review?</h2><ul><li>Учитесь быстрее — правильно составляйте список изменений в коде, это поможет ревьюеру сконцетрироваться на главном и дать полезный фидбек.</li><li>Делайте других лучше — подавайте пример коллегам.</li><li>Избавьтесь от конфликтов в команде — code review это всегда споры. Относитесь к ним обдуманно и последовательно.</li></ul><p>Золотое правило: цените чужое время.</p><p>Старайтесь сами находить ошибки, это полезно для вас обоих. Относитесь к ревьюеру не как к препятствию, а как к достойному доверия союзнику.</p><h2>Техники подготовки к код ревью</h2><h3>Сделайте первое ревью самостоятельно</h3><p>Дайте коду полежать до утра, а потом попробуйте представить, что видите его в первый раз. Что в нём вас смущает? Посмотрите на изменения в том же виде, в котором их увидит ревьюер. Избегайте повторяющихся ошибок (лишний файл, остатки отладочного кода).</p><h3>Напишите понятный список изменений</h3><p>Хороший changelist объясняет, что изменилось на верхнем уровне и почему сделано это изменение. Помните, что читатель может не обладать теми же знаниями о проекте, что и вы.</p><p>Подробнее про списки изменений в статьях <a href="https://chris.beams.io/posts/git-commit/">«How to Write a Git Commit Message»</a> и <a href="https://dhwthompson.com/2019/my-favourite-git-commit">«My favourite Git commit»</a>.</p><h3>Автоматизируйте рутину</h3><p>Не тратьте время ревьюера на проверку отступов у скобок. Отправляйте код на ревью только после того, как все <a href="https://mtlynch.io/human-code-reviews-1/#let-computers-do-the-boring-parts">автотесты отработали без ошибок</a>. Используйте <a href="https://www.atlassian.com/git/tutorials/git-hooks">Git Hooks</a> для проверки кода перед отправкой.</p><h3>Пусть ваш код говорит сам за себя</h3><p>Вы можете объяснить одному человеку как работает ваш код, но лучше, чтобы код был понятен каждому. Поэтому при подготовке к код ревью попробуйте посмотреть на свой код глазами не знакомого с ним человека.</p><p>Помните, что в сложных случаях можно использовать комментарии.</p><h3>Делайте узконаправленные изменения</h3><p>Лучшая тактика — <a href="https://blog.codinghorror.com/curlys-law-do-one-thing/">одно изменение для одной проблемы</a>. В противном случае ревьюеру будет сложно понять, какие изменения служат цели А, а какие цели Б.</p><h3>Разделяйте функциональные изменения и рефакторинг</h3><p>Пара строк функциональных изменений затеряется при рефакторинге. Чтобы этого избежать, действуйте в следующем порядке:</p><ol><li>Добавьте поведенческие тесты.</li><li>Проводите рефакторинг, не изменяя код тестов.</li><li>Измените логику и обновите тесты.</li></ol><h3>Разделяйте длинные changelist’ы</h3><p>Если при подготовке к code review вы видите, что список изменений слишком разросся, подумайте о том, что нужно добавить сейчас, а с чем можно повременить.</p><h3>Адекватно воспринимайте критику</h3><p>При подготовке к code review морально настройтесь, что скорее всего вы получите в том числе негативный отклик. Лучший способ угробить code review — принять критику слишком близко к сердцу. Это особенно легко сделать, когда ревьюер формулирует фидбек <a href="https://mtlynch.io/human-code-reviews-1/#never-say-you">как личные претензии</a>.</p><p>Тем не менее, как автор вы полностью <a href="https://mtlynch.io/book-reports/7-habits-of-highly-effective-people/#habit-1-be-proactive">контролируете свою реакцию на ревью</a>. Конечно, иногда первое желание — попытаться оправдаться. Но лучше просто поблагодарить ревьюера за внимательность.</p><h3>Будьте терпеливы к ошибкам</h3><p>Иногда ревьюеры откровенно ошибаются, но это может быть индикатором того, что нужны изменения. Например, это могут быть какие-то неявные языковые особенности, которые не понятны неспециалисту.</p><h3>Отвечайте на code review</h3><p>Установите в вашей команде правила, которые помогут определить, кто сейчас работает над кодом (вы или ревьюер). Это поможет не мешать друг другу в процессе. Отвечайте на каждое замечание настолько развернуто, насколько это требуется.</p><h3>Задавайте вопросы правильно</h3><p>Если попадается непонятное замечание, спросите: «Что будет полезно изменить?». Также можно попробовать угадать намерения ревьюера и предварительно отредактировать код — это может помочь, даже если вы не совсем попали в цель.</p><h3>В неоднозначных ситуациях отдайте преимущество ревьюеру</h3><p>Некоторые вещи в коде — дело вкуса и их сложно рационально аргументировать. Однако если ревьюер что-то предлагает, подумайте, возможно, его свежий взгляд объективнее.</p><h3>Оперативно отвечайте на комментарии</h3><p>Чем дольше вы отвечаете на замечания, тем больше времени потребуется для того, чтобы вспомнить контекст (и вам, и ревьюеру). После отправки кода на code review, сделайте главным приоритетом ответ на него.</p><p>Расскажите, а как проходит ваша подготовка к код ревью? Готовитесь ли вы как-то вообще и считаете ли это необходимым?</p>]]></content:encoded>
    </item>
    <item>
      <title>Технологические гиганты объединились для избавления от неполиткорректных выражений в своём коде</title>
      <link>https://tproger.ru/news/neutral-code-style</link>
      <comments>https://tproger.ru/news/neutral-code-style?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/neutral-code-style</guid>
      <description><![CDATA[<p>Инициатива Inclusive Naming с участием IBM, Cisco, Red Hat и Linux Foundation заменит whitelist, blacklist, master и slave нейтральными словами.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/neutral-code-style">Технологические гиганты объединились для избавления от неполиткорректных выражений в своём коде</a>»</p>]]></description>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[IBM]]></category>
      <category><![CDATA[VMware]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 19 Nov 2020 14:05:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>Инициатива, названная Inclusive Naming, объединила под своим крылом IBM, Linux Foundation, Cisco, VMware, Red Hat, Akamai и Cloud Native Computing Foundation. Согласно имеющимся данным, все эти компании займутся очищением кода своих продуктов и документации от различных неполиткорректных или оскорбительных для некоторого круга лиц терминов.</p><h2>Какие именно слова под запретом?</h2><p>Список нежелательных терминов состоит из таких выражений как whitelist, blacklist, master и slave. Их предлагается заменить на более нейтральные allowlist, denylist, control plane, сontroller, doer, primary, replica, secondary, leader, follower, parent, child, main, original и source.</p><h2>Но ведь заменить придётся огромное количество кода</h2><p>Да, именно так оно и есть. Например, в списке, подготовленном компанией Red Hat, было отмечено 337 тыс упоминаний слова «master», 105 тыс раз упоминалось слово «slave», 10 тыс раз встречалось слово «whitelist» и 17 тыс — «blacklist». Для того, чтобы выявить все случаи использования неприемлемых терминов, будет разработан специальный фреймворк.</p>]]></content:encoded>
    </item>
    <item>
      <title>Стили именования переменных и функций. Используйте их все</title>
      <link>https://tproger.ru/explain/naming-variables-and-functions-use-them-all</link>
      <comments>https://tproger.ru/explain/naming-variables-and-functions-use-them-all?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Олег Борисенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/explain/naming-variables-and-functions-use-them-all</guid>
      <description><![CDATA[<p>camelCase и другие соглашения помогают понять тип сущности с первого взгляда — идеального единого формата в программировании не существует.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/explain/naming-variables-and-functions-use-them-all">Стили именования переменных и функций. Используйте их все</a>»</p>]]></description>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[Коротко о главном]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 18 Nov 2020 09:46:21 GMT</pubDate>
      <content:encoded><![CDATA[<p>Чтобы обеспечить легкую читаемость кода программисты используют разные стили именования для разных типов объектов, функций и переменных. Именно поэтому нет какого-то одного «идеального» формата. Выбор уместного стиля поможет быстро понять к какому типу относится сущность в коде, но не забывайте и о том, что имя должно объяснять что делает это сущность. Мы расскажем какой стиль существует для каждой из возможных ситуаций.</p><p>В программировании пробел является зарезервированным символом, поэтому все названия обходятся без него. Чтобы строки без пробелов всё же напоминали естественный язык и нужны все эти кейсы.</p><h2>camelCase (dromedaryCase)</h2><p>Каждое слово, кроме первого, начинается с большой буквы.<br />Применяется для именования переменных и функций в большинстве языков.</p><figure><img src="https://media.tproger.ru/uploads/2020/11/camelCase-1.png" alt="" /></figure><h2>PascalCase (CamelCase, StudlyCase)</h2><p>В этом стиле каждое слово начинается с заглавной буквы. Обычно используется для названий классов.</p><figure><img src="https://media.tproger.ru/uploads/2020/11/PascalCase-1.png" alt="" /></figure><h2>snake_case (pothole_case)</h2><p>Вместо пробела ставится нижнее подчёркивание. Используется в основном для имён полей баз данных, переменных и функций.</p><figure><img src="https://media.tproger.ru/uploads/2020/11/snake_case.png" alt="" /></figure><h2>SCREAMING_SNAKE_CASE (MACRO_CASE, CONSTANT_CASE)</h2><p>Тот же snake_case, только буквы всегда в верхнем регистре. Обычно используется для именования констант.</p><figure><img src="https://media.tproger.ru/uploads/2020/11/SCREAMING_SNAKE_CASE.png" alt="" /></figure><h2>kebab-case (dash-case, lisp-case)</h2><p>В этом случае пробел заменяется дефисом. Используется в URL и CSS. В языке Lisp так пишутся любые названия. Примеры:</p><p>background-color</p><h2>TRAIN-CASE (COBOL-CASE, SCREAMING-KEBAB-CASE)</h2><p>Все буквы в верхнем регистре, соединены дефисом. Применяется в языке COBOL для всех названий. Пример:</p><p>PROGRAM-ID</p><h2>Train-Case (HTTP-Header-Case)</h2><p>Каждое слово с большой буквы, соединены дефисом. Стиль названий HTTP заголовков. Пример:</p><p>Content-Length</p><h2>flatcase</h2><p>Все слова в нижнем регистре, без пробелов. Используется в тегах. Пример:</p><p>#stayhome</p>]]></content:encoded>
    </item>
    <item>
      <title>Когда вместо Boolean лучше использовать Enum и почему</title>
      <link>https://tproger.ru/translations/dont-use-boolean-arguments-use-enums</link>
      <comments>https://tproger.ru/translations/dont-use-boolean-arguments-use-enums?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/dont-use-boolean-arguments-use-enums</guid>
      <description><![CDATA[<p>Булевы флаги кажутся простыми, но усложняют бизнес-логику, ухудшают читаемость и масштабируемость, а также запутывают сигнатуры методов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/dont-use-boolean-arguments-use-enums">Когда вместо Boolean лучше использовать Enum и почему</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 08 May 2020 17:46:47 GMT</pubDate>
      <content:encoded><![CDATA[<p>Boolean — один из первых типов данных, которые изучают начинающие программисты. Почему бы и нет? Логический тип максимально прост, ведь принимает всего два значения: true и false.</p><p>Прим.ред. Речь идёт о языках программирования, в которых Boolean не может быть null.</p><p>Хотя использование булевых флагов в коде кажется хорошей идеей, это может усложнить логику, ухудшить читаемость и масштабируемость кода в дальнейшем. Аргументы-флаги делают реализацию бизнес-логики запутанной, а структура кода обретает следующий вид:<a href="https://media.tproger.ru/uploads/2020/05/5567567.jpg"></a></p><p>Передача логического значения функции — воистину ужасная привычка. Она немедленно усложняет сигнатуру метода, громко провозглашая, что функция выполняет более одной операции.</p><h2>Пример использования Boolean</h2><p>Предположим, что группа разработчиков создаёт модуль для управления состоянием пользователя. Один из программистов настаивает на использовании логического типа, так как в требованиях указано только два значения: ONLINE и OFFLINE. Несмотря на то, что большая часть команды не согласна с таким предложением, его принимают, ведь реализация условий с использованием Boolean выглядит простой и быстрой.</p><p>В конце концов, в коде появляются такие функции:</p><p>Вскоре к команде присоединяется новый разработчик, который не понимает, за что отвечает следующая строка:</p><p>Кто-то из команды предлагает изменить название функции на setUserOnline(), и поначалу этого решения оказывается достаточно. Но затем всё превращается в сущий кошмар, ведь требование дополняется необходимостью ввести ещё один статус: BLOCKED. Есть несколько способов решить поставленную задачу. Разберём их подробнее.</p><h2>Одна булева переменная и три состояния</h2><p>Boolean обычно принимает два значения. Но в некоторых языках, таких как Java, где у примитивных типов есть классы обёртки, можно использовать null для присвоения третьего состояния. В нашем примере для определения статуса BLOCKED будет использовано значение null.</p><p>Хотя это и кажется подходящим решением, при работе с такой булевой переменной команда разработчиков рискует напарываться на исключение NullPointerException.</p><p>Кроме того, в некоторых сценариях будет сложно отличить false от null. Возьмём, к примеру, свойство game.isPlaying. Значение true будет чётко указывать на то, что игра запущена. Но что если значение равно false или null? false означает, что игра на паузе или остановлена? А на что в таком случае указывает null?</p><p>Как видите, значение false недостаточно информативно, и наличие третьего состояния, привязанного кnull, только усложнит логику кода.</p><p>К тому же, что произойдёт, если разработчиков попросят добавить ещё один статус —EXPIRED? Становится понятно, что способ с использованием одной булевой переменной не подходит.</p><h2>Несколько булевых переменных</h2><p>В итоге команда решает расширить сигнатуру предыдущей функции, добавив два булевых параметра для новых состояний:</p><p>И вот какие проблемы их поджидают.</p><h3>Появление скрытых зависимостей</h3><p>Простое с виду расширение перечня добавит скрытые зависимости и новые комбинации состояний.</p><p>Теперь будет две скрытые зависимости: isUserOnline — isUserExpiredи isUserOnline—isUserBlocked. Придётся обрабатывать дополнительные условия, чтобы избежать конфликтующих состояний. Например, пользователь со статусом BLOCKEDили EXPIREDне может быть со статусомONLINE. Примеры таких условий:</p><p>Если включить больше статусов, функции превратятся в длинный список параметров, а логика станет сложной, полной условий для обработки зависимых друг от друга значений.</p><h3>Проблемы с безопасностью и читаемостью</h3><p>Использование нескольких булевых переменных также влечёт за собой путаницу, которая обернётся кошмаром на этапе рефакторинга и написания модульных тестов. При вызове функции, которой передаются значения логических переменных, легко перепутать, какая из переменных за что отвечает:</p><p>setUserState(true, false, false)</p><p>Да, многие языки программирования поддерживают именованные аргументы, которые позволяют улучшить читаемость функций. Но вы всё равно не застрахованы от передачи неправильного логического значения, а компилятор даже не сочтёт это за ошибку.</p><p>Группа разработчиков из примера избежит перечисленных проблем, если вместо Boolean использует Enum.</p><h2>Использование Enum</h2><p>Перечисление — это тип данных, который состоит из набора именованных значений и обеспечивает высокую типобезопасность. Использование логического типа выглядит проще, но Enum позволяет избежать сложной логики со множеством условий. Пример перечисляемого типа:</p><p>Рассмотрим главные преимущества Enum.</p><h3>Чёткость и содержательность</h3><p>Перечисления обязывают именовать все состояния, что делает код самодокументируемым. Значения перечисляемого типа взаимоисключающие, а их передача в качестве параметров функции намного понятнее, чем передача значений булевых переменных. Просто сравните:</p><h3>Простое масштабирование</h3><p>Расширить набор значений в Enum проще, ведь с появлением каждого нового значения число комбинаций состояний не удваивается, как было бы с созданием новых булевых переменных. Кроме того, многие компиляторы способны подсказать, какие изменения нужно внести, чтобы учесть новое значение Enum. Это, в свою очередь, упрощает рефакторинг.</p><h3>Высокая типобезопасность</h3><p>С Enum вы не сможете присвоить значения в обход тех, что указаны в перечне. Компилятор предупредит, если вы случайно поменяете значение или передадите недопустимое состояние.</p><p>Однако не все языки поддерживают Enum. В таких случаях вы можете создать собственные типы. Например, в JavaScript можно «заморозить» константы в объекте:</p><p>Прим.ред. Стоит отметить, что кастомные реализации Enum могут ухудшить читаемость и производительность кода. В языках, которые не поддерживают перечисляемый тип, иногда лучше предпочесть Boolean.</p><h2>Заключение</h2><p>Boolean — это не плохо. Его можно использовать, если вы уверены, что имеете дело с двумя взаимоисключающими состояниями, или если это стандартный метод, который подразумевает принятие булевого аргумента (например setEnabled(true)).</p><p>Но зачастую требования меняются и расширяются. В таких случаях стоит потратить чуть больше времени на реализацию Enum — скорее всего, в будущем это окупится.</p>]]></content:encoded>
    </item>
    <item>
      <title>Умеете ли вы правильно называть функции?</title>
      <link>https://tproger.ru/translations/correct-function-names</link>
      <comments>https://tproger.ru/translations/correct-function-names?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/correct-function-names</guid>
      <description><![CDATA[<p>Имя может точно описывать то, что делает функция, и всё равно быть бесполезным на практике. Пример std::log2p1() и что с этим делать.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/correct-function-names">Умеете ли вы правильно называть функции?</a>»</p>]]></description>
      <category><![CDATA[C++]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 14 Jan 2020 09:41:14 GMT</pubDate>
      <content:encoded><![CDATA[<p>Автор перевода — Мария Багулина</p><p>Названия функций крайне важны, особенно если вы занимаетесь разработкой пользовательского API. Иногда имя может прекрасно описывать то, что делает функция, но на практике оказывается абсолютно бесполезным. И с этим можно столкнуться даже в стандартных библиотеках. В качестве примеров рассмотрим несколько функций C++20.</p><h2>Пример 1: std::log2p1()</h2><p>Начнём с функции std::log2p1().Её код выглядит так:</p><p>Функция просто возвращает двоичный логарифм числа плюс один, о чём и говорит её название.</p><p>Но какая от этого польза?</p><p>На самом деле std::log2p1(x) возвращает количество битов, необходимых для хранения x. Это действительно нужная функция, но её название совсем не отражает суть выполняемой операции.</p><h2>Пример 2: std::bless()</h2><p>Если вы плохо знакомы с языком C++, то вот быстрое введение в его объектную модель.</p><p>В С++ существует такая штука, как указатель — переменная, в которую записывается адрес другого объекта в памяти. Над указателем можно выполнять арифметические действия, но только если он является элементом массива. Почему так? Потому что нельзя вычитать или прибавлять что-то к произвольному указателю — это не имеет смысла, так как расположение объектов в памяти неизвестно.</p><p>Однако такое действие не является явной ошибкой, а порождает неопределённое поведение (то есть результат, зависящий от состояния памяти, компилятора, фазы луны или каких-либо других случайных факторов).</p><p>Проблема сводится не к глупым программистам, которые зачем-то складывают указатели (ведь это не запрещено), а к самому языку С++. Поэтому Ричард Смит, исследователь из Google, предложил добавить в стандарт функцию std::bless(void* ptr, std::size_t n),чтобы при необходимости автоматически выделять массив памяти и тем самым разрешить вопрос с арифметикой для указателей.</p><p>Имя bless, разумеется, никак не сообщает обо всех этих нововведениях, поэтому было решено придумать другое название для функции. За дело взялся комитет по развитию языка C++: в качестве кандидатов они выдвинули верси иimplicitly_create_objects() и implicitly_create_objects_as_needed() («неявно создать объекты» и «неявно создать объекты при необходимости»). Имена вполне логичны, ведь функция делает именно то, что в них сказано. Но, согласитесь, если бы вы не знали предысторию, то совершенно не поняли, зачем нужно создавать какие-то объекты.</p><h2>Пример 3: std::popcount()</h2><p>Напоследок ещё одна стандартная функция C++ 20. Просто посмотрите на её имя и попробуйте угадать, что она делает. Кажется, что-то считает? Может быть, это связано со стековыми операциями pop и push?</p><p>Скорее всего, вы не догадаетесь, если только уже не знаете о низкоуровневой инструкции с таким же названием. Функция popcount (сокращённо от «population count») подсчитывает количество установленных битов в машинном слове.</p><p>С одной стороны, это было бы отличное имя, если бы все разработчики знали названия ассемблерных битовых операций. Но будет ли оно очевидно новичку, который не в курсе таких тонкостей?</p><h2>Как же следует называть функции?</h2><p>Ни одно из имён, представленных выше, нельзя назвать плохим: они действительно описывают то, что делают функции. Но для вас, как пользователя, эти имена бесполезны — они содержат не ту информацию, которая вам нужна.</p><p>Вряд ли вы подумаете: «Так, мне нужно вычислить двоичный логарифм плюс один, нет ли случайно стандартной функции для этого?». Скорее в вашей голове будет мысль: «Теперь мне нужно знать, сколько битов требуется для хранения этого значения». И ваш запрос в Google будет выглядеть примерно как: «bit width function C++» — почему бы тогда вместоlog2p1()не использовать имяbit_width()?</p><p>Имена, которые описывают реализацию функции, будут понятны для разработчиков, но могут оказаться совершенно бессмысленными для пользователей. Причём этими пользователями являются другие разработчики, которые хотят подключить к своему проекту кем-то созданную библиотеку. Согласитесь, в этом случае важно то, что делают функции, а не как они реализованы.</p><h2>Happy end</h2><p>Раз уж мы затронули тему C++20, спешим сообщить хорошие новости: кажется, комитет по развитию языка всё-таки переименует std::log2p1()вstd::bit_width(). Но проблема именования затрагивает не только стандартные библиотеки. Поэтому если ваш проект предполагает, что его кодом кто-то будет пользоваться в дальнейшем, выбирайте говорящие имена и смотрите на функции с точки зрения пользователей.</p>]]></content:encoded>
    </item>
    <item>
      <title>Стоит ли писать «красивый» код — отвечают эксперты</title>
      <link>https://tproger.ru/experts/is-it-worth-writing-clean-code</link>
      <comments>https://tproger.ru/experts/is-it-worth-writing-clean-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Никита Прияцелюк]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/experts/is-it-worth-writing-clean-code</guid>
      <description><![CDATA[<p>Оформление по Style Guide и корректные имена переменных дают читаемость кода, без которой коммерческий проект тяжело поддерживать.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/experts/is-it-worth-writing-clean-code">Стоит ли писать «красивый» код — отвечают эксперты</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Ответы экспертов]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 11 Nov 2019 09:55:53 GMT</pubDate>
      <content:encoded><![CDATA[<p>Стоит ли тратить время на «красивое» оформление кода согласно разным Style Guide, если того не требует заказчик? Или же это всё дурные мысли, появляющиеся от безделья, и главное, чтобы код работал? Узнаем у экспертов.</p><p>Корректное именование переменных и Code Style — это не прихоть. Это то, из чего складывается такая полезная вещь, как семантика кода, она же в переводе с высшего эльфийского — читаемость и понятность. В своём проекте можно творить любую дичь, хоть запутывание кода на уровне написания — но любой коммерческий проект подразумевает поддержку. А значит, упорядоченный, читаемый код — «не роскошь, а средство передвижения». Просто спросите себя — а я сам эту «мудрость предков» пойму через месяц? Или буду обкладывать матом человека, который это написал?</p><p>Мой любимый пример — это работа с сервисом очередей на одном проекте. Код был написан на основе внутренней магии сервиса и содержал четыре переменные — a, b, c и d. Чтобы выяснить, что это за переменные и какая именно магия используется внутри, ушло десять часов. Вместо десяти минут. Как сказал человек, которому пришлось это разбирать… Хотя нет, я не могу этого рассказать — это непедагогично.</p><p>Есть и более мелкие примеры, с которыми сталкиваются разработчики изо дня в день. Все они похожи между собой и кочуют из проекта в проект.</p><ul><li>Банальное именование переменных. Например, абстрактные data, result и value — там же данные, результат и значение, что может быть непонятного? Только в проекте этих данных, результатов и значений — как у дурака фантиков. К тому же, каждый раз придётся вспоминать, что там лежит, если не оставить себе на будущее комментарии. Перед каждой строкой, где эти переменные используются.</li><li>«Вроде-как-синонимы». Индекс элемента массива, обозначенный как order1, даже выглядит логично — элементы идут по порядку, начиная с первого. Только «порядок сортировки» и «порядковый номер элемента» это даже не синонимы, хотя в голове автора это, видимо, так. Здесь можно было бы вспомнить про «<a href="https://ru.wikipedia.org/wiki/Ложные_друзья_переводчика">Ложных друзей переводчика</a>», если бы мы говорили о трудностях перевода.</li><li>«Я художник — я так вижу». Вот функция с названием getListCount, которая возвращает true, false или null. Что хотел сказать этим автор? — что длина списка строго больше единицы. А что значит null? — что не придумали другого обозначения для пустого списка. Но читая название функции, я хочу сразу понимать, что она делает, а не гадать, почему на вопрос «Ты будешь чай или кофе?» мне отвечают «В четверг».</li><li>Разное название для одних и тех же терминов. direct, isDirect, oneWay и emptyTransfers — нормальные названия для прямых рейсов в рамках ста строк кода (если не смог договориться с голосами в голове).</li></ul><p>Смотря на все эти примеры, основную мысль можно выразить так: правильное именование сущностей позволяет поддерживать код без головной боли, пустой траты времени и битвы экстрасенсов. Это даёт ожидаемое поведение чего бы то ни было.</p><p>Так что не стоит пренебрегать корректным именованием переменных и форматированием кода — последнее в профессиональных редакторах вообще делается парой клавиш. И себе нервы сэкономите, и человеку, который за вами это будет доделывать. И помните: статья «<a href="https://tproger.ru/translations/unmaintainable-code/">Как писать неподдерживаемый код</a>» — это вредные советы, а не руководство к действию.</p><p>Таким вопросом программисты задаются достаточно часто, и главный аргумент противников «красивого» кода — «время будет потрачено впустую». И если разговор зашёл про время, давайте посмотрим на проблему с другой стороны. Допустим, кому-то придётся модифицировать код, написанный другим программистом (возможно, это будет даже его собственный код, но с момента его написания прошло значительное время, и всё порядком подзабылось). Как быстро удастся с ним разобраться, когда в нём нет комментариев, на каждой строчке расположено по несколько действий, а все переменные именуются «А», «ВВ», «ССС»?  Сразу отвечу: иногда бывает проще написать новый код, чем распутывать это «спагетти».</p><p>Таким образом, оформив и документировав код, мы значительно экономим время того, кто будет дальше его поддерживать и развивать.</p><p>Ответ на поставленный запрос напрямую зависит от того, как и с кем работает программист.</p><p>Если перед программистом стоит задача написать приложение или библиотеку для себя, или если в будущем не планируется привлечения других людей для работы над проектом, то можно действительно «творить» со своим кодом всё, что душа пожелает. Золотое правило для программистов-одиночек звучит следующим образом: «Пока я понимаю свой код, ничего дополнительного мне делать не нужно».</p><p>Если программист работает в команде (или в ближайшее время такая работа планируется), то возникает необходимость в документировании и тестировании исходного кода, а также в корректном именовании переменных, соблюдении стилевого гида. Это необходимо для того, чтобы прямо через исходный код сообщать о своих намерениях коллегам. В противном случае, над проектом всегда будет висеть угроза большого количества ошибок, возникших в результате влияния одних кусков кода на другие — регрессий. Командная работа также подразумевает использование нетривиальных техник программирования — design patterns. С их помощью код разбивается на необходимые структурные элементы, которые документируются и тестируется независимо друг от друга. Если все программисты, работающие над одним проектом, говорят на одном «языке» архитектуры приложения, то каждый сможет написать такие независимые модули, а вероятность их «поломки» будет стремиться к нулю. Design patterns, unit tests, документирование кода — это своеобразное письменное соглашение программистов о том, как ведётся работа над конкретным проектом. Она помогает коллегам лучше помогать друг друга через код.</p><p>Во всяком случае, использование всех вышеперечисленных приёмов для реализации личных проектов, — это хороший способ дисциплинировать себя, научиться писать код, который легко поддерживать спустя многие годы работы над приложением. Для программистов-новичков, к тому же, это лучший шанс подготовиться к работе в команде.</p><p>Писать «красивый» код стоит. Почему?</p><p>Открывая меню любого ресторана/бара/кафе, что вы делаете в первую очередь? Видите картинки. Для себя определяете: нравится ли блюдо, понятен ли его состав, большая ли порция, будет ли её достаточно. Согласитесь: если вам принесут некую непонятную субстанцию, пусть даже и гипотетически вкусную, первая реакция — недоверие.</p><p>Так и с кодом: глядя на него, вам будет хотеться понять его алгоритм, оценить, как программа поведёт себя в том или ином случае, где необходимо внести определённые правки.</p><p>В длинном и неаккуратном коде вы можете возиться очень долго — потеряете время, нервы, силы, и нет гарантии, что всё получится.</p><p>Программист-профессионал чётко знает, что и для кого он пишет, какую задачу должен решать этот код, даже если единственное требование заказчика — «чтобы работало». Код не должен впечатлять, он должен быть понятным, однозначным, конкретным, предсказуемым в будущем. Такой код намного проще не только поддерживать, но и оптимизировать, и фиксить при необходимости.</p><p>Большую роль играют наименования переменных и методов, поскольку значительно упрощают чтение кода. Достижение той же цели, но значительно меньшим количеством кода, делает его более надёжным. Комментируйте, но не увлекайтесь. Не проектируйте лишнего, отталкивайтесь от определённой задачи. Отслеживайте ошибки.</p><p>«Красивый», но неработающий код бесполезен, а работающий код без красоты нечитаем и сложен. Сделать его и работающим, и «красивым» помогает целый ряд ПО. Мы, например, используем:</p><ul><li>Smoke test на Vanessa-add (разработанная на основе Vanessa-behavior) — для проверки работоспособности;</li><li>SonarQube — для анализа качества и «красоты» кода.</li></ul><p>Вот некоторые моменты, на которые мы обращаем внимание при написании кода в своих разработках:</p><ul><li>когнитивная сложность функции/процедуры: помогает ограничить количество условий и циклов в одной функции/процедуре. Такое ограничение нужно для повышения сопровождаемой функции/процедуры. Многие разработчики этим общим стандартом пренебрегают, а в дальнейшем сталкиваются с достаточно типовыми проблемами — например, в тестировании или в доработке таких функций/процедур;</li><li>«магические» числа/даты — сущность, появляющаяся в коде из ниоткуда и используемая напрямую в выражениях; за ней надо следить, потому что это тоже достаточно частый грешок программистов, после чего сам же программист сталкивается с непониманием того, что он сделал;</li><li>именование виртуальных таблиц в запросах. Ещё одна очень часто встречающаяся проблема, когда программист строит многоуровневый запрос с большим количеством виртуальных таблиц или вложенных запросов и именует их по типу VT1, VT2, VT3 и т. д. В дальнейшем такой подход усложняет процесс сопровождения и читаемости запроса.</li></ul><p>Это, разумеется, далеко не все важные моменты. Но всё, что ещё можно было бы здесь перечислить, так или иначе влияет на сопровождаемость, читаемость и тестирование кода. Отсюда можно сделать вывод: «красивый» и работающий код, написанный по общепризнанным стандартам, упрощает и сокращает затраты на его сопровождение.</p><p>Начнём с самого главного: если код не работает, то можно не тратить время на оценку остальных его параметров. Неработающий код — это отсутствующий код. Но как только всё собралось и заработало, наступает время подумать, что же дальше.</p><p>А дальше этот код будут читать. Много, долго и совершенно непричастные люди. Гораздо дольше, чем планирует автор, и люди, максимально далёкие от заложенных в коде идей. Или даже сам автор, но в ситуации, которая исключает плавное и вдумчивое погружение во вчерашние озарения. Поэтому то, что называется «красивостью», является обычным инструментом, который призван удешевить главный параметр кода — его сопровождаемость.</p><p>Архитектура, стиль, следование стандартам и документации, мнемоничность именования сущностей, да даже размеры отступов — это всё должно служить одной цели: облегчению сопровождения кода. То есть удешевлению стоимости внесения изменений в уже работающий код.</p><p>Заказчик в крайне редких случаях предъявляет какие-то требования к коду. Разве что его основной бизнес — программирование. Покупают у программистов фичи, а не код, инструменты и их работающую функциональность. А ещё дешёвое внесение модификаций в уже работающую систему или расширение функциональности, не требующее экспоненциально растущих затрат.</p><p>Можно ли сэкономить на красоте? Можно, конечно. Если код планируется «write-only» — запустить один раз и забыть.</p><p>Я не вижу дихотомии. Код должен работать и быть красивым, то есть простым (не примитивным!), читаемым, понятным, легко модифицируемым и расширяемым.</p><p>Корректное оформление кода позволяет сохранять код понятным и поддерживаемым. На крупных проектах, над которыми работают несколько команд программистов, особенно важно правильно понимать то, что сделано другими. Во frontend разработке, в частности, принято комментирование кода согласно JsDoc и корректное именование переменных. Для оформления отступов и форматирования можно применять Prettier, настраивать pre-commit и pre-push hooks для Git, а в качестве дополнительного средства для улучшения качества кода использовать статические анализаторы.</p><p>Code Style важен для проекта, особенно если над ним работает не один человек, а целая команда. Для того, чтобы с кодом в дальнейшем можно было работать и поддерживать его, дополняя и внося изменения, обязательно должна быть логика именования переменных, описания функций и т. п. Вопросы стилизации кода, коррекции его отступов, расстановку запятых можно автоматизировать и не тратить на них времени, если в проекте уже есть настройки для плагинов, форматирующих код в IDE или для самой IDE, если язык это позволяет делать. На эту часть работы тратится от силы час в начале работы над проектом и дальше автоматика всё делает за разработчика, хотя с какого-то момента уже и сам начинаешь писать код в соответствии со стилем (потому что это очень удобно, когда сразу всё в одном стиле).</p><p>Если же стоит задача сделать как можно скорее, чтобы выкатить функцию для тестирования, то в этом случае, необходимо после выкладки функции производить дополнительно некоторый рефакторинг, который позволит привести код в порядок и сделать из сложно читаемого быстрого решения что-то, что будет нормально восприниматься не только автором кода, но и его коллегами.</p><p>Моё мнение, что проекты, в которых есть Style Guide и следование стандартам написания кода и именования переменных, на голову жизнеспособнее в долгосрочной перспективе по сравнению с проектами, где Style Guide отсутствует.</p><h2>Итак, нужно ли писать «красивый» код?</h2><p>Если вы пишете что-то для себя, то в целом вы вольны творить с кодом что угодно. До тех пор, пока вы понимаете, что происходит, можно считать, что проблем нет.</p><p>Если же вы работаете над каким-то проектом с командой, то тут, безусловно, нужно придерживаться определённых правил. И дело не в том, что у компаний слишком много денег, что они готовы тратить драгоценное время программистов на написание кода в каком-то определённом стиле. Проекты, как правило, предполагают поддержку. А код, написанный абы как, поддерживать дорого, потому что даже его создатель через месяц может не вспомнить, почему он использовал этот шаблон проектирования или что это за переменная data.</p><p>Итого: пишете что-то для себя — чистый код может подождать, работаете в команде — следуйте принятым правилам оформления кода и пишите с перспективой на будущее.</p><p>Напоминаем, что вы можете <a href="https://docs.google.com/forms/d/e/1FAIpQLSdSanNvlfPRrSyQWfnoGPflSVwO4KctnjOdEKHzuxjCmFX2dA/viewform">задать свой вопрос</a> экспертам, а мы соберём на него ответы, если он окажется интересным. Вопросы, которые уже задавались, можно найти в списке выпусков <a href="https://tproger.ru/experts/">рубрики</a>. Если вы хотите присоединиться к числу экспертов и прислать ответ от вашей компании или лично от вас, то пишите на <a>experts@tproger.ru</a>, мы расскажем, как это сделать.</p>]]></content:encoded>
    </item>
    <item>
      <title>Страшна, вырубай: хэллоуинская подборка кода, от которого волосы встают дыбом</title>
      <link>https://tproger.ru/articles/halloween-scary-code-compilation</link>
      <comments>https://tproger.ru/articles/halloween-scary-code-compilation?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/halloween-scary-code-compilation</guid>
      <description><![CDATA[<p>Примеры эпичного кода к Хэллоуину, от которых не знаешь, смеяться или плакать: код — это творчество, и иногда авторы творят страшные вещи.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/halloween-scary-code-compilation">Страшна, вырубай: хэллоуинская подборка кода, от которого волосы встают дыбом</a>»</p>]]></description>
      <category><![CDATA[Юмор]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 31 Oct 2019 16:18:13 GMT</pubDate>
      <content:encoded><![CDATA[<p>isalpha()? Не, не слышал.</p><p>Писать, почему этот код неок — всё равно, что объяснять смысл анекдота.</p><p>Переводим только самые актуальные языки: древнепрусский, нижнелужицкий, авестийский…</p><p>Как говорила Скарлетт О’Хара: «Я подумаю об этом завтра».</p><p>Когда препод задал написать рекурсивную функцию, но факториал и Фибоначчи уже забрали, а тебе досталась сумма.</p><p>То пиши понятные названия переменных, то не пиши…</p><p>Все эти ванильные дефайны с эмоджи — ерунда по сравнению с этим:</p><p>А как вам рисование линий по пикселям с помощью функции которая предназначена для рисования линий?</p><p>На сладкое. Просто попробуйте понять, что делают эти две строчки кода.</p>]]></content:encoded>
    </item>
    <item>
      <title>Какие примеры кода вызывали у вас восхищение — отвечают эксперты</title>
      <link>https://tproger.ru/experts/excellent-code</link>
      <comments>https://tproger.ru/experts/excellent-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анастасия Витвицкая]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/experts/excellent-code</guid>
      <description><![CDATA[<p>Фрагменты кода, которые впечатлили опытных разработчиков, — ответы экспертов на вопрос подписчика о самых восхитительных примерах.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/experts/excellent-code">Какие примеры кода вызывали у вас восхищение — отвечают эксперты</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Для мотивации]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Ответы экспертов]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 21 Oct 2018 18:33:01 GMT</pubDate>
      <content:encoded><![CDATA[<p>Мечтаете ли вы стать кумиром для программистов? Наш подписчик, наверное, стремится к этому, и он обратился в нашу редакцию с вопросом:</p><p>«Какие примеры кода вызывали у вас восхищение?»</p><p>За разъяснениями мы обратились к нашим экспертам, а полученные ответы предоставляем вашему вниманию.</p>]]></content:encoded>
    </item>
    <item>
      <title>Интересные проекты: Vim-плагин против глубокой вложенности кода</title>
      <link>https://tproger.ru/articles/vim-disapprove-deep-indentation-by-dodie</link>
      <comments>https://tproger.ru/articles/vim-disapprove-deep-indentation-by-dodie?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Екатерина Никитина]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/vim-disapprove-deep-indentation-by-dodie</guid>
      <description><![CDATA[<p>Плагин для Vim добавляет визуальный значок при вложенности от пяти уровней, не меняет исходный код и устанавливается через Pathogen или Vundle.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/vim-disapprove-deep-indentation-by-dodie">Интересные проекты: Vim-плагин против глубокой вложенности кода</a>»</p>]]></description>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Pet-проекты]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 26 Dec 2017 09:58:13 GMT</pubDate>
      <content:encoded><![CDATA[<p>На GitHub появился <a href="https://github.com/dodie/vim-disapprove-deep-indentation">плагин</a> для текстового редактора Vim, рисующий значок ಠ_ಠ в начале каждой строки с уровнем вложенности кода от пяти и выше.</p><figure><img src="https://media.tproger.ru/uploads/2017/12/2017-12-24.-disapprove.gif" alt="" /></figure><p>Предельный уровень можно установить по своему желанию с любой из команд:</p><p>Значение 0 отключает функцию.</p><figure><img src="https://media.tproger.ru/uploads/2017/12/2017-12-24.-disapprove_2.png" alt="" /></figure><h3>Установка</h3><p>Плагин можно легко установить с помощью <a href="https://github.com/tpope/vim-pathogen">Pathogen</a> или <a href="https://github.com/VundleVim/Vundle.vim">Vundle</a>. Чтобы появился смайлик, Vim должен быть скомпилирован с +conceal.</p><h3>Принцип работы</h3><p>Плагин использует свойство редактора conceal. Он никоим образом не меняет исходный код, неодобрительный смайлик — это лишь визуальный эффект.</p><p>Работа conceal зависит от правил подсветки синтаксиса. В некоторых случаях определенные плагином правила могут вступать в конфликт с теми, что устанавливаются по умолчанию для того или иного типа файлов. Это может привести к тому, что неодобрительный смайлик появится в начале строки с неглубокой вложенностью. В таком случае разработчики советуют не стесняться сообщать о проблеме, а пока она решается, отключить плагин для этих типов файлов с помощью команды:</p>]]></content:encoded>
    </item>
    <item>
      <title>Будь как кот, вылижи свой код: 8 хороших практик по повышению качества кода</title>
      <link>https://tproger.ru/translations/lick-clean-your-code</link>
      <comments>https://tproger.ru/translations/lick-clean-your-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Ярослав Сарницкий]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/lick-clean-your-code</guid>
      <description><![CDATA[<p>Хороший код должен не просто работать, он должен быть простым, модульным, легко тестируемым, поддерживаемым и продуманным. Рассказываем, как этого добиться.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/lick-clean-your-code">Будь как кот, вылижи свой код: 8 хороших практик по повышению качества кода</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 14 Sep 2017 18:05:57 GMT</pubDate>
      <content:encoded><![CDATA[<p>Начинающие программисты обычно проводят год или два, не обращая внимания на правила «хорошего кода». Конечно, они могут слышать такие выражения, как «элегантный» или «чистый» код, но не всегда способны дать им определение. Это вполне нормально. Для программиста без опыта существует только один важный параметр — рабочий код.</p><p>Вскоре каждый программист поднимает планку качества кода. Хороший код должен не просто работать, а быть модульным, легко тестируемым, поддерживаемым и продуманным. Если вам повезет работать с командой, которая тщательно продумывает архитектуру кода, тогда вы сможете развить навыки для написания хорошо структурированного программного обеспечения. Если же не повезет, тогда команда будет постоянно жаловаться на качество вашего кода. В любом случае изучить несколько универсальных принципов написания кода будет полезно каждому.</p><p>Возьмем, например, глобальную переменную. Доступ к глобальным переменным можно получить из любой функции или места в приложении. Большинство влиятельных блогеров не рекомендуют использовать глобальные переменные, а начинающие программисты не понимают, почему это так. Причина заключает в том, что хотя такая практика и помогает писать код быстрее, но он становится сложнее для понимания. Конечно, глобальная переменная позволит легко вставлять, например, username в любом месте приложения, чтобы сэкономить несколько строчек кода. Однако здесь вы жертвуете безопасностью ради удобства. Если во время создания приложения обнаружится баг, связанный со значением username, тогда придется отлаживать не только один класс или метод, но и весь проект. Но вернемся к этому позже.</p><p>Разница между «хорошим» и «плохим» кодом заключается не только в его влиянии на вас. Код всегда остается общим ресурсом, им обычно делятся со сторонними разработчиками или с программистами из вашей команды, или человеком, у которого останется ваша работа, или «будущим собой» (который уже не будет понимать свой старый код), или отладчиком кода, который будет искать ошибки и баги. Все эти люди сделают свою работу намного быстрее, если код будет написан с умом. Таким образом, писать хороший код — это форма профессиональной любезности.</p><p>А теперь давайте рассмотрим принципы, которые помогут писать более качественный код.</p><h3>Термины</h3><p>Для начала дадим несколько определений:</p><ul><li>состояние (state) — это данные, хранящиеся в памяти приложения. Каждая назначенная переменная является частью состояния приложения;</li><li>рефакторинг (refactor) — изменение кода программы без изменения ее поведения (по крайней мере, видимого пользователю). Цель рефакторинга — упростить код и сделать его проще для чтения и понимания.</li></ul><h2>1. Разделение проблем</h2><p>Давайте сравним создание кода с процессом готовки. Простой рецепт предполагает, что каждый последующий шаг будет совершен после завершения предыдущего, как только все шаги будут выполнены — блюдо будет готово. Но если взять, например, сложный рецепт, когда на плите одновременно стоят две кипящие кастрюли, в микроволновке вращается тарелка, у вас есть три вида овощей, мельницы с разными специями (и вы не помните, что уже добавили), это вызовет настоящий стресс.</p><p>Кроме того, на кухне есть еще один повар, который то усложняет, то упрощает процесс. Нужно тратить время на координацию, передавая вещи туда и обратно, сражаться за место за плитой и все время регулировать температуру в духовке. Чтобы делать все это, нужна практика.</p><p>Если знать, что на кухне будет несколько поваров, тогда стоит разделить рецепт на несколько субрецептов. Тогда каждый из поваров будет работать только над своей частью рецепта с минимальным взаимодействием. Один — готовит кипящую воду для макарон, второй — нарезает и готовит овощи, третий — измельчает сыр. Четвертый — делает соус. Благодаря четко определенным задачам каждый из них делает свою работу.</p><p>Худший вариант написания кода равен самому простому рецепту, когда каждая строчка кода определена в одном и том же пространстве и нанизана сверху вниз. Чтобы понять или изменить такой код, вам нужно будет пересмотреть его много раз. Ведь переменная из второй строчки может влиять на операцию в строке 832, и единственный способ это понять — пересмотреть весь код.</p><p>Более хороший вариант написания кода похож на пример со вторым поваром. Некоторые операции передаются другим частям программы, что частично упрощает код, но не приводит к его упорядочению. Это, конечно, улучшение, но этого недостаточно.</p><p>Лучший из вариантов — это разделение рецепта на субрецепты. В коде их называют «модулями» или «классами». Каждый модуль связан с определенной операцией или частью данных. Таким образом, человек, занимающийся овощами, не будет беспокоиться об ингредиентах для соуса, а человек, готовящий макароны, не будет волноваться о терке для сыра. Их проблемы разделены.</p><p>Польза от такого разделения очевидна. Предположим, что программисту нужно изменить некоторые данные программы позже — сделать ее свободной от глютена для клиентов с целиакией или добавить сезонный овощ. Ему нужно будет внимательно посмотреть код и изменить одну небольшую часть. Если весь код, связанный с овощами, содержится в одном небольшом классе с минимальным интерфейсом, программисту не нужно будет беспокоиться о том, что добавление овоща испортит соус.</p><p>Суть в том, что для внесения каких-либо изменений программисту нужно будет думать только о небольших частях программы, а не обо всех сразу.</p><h2>2. Глобальные переменные</h2><p>Возьмем, например, переменную username. При создании формы авторизации в приложении вы вдруг решили, что имя пользователя будет использоваться в нескольких местах приложения, например, на странице авторизации и в настройках. Поэтому сделали эту переменную глобальной. В Python она обозначается как global, а в JavaScript это свойство объекта window. На первый взгляд, это хорошее решение. Теперь в любом месте, где вам нужно использовать переменную username, вы легко можете это сделать. Но почему не сделать глобальными все переменные?</p><p>Представим, что что-то пошло не так. Нашелся баг в коде, который связан с переменной username. Даже с использованием инструментов поиска в вашей IDE найти эту переменную будет сложно. При поиске переменной username вы получите сотни, а то и тысячи результатов. Некоторые результаты поиска будут глобальной переменной, которую вы установили в начале проекта, некоторые — другими переменными с именем username, некоторые будут просто словом username, которое использовалось в комментарии, имени класса, имени метода и т. д. Можно будет установить дополнительные фильтры для поиска, но все же отладка займет много времени.</p><p>Решение проблемы заключается в том, чтобы поместить username в контейнер (например, класса или объекта данных), который вводится или передается в качестве аргумента классам и методам, нуждающимся в нем. Контейнер также может хранить любые подобные данные, связанные с входом в систему (только не пароль пользователя). Также можно сделать этот контейнер неизменяемым, например, при установке имени пользователя оно уже не может быть изменено. Это упростит отладку, даже если имя пользователя используется десятки тысяч раз.</p><p>Такое использование кода облегчит вашу жизнь. Нужные данные всегда будут находиться только в одном месте. И если вам понадобится отследить, когда часть кода или данных была изменена, вы всегда сможете использовать getter или setter.</p><h2>3. Не повторяйте себя</h2><p>Давайте поговорим про отношения.</p><p>Быть в отношениях — это хорошо, ведь вы всегда находите поддержку в своем партнере. Часто бывает, что приходится рассказывать историю вашего знакомства. И редко такая история бывает такой простой, как: «Мы завязали разговор в продуктовом магазине и вышли замуж на следующий день». Таким образом, вам приходится рассказывать одну и ту же историю каждый раз, несколько раз в неделю, что довольно утомительно.</p><p>Чтобы усугубить ситуацию, представьте себе, что через несколько месяцев вы узнаете новую информацию о своем знакомстве со второй половинкой. Вы считали, что это была чистая случайность, но на самом деле это не так. Знакомство произошло после нескольких месяцев тщательного заговора, который был успешно организован, чтобы вы понравились друг другу. С одной стороны, это сработало, и вы оба счастливы. С другой стороны, вы постоянно рассказывали другую историю в течение нескольких месяцев. Когда люди узнают, что на самом деле произошло, они могут подумать, что вы солгали им (несознательная ложь, но все же).</p><p>Находясь в полном недоумении, вы создаете веб-страницу «Как мы встретились», а потом посещаете офис FedEx, чтобы распечатать тысячу визитных карточек с адресом этого сайта. После этого отправляете письмо со ссылкой всем, кто слышал старую версию. И теперь, когда кто-то спрашивает, как вы встретили своего партнера, вы просто даете ему визитную карточку. Если история когда-либо изменится, вы можете обновить веб-страницу, тогда все узнают новые подробности вашего знакомства.</p><p>Это не только хороший способ решить одну сложную ситуацию в отношениях, но и отличный способ для программирования: писать код для каждой операции (каждого алгоритма, каждого элемента представления, каждого взаимодействия с внешним интерфейсом) только один раз, и всякий раз, когда другая часть кода должна знать об этой операции, вызывать ее по имени. То есть каждый раз, когда вы копируете и вставляете код больше одного раза, подумайте, возможно, вы делаете что-то не так. Поэтому если история о том, как LonelyUser получил сопоставление с MarriedUser, повторяется больше одного раза, пришло время рефакторинга.</p><p>Суть в том, что если операция должна измениться, вам нужно будет изменить только один класс или метод. Это быстрее и надежнее, чем попытка сохранить несколько копий одного и того же кода, что в итоге потребует много времени для внесения правок, а если пропустить одну или две строчки, может вызвать проблемы, которые будет трудно диагностировать.</p><h2>4. Сокрытие сложности</h2><p>Допустим, я хочу продать вам машину. Но потребуется определенная подготовка, чтобы узнать, как ее использовать.</p><p>Чтобы завести автомобиль, нужно взять белый и красный провод и соединить их, приподнять переднее колесо и залить соответствующее количество топлива в инжектор, который находится под центральной консолью. Как только автомобиль запустится, доберитесь до коробки передач и передвиньте распределительный вал к первой передаче на дифференциальном валу. Чтобы ехать быстрее, увеличьте поток бензина в инжектор. Чтобы остановиться, вставьте палку в колеса.</p><p>Очень надеюсь, что вы ненавидите этот автомобиль так же, как ненавижу его я. Теперь спроецируйте свою злость на элементы кода с чрезмерно сложными интерфейсами.</p><p>Когда вы создаете класс или метод, первое, что вам нужно создать, — это интерфейс, то есть часть кода, которую должен знать другой кусок кода (вызывающий) для использования этого класса или метода. Для метода это также называется сигнатурой. Каждый раз во время просмотра функции или класса в API документации (например, на MDN или jquery.com) вы видите интерфейс — все, что вам нужно знать для его использования без содержащегося в нем кода.</p><p>Интерфейс должен быть простым, но выразительным. Все должно быть понятно без слов, вызывающая функция не должна знать порядок выполнения событий или данных, за которые она не отвечает.</p><p>Плохой интерфейс:</p><p>Хороший интерфейс:</p><p>Если интерфейс можно уменьшить, то это нужно сделать. Если значение может быть выведено из других значений — это нужно сделать. Если у метода больше нескольких параметров, вы должны спросить себя, не делаете ли вы что-то не так (хотя можно делать исключения для конструкторов с зависимостями).</p><p>Но не нужно заходить слишком далеко. Если вы настраиваете глобальные переменные, чтобы избежать передачи параметров функции, вы делаете это неверно. Если для этого метода требуется множество разных данных, попробуйте разбить его на несколько мелких функций. Если это невозможно, то создайте класс, специально предназначенный для передачи этих данных.</p><p>Стоит помнить, что все методы и данные, принадлежащие классу, но доступные за пределами этого класса, являются частью его интерфейса. Это значит, что как можно больше методов и полей должны быть приватными.</p><p>В JavaScript переменные, объявленные с помощью var, let или const, автоматически становятся приватными в функции, в которой они объявлены, до тех пор, пока вы не возвращаете или не назначаете их объекту. Во многих других языках используется ключевое слово private. Оно должно стать вашим лучшим другом. Переменные стоит делать публичными только в случаях крайней необходимости.</p><h2>5. Близость</h2><p>Нужно объявлять переменные как можно ближе к месту их использования.</p><p>Инстинкт программиста к организации кода может работать даже против самого программиста. Ведь можно подумать, что организованный код выглядит так:</p><p>getA() и другие подобные функции не определены в этом сегменте кода, но представьте, что они возвращают полезные значения.</p><p>Смотря на этот небольшой метод, можно подумать, что код хорошо организован и легко читается. Но это не так. d, по какой-то причине, объявляется в строке 4, хотя она не используется до строки 9, а это значит, что нужно прочитать весь метод, чтобы убедиться, что переменная больше нигде не используется.</p><p>Хорошо организованный метод будет выглядеть так:</p><p>Теперь понятно, что переменная будет использоваться сразу после ее объявления.</p><p>Конечно, в большинстве случаев ситуация не настолько простая. Что, если b нужно передать два метода: doSomething() и doOtherStuff()? В этом случае вашей задачей будет взвесить параметры и убедиться, что метод все еще прост для чтения (в первую очередь, оставляя его небольшим). В любом случае нужно убедиться в том, что b не объявляется раньше момента ее использования и используется в ближайшем сегменте кода.</p><p>Если делать все последовательно, то можно обнаружить независимость части метода от кода выше и ниже его. Это хорошая возможность поместить его в другой метод. Даже если этот метод будет использоваться только один раз, будет полезно вложить все части операции в понятный, хорошо названный блок.</p><h2>6. Многоуровневое вложение кода (Deep nesting)</h2><p>JavaScript известен своей сложной ситуацией, известной как «callback hell»:</p><figure><img src="https://media.tproger.ru/uploads/2017/09/1.jpg" alt="" /></figure><p>Видите )};,повторяющийся начиная с середины кода? Это и есть пресловутый ад обратного вызова (callback hell). Этого можно избежать, но это история для еще одной статьи.</p><p>Но давайте рассмотрим нечто, что называется if hell.</p><p>Подсчитайте пары фигурных скобок  { }. Шесть из которых вложены. Это слишком много. Этот блок кода трудно читать частично из-за того, что код вот-вот закроет правую сторону экрана, а программисты ненавидят горизонтальную прокрутку, ведь придется прочитать все условия if, чтобы выяснить, как вы попали на строку 10.</p><p>Теперь посмотрим на это:</p><p>Так намного лучше. Теперь это нормальный путь кода, и только в некоторых ситуациях код отклоняется в блок if. Процесс отладки упрощается в разы. И если мы хотим добавить дополнительный код для обработки условий ошибки, можно легко написать пару строк внутри этих блоков if (а представьте, что блоки if в исходном коде также имели бы блоки else, ужас).</p><p>Кроме этого, были удалены блоки try-catch, потому что не нужно подавлять ошибки. Ошибки — ваш друг, и без них приложение станет мусором.</p><h2>7. Чистые функции</h2><p>Чистая функция (или функциональный метод) — это метод, который не меняется и не зависит от внешнего состояния. Другими словами, одинаковые входные данные будут выдавать один и тот же результат, независимо от того, что изменилось за пределами такой чистой функции, а состояние приложения никак не зависит от происходящего внутри функции. Все чистые функции имеют хотя бы один аргумент и, по крайней мере, одно возвращаемое значение.</p><p>Это чистая функция:</p><p>А это не чистая функция:</p><p>Если вам нужно провести отладку первой функции, то поместите ее в отдельную среду, например,jsfiddle или консоль браузера и поиграйте с ней, пока не выясните, что случилось.</p><p>Если же надо сделать отладку второй функции, то придется перерыть всю программу, чтобы убедиться, что найдены все места, где доступны scope.sum и scope.exp. И если нужно переместить эту функцию в другой класс, придется проверить, имеет ли она доступ ко всем тем же областям.</p><p>Не все методы могут стать чистыми, но если в вашем приложении их совсем нет, его полезность будет ограниченной. Чистые функции нужно создавать как можно чаще. Это сделает ваше приложение легким в обслуживании и масштабировании.</p><h2>8. Модульное тестирование</h2><p>Любой класс или метод, который является более, чем голой оболочкой над другим кодом, то есть любым классом или методом, содержащим логику, должен сопровождаться модульным тестом. Этот модульный тест должен запускаться автоматически как часть вашей сборки.</p><p>Правильно написанные модульные тесты устраняют ложные предположения и облегчают понимание кода. Если кто-то не поймет, что делает определенный кусок кода, он всегда может посмотреть на модульный тест и увидеть варианты использования. Написание таких тестов может тормозить процесс разработки, но наличие таких тестов признак того, что вы на верном пути.</p><h2>Заключение</h2><p>Хороший код приносит удовольствие от работы с ним, его поддержка не вызывает у вас особых проблем. Плохой код — пытка для души. Старайтесь писать хороший код.</p><p>При написании кода стоит задавать себе один вопрос: легко ли его будет удалить при ненадобности? Если код глубоко вложен, скопирован и вставлен повсюду, зависит от разных уровней и строк кода, разбросанных по всей программе, люди не будут понимать, как с ним работать, как его читать и изменять. Код должен быть понятным и читабельным, части кода должны быть легко удаляемыми, если больше не несут полезности.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вредные советы: зачем нужен неподдерживаемый код и как его писать</title>
      <link>https://tproger.ru/translations/unmaintainable-code</link>
      <comments>https://tproger.ru/translations/unmaintainable-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Антон]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/unmaintainable-code</guid>
      <description><![CDATA[<p>Шуточная подборка приёмов, после которых простейшая правка отнимает у следующих программистов годы: код должен быть сложным, а не выглядеть таким.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/unmaintainable-code">Вредные советы: зачем нужен неподдерживаемый код и как его писать</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 27 Mar 2017 21:30:46 GMT</pubDate>
      <content:encoded><![CDATA[<p>Мы решили собрать несколько советов по написанию неподдерживаемого кода.</p><p>Все, кто будет пользоваться этим советами впоследствии увидят, что их код невероятно сложно поддерживать, а простейшее изменение займет у программистов, пришедших после них, годы оплачиваемого труда! Впрочем, сложные задачи оплачиваются хорошо, значит преемники скажут «Спасибо».</p><p>Более того, внимательно следуя этим правилам, разработчик сохранит и своё рабочее место — все будут бояться eго сложного кода и бежать от него.</p><p>Тем не менее, помните: при написании неподдерживаемого кода результат не должен выглядеть сложным, он должен быть таковым. «Кривой» код может написать любой дурак, но это заметят и eго уволят, а проект будет переписан с нуля. Наши советы помогут вам и в этом случае, от вас требуется только строгое следование им.</p><h3>Нарушайтe соглашeния</h3><p>Когда цель — помешать другому программисту исправить ваш код, необходимо понять ход его мыслей.</p><p>Давайте представим: перед ним — ваш большой скрипт, и его задача — изменить его. У него нет ни времени, ни желания читать весь код целиком, а тем более досконально изучать. Он хочет побыстрее найти нужное место и сделать своё дело без появления побочных эффектов.</p><p>Другой разработчик рассматривает ваш код, будто чeрeз замочную скважину. Такой подход не даёт ему общей картины, но он ищет лишь тот небольшой фрагмент, который ему необходимо изменить. По крайней мере, он надеется, что искомый фрагмент будет небольшим.</p><p>Главной опорой в его поиске станут соглашения, принятые в программировании об именах пeрeмeнных, названиях функций и мeтодов и т.п. Отсюда следует, что затруднить задачу своему последователю легко: достаточно везде нарушать соглашения, но такой подход, как мы говорили — удел дураков. Подумайте, как поступил бы ниндзя на вашем месте? Он бы следовал соглашениям в общем, но порой нарушал их в неподходящий момент.</p><p>Тщательно разбросанные по коду нарушения соглашений не делают код явно плохим на первый взгляд, зато приносят аналогичный, если не лучший эффект. Давайте разберём небольшой пример: jQuery содержит метод <a href="http://api.jquery.com/wrap/">wrap</a>, задача которого — обeрнуть один элемент вокруг другого. Вот пример такого кода:</p><p>Результат после использования wrap — два элемента, один из которых вложен в другой:</p><p>Добавим к скрипту следующую строчку: div.append('&lt;/span&gt;');. Как вы думаете, что произойдёт? &lt;/span&gt; добавится в конец div, сразу после img? Ничего подобного! Искусный ниндзя уже нанёс свой удар и поведение кода стало неправильным.</p><p>Как правило, методы jQuery работают с элементами, которые им переданы, но не в данном случае. Вызов img.wrap(div) клонирует div и оборачивает вокруг img уже озлобленную суррогатную копию клон. Исходная переменная при этом не меняется.</p><p>После использования append появляются два независимых div — содержащий span и скрытый клон с img. Люди, привыкшие уважать соглашения не предполагают, что wrap неявно клонирует элементы, ведь в jQuery это делает только clone.</p><h3>Пишите короче</h3><p>Думаю многие слышали фразу «Краткость — сестра таланта». Она применима и здесь. Пишите «как короче», а не «как понятнее», ведь меньше букв — уважительная причина нарушения соглашений. Ваш верный помощник в данной ситуации — возможности языка, использованные неочевидным образом.</p><p>Давайте рассмотрим тернарное условие в jQuery:</p><p>Программист, встретивший эту строку, предпримет попытки понять, чему же равно i, а потом наверняка прибежит к вам за разъяснениями. Смело отвечайте: «короче — всегда лучше», затем посвятите его в путь ниндзя-разработчика и вручите <a href="http://lib.ru/POECHIN/lao1.txt">«Дао дэ цзин»</a>.</p><h3>Сокращайте названия переменных</h3><p>Самый удобный способ скрытно «улучшить» код — использовать однобуквенные переменные: a, b, c…</p><p>Такую переменную нельзя найти, используя функцию поиска в текстовом редакторе. Если же кто-то нашёл её, то не сможет понять предназначение.</p><p>Другой вариант — использовать акронимы. Например, ie для Inner Element или mc для Money Counter.</p><h3>Не используйте i для цикла</h3><p>В местах, где переменные из одной буквы общеприняты, например, в счетчике цикла, ни в коем случае не используйте стандартные названия по типу i, j или k. Выбирайте нечто более экзотическое, например, x, y или z.</p><p>Эффективность такого подхода особенно заметна, когда тело цикла занимает несколько страниц, ведь заметить, что переменная является счетчиком цикла, не пролистывая до его начала — невозможно.</p><h3>Транслитерируйте и изменяйте</h3><p>Когда использовать длинные и понятные имена попросту приходится, тоже есть выход. Например, транслитерировать слова: var ssilka или var ssylka.</p><p>Не забудьте использовать разные названия в разных частях проекта, чтобы ещё больше запутать код. Можно ведь и сокращать названия, тогда в одном месте будет написано var link, а в другом — var lnk. Мало того, что такой подход очень действенен и количество ошибок при поддержке кода увеличивается во много раз, так он ещё и предоставляет возможность проявить креативность!</p><h3>Абстрагируйтесь</h3><p>Хороший вариант использования полноценных имён — абстрактные названия, например: data, value, item или elem.</p><p>Вообще, используйте data везде, где это возможно, ведь каждая переменная содержит некоторые данные. Уже заняли это имя? Попробуйте value — такой же универсальный вариант, согласитесь.</p><h3>Добавляйте цифры</h3><p>«Общие» названия закончились, а фантазия иссякла? Можно добавить цифры и получить бесконечный набор переменных: data1, data777, value327, elem9…</p><h3>Используйте тип переменной как имя</h3><p>Другой вариант — назвать переменные по типу данных, которые она хранит. Например: arr, num, obj…</p><p>Казалось бы, это никак не усложнит разработку, но вы только вдумайтесь: название переменной говорит лишь о том, что в ней хранится число, объект или массив, но это и так легко понять, запустив отладчик. Когда непосвящённый будет разбирать ваш код, он не постигнет смысл этой переменной. Что за массив или число у неё внутри? Без долгой медитации над кодом тут не обойтись.</p><h3>Придумывайте похожие имена</h3><p>Ваш код достоин понять только истинно внимательный программист. Так как же проверить, достоин ли читающий?</p><p>Мы предлагаем использовать похожие имена переменных, например, data и date. Заметить разницу при беглом прочтении практически невозможно, а уж заметить опечатку и поправить её…</p><h3>Подумайте о синонимах</h3><p>Конфуций как-то сказал: «Очень трудно найти чёрную кошку в тёмной комнате, особенно когда её там нет». Мы же интерпретировали это в своём стиле и предлагаем вам использовать <i>похожие</i> названия для <i>одинаковых действий</i>.</p><p>Допустим, если метод показывает что-то на экране — назовите его display… (например, displayElement), а в другом месте объявите аналогичный метод как show… (showFrame).</p><p>Иными словами, намекните на тонкое различие между способами работы в методах, когда его нет и в помине.</p><p>Если вы работаете в команде — договоритесь между собой так, чтобы один обязательно использовал display, другой render, а третий — paint.</p><p>Справедлив и обратный вариант, когда у двух функций есть важные отличия. В такой ситуации используйте одно слово для их описания. Например, с print начинается метод печати на принтере printPage, а также метод добавления текста на страницу printText.</p><p>Интересно будет и добавить элемент неожиданности. Допустим, читающий код программист, думает: «Куда же выводит сообщение printMessage?», а он выводит не туда, куда все, а в новое окно.</p><h3>Забудьте про словарь терминов</h3><p>Ни за что не поддавайтесь требованиям написать словарь терминов к проекту, а в ситуации, когда он уже есть — не следуйте ему, а лучше проглотите и скажите, что так и было.</p><p>Пусть программист, читающий ваш код, напрасно ищет различия в helloUser и welcomeVisitor, да пытается понять, когда и что использовать. Вы-то знаете, что на самом деле различий нет, но другой разработчик искать их будет очень долго.</p><h3>Используйте имена повторно</h3><p>Везде, где это возможно, используйте уже существующие имена переменных, функций и свойств. Просто записывайте в них новые значения. Добавлять новые имена можно лишь в случае абсолютной необходимости.</p><p>В функции старайтесь обойтись переменными, которые были переданы в качестве параметров: это не только затруднит понимание того, что сейчас находится в переменной, но и сделает почти невозможным поиск места присвоения значения контейнеру.</p><p>Помните: наша цель — максимально усложнить отладку и заставить читающего код программиста построчно анализировать код и конспектировать изменения переменных для каждой ветки исполнения.</p><p>Продвинутый вариант этого подхода — незаметно (!) подменить переменную на нечто похожее, например:</p><p>Человек, пожелавший добавить действия с elem во вторую часть функции, будет крайне удивлён. Только при отладке, посмотрев весь код, он обнаружит, что имел дело с клоном! Регулярные встречи с этим приемом на практике доказывают, что защититься невозможно. Эффективно даже против опытного ниндзя-программиста.</p><h3>Добавляйте подчеркивания</h3><p>Хороший вариант разнообразить и одновременно усложнить имена переменных — добавить к ним однократные и многократные подчёркивания (_ или __). При этом, в них не должно быть никакого смысла.</p><p>Этим шагом вы достигните двух целей сразу:</p><ol><li>Увеличится длина кода и уменьшится его читабельность.</li><li>Ваш преемник потратит много рабочего времени на поиск смысла ваших действий.</li></ol><p>Ещё большую суматоху в его мысли внесёт наличие подчёркиваний в некоторых частях проекта и отсутствие в других.</p><p>В процессе написания кода вы, скорее всего, будете путаться и смешивать стили: добавлять имена с подчеркиваниями там, где обычно подчеркиваний нет, и наоборот. Это не просто нормально, но даже соответствует третьей цели — увеличение количества ошибок при попытке внести изменения.</p><h3>Покажите любовь к программированию</h3><p>Такие имена, как superElement, megaFrame или niceItem покажут силу вашей любви к разработке, а при благоприятном положении звёзд могут даже привести к просветлению читающего код.</p><p>К тому же, соответствуют требованию к «понятным» именам, ведь что-то же написано: super, mega или nice, хотя и не несёт никакой конкретики. Читающий может попробовать поискать в этом глубинный смысл и замедитировать на часок-другой оплаченного рабочего времени.</p><h3>Перекрывайте внешние переменные</h3><p>Повторное использование имён можно реализовать и таким способом:</p><p>Зашедший в середину функции render, скорее всего, не заметит, что переменная user поменяла своё значение. Он внесёт правки и только после отладки поймёт, что оказался в ловушке.</p><h3>Добавьте «мощности» функциям</h3><p>Не стоит ограничивать действия функций их названием, расширяйте свой кругозор. К примеру, метод validateEmail может не только проверять правильность ввода, но также выводить сообщение об ошибке и очищать поле ввода для новой попытки.</p><p>Стоит добавить хотя бы одно-два «сверх-действия» к своей функции, но они не должны быть очевидны из названия. Истинный же ниндзя-разработчик сделает их и неочевидными из тела функции.</p><p>Такое объединение смежных действий в одну функцию защитит ваш код от повторного использования. Только представьте, что другому разработчику нужно только лишь проверить адрес электронной почты, но не выводить результат. validateEmail, выполняющая и то, и другое, ему совершенно не подходит. Что ж, работодатель оплатит создание новой =)</p><h3>Ещё больше увеличивайте «мощность»</h3><p>Если смотреть на названия таких функций, как isReady, checkPermission или findTags, то становится ясно, что они ничего не меняют. Вы уже понимаете, к чему мы идём? Да, нужно добавить сюда нечто полезное, причём сразу с проверкой.</p><p>Представьте то удивление, что возникнет на лице вашего коллеги, увидевшего, что функция с названием isNumber меняет значения переменных. Такое, несомненно, расширит его границы разумного.</p><p>Ещё одна вариация такого подхода — возврат нестандартного значения.</p><p>Среди блюстителей соглашений известно, что функции is и check обычно возвращают true или false. Покажите им оригинальность своего мышления, пусть вызов checkPermission вернёт объект с результатами проверки! А что, полезно, как-никак. Да и те разработчики, кто попытается написать проверку if (checkPermission(date))…, будут удивлены результатом. Когда они придут к вам, скажите: «Надо читать документацию!» и отправьте эту статью.</p><h3>Заключение</h3><p>Все эти советы пришли из реального кода, порой и из больших проектов от программистов с большим стажем. Возможно, даже больше вашего, так не судите опрометчиво 😉</p><ul><li>Следуйте нескольким советам — и ваш код станет полон сюрпризов.</li><li>Следуйте многим — и ваш код станет истинно вашим, никто не захочет изменять его.</li><li>Следуйте всем — и ваш код станет ценным уроком для молодых разработчиков, ищущих просветления.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>10 вредных советов для начинающих разработчиков</title>
      <link>https://tproger.ru/articles/10-bad-guidelines-for-beginners</link>
      <comments>https://tproger.ru/articles/10-bad-guidelines-for-beginners?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Михайлишин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/10-bad-guidelines-for-beginners</guid>
      <description><![CDATA[<p>Подборка вредных советов для начинающих программистов: другие разработчики могут с ними не согласиться, и именно это делает советы редкими и ценными.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/10-bad-guidelines-for-beginners">10 вредных советов для начинающих разработчиков</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Юмор]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 15 Feb 2017 12:11:39 GMT</pubDate>
      <content:encoded><![CDATA[<p>Другие программисты могут не согласиться с данными советами, но это именно то, что делает их такими редкими и ценными.</p><ol><li>Будьте краткими. Все связанные между собой вещи располагайте на одной строчке.</li><li>Используйте однобуквенные переменные. Добавляйте к ним цифры, если буквы закончатся.</li><li>Не ставьте пробелы. Вообще. Они только для нубов.</li><li>Сначала пишите код, только потом думайте. Не стоит строить планы, пока в них нет потребности.</li><li>Никогда не оправдывайтесь. Если менеджеры не понимают чего-либо, то почему должны вы?</li><li>Если ваши расчёты не сходятся, просто прибавьте единицу и двигайтесь дальше.</li><li>Если у вас есть сомнения, всегда обвиняйте железо. Эти чёртовы микросхемы такие сложные.</li><li>Когда программа не компилируется, просто продолжайте писать код. Как-нибудь само починится.</li><li>Если какая-нибудь функция не работает, замените её на три других. Вам лучше знать, как должно быть.</li><li>Никогда не тестируйте. Если вы написали код, то он работает.</li></ol>]]></content:encoded>
    </item>
    <item>
      <title>Гайд по оформлению кода на С++ от Стэнфордского университета</title>
      <link>https://tproger.ru/translations/stanford-cpp-style-guide</link>
      <comments>https://tproger.ru/translations/stanford-cpp-style-guide?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Глеб Умаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/stanford-cpp-style-guide</guid>
      <description><![CDATA[<p>Стандарты оформления кода на С++ от Стэнфорда: пробелы и отступы, длина строки, описательные имена переменных и пустые линии между функциями.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/stanford-cpp-style-guide">Гайд по оформлению кода на С++ от Стэнфордского университета</a>»</p>]]></description>
      <category><![CDATA[C++]]></category>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 18 Jan 2017 10:31:59 GMT</pubDate>
      <content:encoded><![CDATA[<p>Стэнфордский университет представил <a href="http://stanford.edu/class/archive/cs/cs106b/cs106b.1158/styleguide.shtml">гайд</a> по основным стандартам оформления кода на С++. Умение корректно оформить ваш код является ценным навыком, так как это в разы облегчает работу других. Также у нас есть <a href="https://tproger.ru/articles/15-tips-selfdoc-js/">подобная статья</a>, посвящённая написанию самодокументируемого кода.</p><h3>Пробелы и отступы</h3><p>Отделяйте пробелами фигурные скобки:</p><p>Ставьте пробелы между операторами и операндами:</p><p>Когда строка становится длиннее 100 символов, разделите её на две, сделав перевод на новую строку после оператора, и продолжайте писать:</p><p>Оставляйте пустые линии между функциями и между группами выражений:</p><h3>Названия и переменные</h3><p>Давайте переменным описательные имена, такие как firstName или homeworkScore. Избегайте однобуквенных названий вроде x или c, за исключением итераторов вроде i.</p><p>Называйте переменные и функции, используя верблюжийРегистр. Называйте классы ПаскальнымРегистром, а константы — в ВЕРХНЕМ_РЕГИСТРЕ. Узнать подробнее про верблюжий регистр вы можете в <a href="https://tproger.ru/translations/camelcase-vs-underscores-scientific-showdown/">этой статье</a>.</p><p>Если переменная используется лишь внутри определенного if, то делайте её локальной, объявляя в том же блоке кода, а не глобальной.</p><p>Выбирайте подходящий тип данных для ваших переменных. Если переменная содержит лишь целые числа, то определяйте её как int, а не double.</p><p>Используйте текстовую строку, стандартную для C++, а не С. С++ путает тем, что имеет два вида текстовых строк: класс string из С++ и старый char* (массив символов) из С:</p><p>Если определенная константа часто используется в вашем коде, то обозначьте её как const и всегда ссылайтесь на данную константу, а не на её значение:</p><p>Никогда не объявляйте изменяемую глобальную переменную. Глобальными переменными должны быть только константы. Вместо того, чтобы делать значение глобальным, сделайте его параметром и возвращайте значение, когда необходимо:</p><h3>Базовые выражения С++</h3><p>С++ основан на С, поэтому всегда есть вариант решить задачу «путем С++» и «путем С». Например, когда вы желаете вывести что-либо на системную консоль, вы можете сделать это «путем С++» , использовав оператор вывода cout, в то время как «путем С» вы бы использовали глобальную функцию вроде printf:</p><p>Частенько затрудняетесь с выбором между for и while? Используйте цикл for, когда вы знаете количество повторений, а цикл while, когда количество повторений неизвестно:</p><p>Когда используете операторы управления вроде if / else, for, while, всегда используйте {} и соответствующие отступы, даже если тело всего оператора управления состоит лишь из одной строки:</p><p>Старайтесь избегать использования выражений break или continue. Используйте их только в том случае, если это абсолютно необходимо.</p><p>В C++ есть функция exit, которая немедленно завершает программу. Настоятельно не рекомендуется использовать данную функцию. Программа всегда должна заканчиваться естественно, достигая оператора return функции main.</p><p>Используя выражения if / else, подобающе выбирайте между разнообразными if и else шаблонами в зависимости от условий, относящихся к друг другу. Избегайте излишних тестов if:</p><p>Если у вас есть выражение if / else, которое возвращает логическое значение, возвращайте результаты теста напрямую:</p><p>Никогда не проверяйте значения логического типа, используя == или != с true или false:</p><h3>Чрезмерность</h3><p>Если вы используете один и тот же код дважды или более, то найдите способ удалить излишний код, чтобы он не повторялся. К примеру, его можно поместить во вспомогательную функцию. Если повторяемый код похож, но не совсем, то постарайтесь сделать вспомогательную функцию, которая принимает параметры и представляет разнящуюся часть:</p><p>Переместите общий код из выражения if / else, чтобы он не повторялся:</p><h3>Комментарии</h3><p>Заглавный комментарий. Размещайте заглавный комментарий, который описывает назначение файла, вверху каждого файла. Предположите, что читатель вашего комментария является продвинутым программистом, но не кем-то, кто уже видел ваш код ранее.</p><p>Заголовок функции / конструктора. Разместите заголовочный комментарий на каждом конструкторе и функции вашего файла. Заголовок должен описывать поведение и / или цель функции.</p><p>Параметры / возврат. Если ваша функцию принимает параметры, то кратко опишите их цель и смысл. Если ваша функция возвращает значение — кратко опишите, что она возвращает.</p><p>Исключения. Если ваша функция намеренно выдает какие-то исключения для определенных ошибочных случаев, то это требует упоминания.</p><p>Комментарии на одной строке. Если внутри функции имеется секция кода, которая длинна, сложна или непонятна, то кратко опишите её назначение.</p><p>TODO. Следует удалить все // TODO комментарии перед тем, как заканчивать и сдавать программу.</p><h3>Эффективность</h3><p>Вызывая большую функцию и используя результат несколько раз, сохраните результат в переменной вместо того, чтобы постоянно вызывать данную функцию:</p><h3>Функции и процедурное проектирование</h3><p>Хорошо спроектированная функция имеет следующие характеристики:</p><ul><li>Полностью выполняет четко поставленную задачу;</li><li>Не берет на себя слишком много работы;</li><li>Не связана с другими функциями бесцельно;</li><li>Хранит данные максимально сжато;</li><li>Помогает распознать и разделить структуру программы;</li><li>Помогает избавиться от излишков, которые иначе присутствовали бы в программе.</li></ul><p>Используйте параметры, чтобы отправлять информацию из функции или когда функции нужно возвратить несколько значений. Не используйте параметры без необходимости. Заметьте, что a,b, и с не являются параметрами в нижеприведенной функции, так как это не нужно:</p><p>Когда требуется вернуть значение из функции, используйте значение return:</p><p>Отправляя объект в функцию как параметр, вы должны передавать его по ссылке, так как если он будет передан как значение, то будет скопирован весь объект. Копирование объектов требует больших затрат памяти.</p><p>Используйте ссылочные переменные, а не указатели. Одна из причин — это то, что ссылочные переменные, в отличие от указателей, не могут принимать значение NULL:</p><p>Если вы передаете объект в функцию и код не изменит вида объекта — передайте его как const-ссылку:</p><p>Избегайте “цепных” вызовов, когда множество функций вызывают друг друга по цепочке, не возвращая значение в main. Убедитесь, что main является кратким описанием всей программы:</p><h3>Проектирование классов</h3><p>Инкапсуляция. Отделяйте ваши объекты, делая все поля данных в вашем классе private:</p><p>.h vs .cpp. Всегда размещайте объявления классов и их частей в собственные файлы, ClassName.h. Всегда сворачивайте файлы объявления классов .h в блок препроцессоров #ifndef / define / endif, чтобы избежать множественных объявлений одного класса:</p><p>class vs struct. Всегда используйте class, только если вы не создаете очень маленький и простой вид данных, для которого нужны лишь несколько публичных переменных и, возможно, конструктор для их инициализации.</p><p>Избегайте ненужных полей. Используйте поля, чтобы хранить важные данные о ваших объектах, но не временные значения, которые используются единожды.</p>]]></content:encoded>
    </item>
    <item>
      <title>Производительность программы против читаемости и простоты кода: в пользу чего стоит делать выбор?</title>
      <link>https://tproger.ru/translations/performance-vs-simplicity</link>
      <comments>https://tproger.ru/translations/performance-vs-simplicity?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/performance-vs-simplicity</guid>
      <description><![CDATA[<p>Arne Mertz объясняет на примере C++, почему не стоит жертвовать простотой и чистотой кода ради скорости и чем производительность отличается от эффективности.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/performance-vs-simplicity">Производительность программы против читаемости и простоты кода: в пользу чего стоит делать выбор?</a>»</p>]]></description>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 04 Oct 2016 19:55:52 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рассказывает Arne Mertz</p><p>Одной из сильных сторон C++ является возможность написания очень производительного кода. Но значит ли это, что мы должны постоянно беспокоиться о производительности и писать весь код настолько производительно, насколько это возможно? Должны ли мы отказаться от простоты ради этого? А стоит ли?</p><p>Лично я так не думаю и могу привести много причин, почему не стоит жертвовать простотой и чистотой кода для повышения производительности. Я бы предпочел, чтобы все изначально писали простой и чистый код. Вот несколько из причин для такого выбора.</p><h3>Производительность ≠ эффективность</h3><p>В первую очередь нужно научиться различать производительность и эффективность. В чем разница? Если коротко: производительность влияет на то, как быстро вы что-то делаете, а эффективность — на то, сколько это занимает у вас времени.</p><p>Вроде бы одно и то же, скажете вы, и будете неправы. Представьте, что вы перемещаетесь из пункта А в пункт Б. Эффективно будет пойти кратчайшим путем. Производительно будет, если вы побежите. То есть, если вы на всех парах промчитесь по всему району, чтобы попасть к соседу, это будет производительно, но не эффективно.</p><p>В программировании циклы сильно влияют на время выполнения программы. В этом случае производительность будет отвечать за время выполнения одной итерации, а эффективность — за их количество, которое можно уменьшить лучшим алгоритмом.</p><p>Иногда эти понятия не пересекаются. Более эффективный алгоритм может быть менее производительным. Однако, прежде чем выжать максимум производительности из участка кода, убедитесь, что он эффективен. Только когда вы учли все возможности в плане эффективности, можно начать заниматься повышением производительности.</p><blockquote>Порой для получения желаемой скорости достаточно повысить эффективность кода и не беспокоиться о производительности.</blockquote><h3>Производительность нужна не всегда</h3><p>Это очевидно, но многие программисты, особенно начинающие, не всегда понимают это. На форумах висят сотни вопросов об оптимизации кода. При этом, если задается вопрос о том, является ли этот участок кода “бутылочным горлышком” для общей производительности, ответ на него чаще всего дается отрицательный.</p><p>Говорят, что 80% времени своей работы программа занимается выполнением 20% кода. Но точные числа здесь не важны. Главным является тот факт, что программа тратит большую часть времени на исполнение меньшей части кода.</p><p>Иными словами, это означает, что почти весь код мало влияет на время выполнения, и его оптимизация прироста скорости не даст.</p><blockquote>Не оптимизируйте код, который не влияет на общую производительность программы.</blockquote><h3>На самом деле мы не знаем, как правильно оптимизировать</h3><p>О да, как я посмел 🙂 Дело в том, что огромное влияние на время выполнения программы имеет количество инструкций, исполняемых процессором. А их задаем не мы, а компилятор и его оптимизатор.</p><p>Оптимизаторы бывают разные, и если вы не эксперт, то вряд ли вы догадаетесь, что они делают с нетривиальным участком кода. Оптимизаторы могут удалять временные объекты, делать функции встроенными, порой даже во время линкования, и даже перемешивать и удалять многие из этих инструкций.</p><p>Так что мы можем сделать для повышения производительности с учетом этих суперсил компилятора и нашего незнания того, какой код оптимален? На первый взгляд — ничего. И если мы действительно беспокоимся о производительности, стоит положиться не на воображение и опыт, а на инструменты.</p><blockquote>Изначально пишите поддерживаемый код, поскольку он вполне может быть достаточно производительным. Для улучшения производительности используйте профайлер.</blockquote><p>Конечно же, вышесказанное не значит, что стоит писать непроизводительный код. Если есть два способа написать одинаково читаемый код, выбирайте более производительный. Например, используйте ++iter вместо iter++, если вам не нужно сохранять результат выражения, и так далее.</p><h3>Производительность и простота — не взаимоисключающие признаки</h3><p>Серьезный вклад во время выполнения программы также вносит структура и расположение данных в памяти. Об этом можно прочитать <a href="http://channel9.msdn.com/Events/CPP/C-PP-Con-2014/Efficiency-with-Algorithms-Performance-with-Data-Structures">хорошую статью</a>, я не буду заострять свое внимание на этом вопросе.</p><p>Главное — если вы плохо структуризовали данные в памяти, это точно приведет к ухудшению производительности.</p><blockquote>Убедитесь, что вы используете самые производительные структуры данных, прежде чем начать оптимизировать сам код.</blockquote><p>Есть еще один способ написания производительного и простого кода: <a href="http://arne-mertz.de/2015/02/know-your-libraries/">используйте проверенные библиотеки</a>. Их авторы, как правило, умные ребята, и разбираются в производительности. Поэтому, если вы будете использовать библиотеки, а не свои решения, код будет не только проще, но и производительней.</p><blockquote>Используйте библиотеки, но только если профайлер не жалуется на их плохую производительность.</blockquote><h3>Заключение</h3><p>Изначально пишите простой и читаемый код. Если же вы нашли проблему в производительности, исправить ее можно, не превращая код в быстрый, но непонятный беспорядок. Жертвуйте простотой ради производительности только в крайнем случае, и всегда используйте профайлер.</p><p>А что вы думаете по этому поводу? Делитесь мнениями в комментариях, и да начнётся холивар 🙂</p>]]></content:encoded>
    </item>
    <item>
      <title>Советы по языку программирования Си: 10 полезных приемов</title>
      <link>https://tproger.ru/translations/10-useful-things-in-c</link>
      <comments>https://tproger.ru/translations/10-useful-things-in-c?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/10-useful-things-in-c</guid>
      <description><![CDATA[<p>Приёмы для начинающих и опытных Си-разработчиков — от указателей на функции до других возможностей языка, где легко выстрелить себе в ногу.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/10-useful-things-in-c">Советы по языку программирования Си: 10 полезных приемов</a>»</p>]]></description>
      <category><![CDATA[Низкоуровневое программирование]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Язык Си]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 30 Sep 2016 21:02:39 GMT</pubDate>
      <content:encoded><![CDATA[<p>Си — это один из самых важных и широко распространённых языков программирования. Его можно использовать не только для общих целей, но и для написания низкоуровневых программ, работающих с “железом”. Си позволяет программисту многое из того, чего не позволяют другие языки. Однако в этом кроется как сильная, так и слабая сторона языка: можно писать высокопроизводительный код, но гораздо проще выстрелить себе в ногу. Поэтому мы делимся с вами десятью советами, которые пригодятся как начинающим, так и опытным Си-разработчикам.</p><h3>1. Указатели на функцию</h3><p>Иногда бывает удобно хранить функцию в переменной. Этот способ нечасто используется в повседневном программировании, но его можно использовать для улучшения модульности программы или для обработки события.</p><p>Этот приём заключается в следующем. Сперва нужно задать тип “указатель на функцию, возвращающую что-то” и использовать его для объявления переменной. Рассмотрим простой пример. Сначала я задаю тип PFC (Pointer to a Function returning a Character):</p><p>Затем использую его для объявления переменной z:</p><p>Определяю функцию a():</p><p>Адрес функции теперь хранится в z:</p><p>Заметим, что вам не нужен оператор &amp; ("address-of"); компилятор знает, что a должна быть адресом функции. Так происходит из-за того, что с функцией можно произвести лишь две операции: 1) вызвать её или 2) взять её адрес. Поскольку вызова функции не происходит (отсутствуют скобки), остаётся лишь вариант с получением адреса, который помещается в z.</p><p>Чтобы вызвать функцию, адрес которой находится в z, просто добавьте скобки:</p><h3>2. Списки аргументов переменной длины</h3><p>Обычно вы объявляете функцию, которая принимает фиксированное число аргументов. Тем не менее, можно написать функцию, которая принимает любое их количество. Стандартная функция printf() тому доказательство. Разумеется, вы можете сами написать подобную функцию. Вот пример:</p><p>Первый аргумент, arg_count — это целое, в котором хранится реальное число аргументов, следующих за ним в списке переменных, указанном как три точки.</p><p>С переменными аргументами работают несколько встроенных функций и макросов: va_list, va_start, va_arg и va_end (они определены в stdarg.h).</p><p>Сперва вам нужно объявить указатель на список аргументов:</p><p>Затем установите argp в первый аргумент переменной части. Это первый аргумент после последнего фиксированного (в нашем случае arg_count):</p><p>Теперь извлекаем каждую переменную по очереди, используя va_arg:</p><p>Заметим, что вам нужно знать тип аргумента заранее (в нашем случае int) и число аргументов (у нас задаётся фиксированным arg_count).</p><p>Наконец, нужно убраться при помощи va_end:</p><h3>3. Проверка и установка отдельных битов</h3><p><a href="https://tproger.ru/links/bitwise-tricks/">Битовые операции</a> иногда воспринимаются как некий сорт тёмной магии, используемой продвинутыми программистами. Да, работа с битами напрямую может быть весьма непонятной, но понимание этого процесса может вам пригодиться.</p><p>Обсудим, зачем это вообще нужно. Программы часто используют переменные-флаги для хранения булевых величин. У вас в коде вполне могут встречаться такие переменные:</p><p>Если они как-то связаны, как в примере выше (они все описывают состояние движения), то зачастую бывает удобнее хранить их в одной “переменной состояния” и использовать каждый бит для задания того или иного состояния:</p><p>Тогда вы сможете использовать битовые операции для задания или обнуления отдельных битов:</p><p>Преимуществом является то, что вся информация хранится в одном месте, и очевидно, что вы работаете с одной логической сущностью.</p><p>В архиве с кодом, который будет дан в конце статьи, есть пример работы с битами.</p><p>Чтобы установить заданный бит переменной value (в диапазоне от 0 до 31), используйте такое выражение:</p><p>Для очистки бита используйте:</p><p>А для получения значения бита:</p><h3>4. Ленивые логические операторы</h3><p>Логические операторы Си, &amp;&amp; (“и”) и || (“или”), позволяют вам составлять цепочки условий в тех случаях, когда действие должно выполняться при выполнении всех условий (&amp;&amp;) или только одного (||). Но в Си также есть операторы &amp; и |. Очень важно понимать разницу между ними. Если вкратце, двухсимвольные операторы (&amp;&amp; и ||) называются “ленивыми” операторами. Если они используются между двумя выражениями, то второе будет выполнено, только если первое оказалось верным, иначе оно пропускается. Рассмотрим пример:</p><p>Тест (int)f &amp;&amp; feof(f) должен вернуть истинный результат, когда будет достигнут конец файла f. Сперва тест вычисляет f; она будет равна нулю (ложное значение), если файл не был открыт. Это ошибка, поэтому попытка чтения файла не увенчается успехом. Однако, поскольку первая часть теста провалена, вторая не будет обработана, и feof() не будет запущена. Этот пример демонстрирует корректное использование ленивого оператора. Теперь посмотрите на этот код:</p><p>В этом случае используется оператор &amp;, а не &amp;&amp;. Оператор &amp; — это инструкция для выполнения обоих выражений при любых условиях. Поэтому, даже если первая часть теста провалится, вторая будет выполнена. Это может привести к различным ошибкам.</p><h3>5. Тернарные операторы</h3><p>Операция называется тернарной. когда принимает три операнда. В Си тернарный оператор ? : можно использовать для сокращённой записи тестов if..else. Общий синтаксис выглядит так:</p><p>Пусть у нас есть две целых переменных, t and items. Мы можем использовать if..else для проверки значения items и присваивания её значения переменной t таким образом:</p><p>Используя тернарный оператор, эту запись можно сократить до одной строки:</p><figure><img src="https://media.tproger.ru/uploads/2016/09/2-3.png" alt="" /></figure><p>Если вы не привыкли к тернарным операторам, то они могут показаться вам странными, но на самом деле они весьма удобны.</p><p>Рассмотрим ещё один пример. Этот код выводит первую строку, когда у нас один предмет, и вторую, когда их несколько:</p><p>Это можно переписать так:</p><h3>6. Стек</h3><p><a href="https://ru.wikipedia.org/wiki/Стек">Стек</a> — это LIFO-хранилище. Вы можете использовать адресную арифметику для добавления элементов в стек или извлечения их из него. Часто под стеком подразумевается структура, используемая Си для хранения локальных переменных функции. Но на самом деле стек — это общий тип структуры данных, которым вы спокойно можете пользоваться.</p><p>Код ниже задаёт очень маленький стек: массив _stack из двух целых. Помните, что при тестировании всегда лучше использовать небольшие числа. Если код содержит ошибки, найти их при работе с массивом из 2 элементов будет проще, чем если их будет 100. Также объявляется указатель на стек _sp и устанавливается в основание стека _stack:</p><p>Теперь определим функцию push(), которая помещает целое в стек. Она возвращает новое число элементов в стеке или -1, если стек полон:</p><p>Для получения элементов стека нужна функция pop(). Она возвращает новое число элементов в стеке или -1, если он пуст:</p><p>А вот пример, демонстрирующий работу со стеком:</p><h3>7. Копирование данных</h3><p>Вот три способа копирования данных. Первый использует стандартную функцию memcpy(), которая копирует n байт из src в dst:</p><p>Теперь посмотрим на самодельную альтернативу memcpy(). Она может быть полезной, если копируемые данные нужно как-то обработать:</p><p>И наконец, функция, использующая 32-битные целые для ускорения копирования. Помните, что скорость в конечном итоге зависит от оптимизации компилятора. В этом примере предполагается, что счётчик данных n кратен 4 из-за работы с 4-байтовыми указателями:</p><p>Примеры можно найти в архиве ниже.</p><h3>8. Использование заголовочных файлов</h3><p>Си использует заголовочные файлы (.h), которые могут содержать объявления функций или констант. Заголовочный файл можно импортировать в код двумя способами: если файл предоставляется компилятором, используйте #include &lt;string.h&gt;, а если файл написан вами — #include "mystring.h". В сложных программах есть риск того, что вы можете подключить один и тот же заголовочный файл несколько раз.</p><figure><img src="https://media.tproger.ru/uploads/2016/09/3-3.png" alt="" /></figure><p>Предположим, что у нас есть простой заголовочный файл, header1.h, содержащий следующие определения:</p><p>Затем создадим другой файл header2.h, содержащий это:</p><p>Добавим в нашу программу, main.c, это:</p><p>При компиляции программы мы получим ошибку компиляции, потому что T_SIZE будет объявлена дважды (её определение в header1 подключено к двум разным файлам). Мы должны подключить header1 к header2 для того, чтобы header2 компилировался в тех случаях, когда header1 не используется. И как это исправить? Можно написать макрос для header1:</p><p>Эта проблема настолько распространена, что многие IDE делают это за вас. Тем не менее, если вы будете делать это вручную, делайте это осторожно.</p><h3>9. Скобки: нужны ли они?</h3><p>Вот несколько простых правил:</p><ol><li>Скобки нужно использовать для изменения порядка выполнения операторов. Например, 3 * (4 + 3) — не то же самое, что 3 * 4 + 3 .</li><li>Скобки можно использовать для улучшения читаемости. Здесь они, очевидно, не нужны:t = items &gt; 0 ? items : -items;Приоритет оператора || ниже, чем &lt; и &gt;. Однако, в этом случае скобки точно не будут лишними:(x &gt; 0) || (x &lt; 100 &amp; y &gt; 10) || (y &lt; 0)</li><li>Скобки стоит использовать в макросах:#define MYCONST (4 + 3)Вы не знаете, где будете использовать эту константу, поэтому скобки нужны. Рассмотрим такой случай применения:3 * MYCONSTБез скобок результат получился бы неверным из-за порядка выполнения операторов.</li></ol><p>Но в одном месте скобки точно не нужны: в выражении после return. Например, это…</p><p>…выполнится так же, как это:</p><h3>10. Массивы как адреса</h3><p>Программисты, которые учат Си после какого-то другого языка, часто удивляются, когда Си работает с массивами как с адресами и наоборот. Массив — это контейнер фиксированного размера, а адрес — это число, связанное с местом в памяти; разве они связаны?</p><p>Выходит, что да.</p><p>Си прав: массив — это просто адрес базы в блоке памяти, а форма записи массива, например, в Java или JavaScript — просто синтаксический сахар.</p><p>Присмотритесь к этому коду:</p><p>Первый цикл здесь копирует адрес каждого элемента массива в сам массив:</p><p>На каждой итерации адрес увеличивается на i. Поэтому адрес переменной _x будет первым элементом, а каждый следующий адрес — адресом  _x плюс 1. Когда мы прибавляем 1 к адресу массива, компилятор Си вычисляет подходящий сдвиг в зависимости от типа данных (в нашем случае 4 байта для массива целых).</p><p>Второй цикл выводит значения, хранящиеся в массиве, сперва выводя адрес элемента _x + i, затем значение элемента через привычный вид массива _x[i], а потом содержимое массива с использованием адресной нотации (где оператор * возвращает содержимое памяти по адресу в скобках): *(_x + i). Во всех случаях значения будут одинаковыми. Это наглядно демонстрирует, что массив и адрес — это одно и то же.</p><p>Обратите внимание, что для получения адреса массива вам не нужен оператор &amp;, поскольку компилятор считает, что массив и есть адрес.</p><p>Для того, чтобы попробовать применить эти советы на практике, вы можете <a href="https://web.archive.org/web/20160629110159/https://dujk9xa5fr1wz.cloudfront.net/extra_html/mix/c_tips.zip">скачать</a> исходники.</p>]]></content:encoded>
    </item>
    <item>
      <title>16 лучших практик для написания читаемого кода: что нужно знать любому программисту перед устройством на работу и не только</title>
      <link>https://tproger.ru/articles/how-to-write-readable-code</link>
      <comments>https://tproger.ru/articles/how-to-write-readable-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Тарас Сереванн]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/how-to-write-readable-code</guid>
      <description><![CDATA[<p>Комментирование и документация, стандарты оформления и другие практики, которые помогают писать код, понятный коллегам и удобный для поддержки.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/how-to-write-readable-code">16 лучших практик для написания читаемого кода: что нужно знать любому программисту перед устройством на работу и не только</a>»</p>]]></description>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[PHP]]></category>
      <category><![CDATA[Материалы от друзей Tproger]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 01 Jul 2016 12:28:07 GMT</pubDate>
      <content:encoded><![CDATA[<p>Читаемость кода — универсальный показатель в мире программирования. Это одна из первых вещей, которые <a href="https://tproger.ru/articles/junior-developer-should-know/">должен знать разработчик</a>. В этой статье мы рассмотрим 16 лучших практик, которые помогают писать более читаемый код.</p><p>Публикуем перевод, сделанный для Tproger международной IT-компанией Noveo.</p><h3>1. Комментирование и документация</h3><p>За последние 5 лет среды разработки (IDE) прошли большой путь. Это сделало комментирование кода важным как никогда. Использование определённых стандартов комментирования позволяет среде разработки и другим инструментам использовать комментарии определённым образом.</p><figure><img src="https://media.tproger.ru/uploads/2016/06/readable_code_1.png" alt="" /></figure><p>Рассмотрим этот пример:<br /></p><p>Комментарий, который я добавил при определении функции, можно просматривать каждый раз, когда я использую функцию, даже из другого файла.</p><figure><img src="https://media.tproger.ru/uploads/2016/06/readable_code_2.png" alt="" /></figure><p>Вот ещё один пример, где я вызываю функцию из сторонней библиотеки:<br /></p><h3>2. Последовательные отступы</h3><p>Я думаю, вы уже знаете, как расставлять отступы в коде. В любом случае, нужно напомнить, что последовательность в отступах будет хорошей идеей.</p><p>Есть несколько вариантов выставления отступов:</p><p>Стиль 1:</p><p>Стиль 2</p><p>Стиль 3</p><p>Раньше я использовал второй стиль, но недавно перешёл на первый. Впрочем, это дело вкуса. Не существует “лучшего” стиля, которого должны придерживаться все без исключения. На самом деле лучший стиль – это последовательный стиль. Если вы участвуете в проекте в составе команды, необходимо придерживаться стиля, который уже используется на проекте.</p><p>Стили отступов не всегда можно отличить друг от друга: иногда смешиваются различные правила. Например, в PEAR Coding Standards открывающая скобка (“{“) остаётся на той же строке, что и контролирующие структуры, но переносится на следующую строку при определении функций.</p><p>Стиль PEAR:</p><p>Также можно отметить, что вместо табуляции для отступов используется четыре пробела.</p><p><a href="http://en.wikipedia.org/wiki/Indent_style">Здесь</a> находится статья Википедии, где можно прочитать о различных стилях отступов. А <a href="http://editorconfig.org/">здесь</a> вы можете найти отличный инструмент, который позволяет создать единый формат настроек и раз и навсегда решить вопросы вроде “табы или пробелы” для всех IDE и всех языков программирования.</p><h3>3. Избегайте очевидных комментариев</h3><p>Комментировать код — это просто прекрасно, но иногда комментарии становятся необязательными или попросту лишними.</p><p>Возьмём этот пример:</p><p>Когда текст настолько очевиден, нет смысла дублировать его комментарием.</p><p>Если же комментарий необходим, можно сделать это одной строкой:</p><h3>4. Группировка кода</h3><p>Как правило, для выполнения определённых задач требуется несколько строк кода. Разумным будет оформлять такие задачи как отдельные блоки с разрывами между ними.</p><p>Приведём пример:</p><h3>Последовательность в наименованиях</h3><p>PHP сам не всегда бывает последовательным в наименованиях:</p><ol><li>strpos() при str_split()</li><li>imagetypes() при image_type_to_extension()</li></ol><p>Прежде всего, в именах должны быть различимы граница слов. Есть два популярных варианта:</p><ol><li>camelCase: заглавной становится первая буква каждого слова, кроме первого.</li><li>Нижнее_Подчёркивание: слова разделяются нижним подчёркиванием, например, mysql_real_escape_string().</li></ol><p>Существование нескольких опций создаёт ту же ситуацию, что и с отступами. Если на проекте уже существуют договорённости, нужно им следовать. Помимо того, некоторые платформы стремятся к использованию определённого стиля.</p><p>Например, большая часть проектов на Java использует camelCase, в то время как в PHP более популярно нижнее подчёркивание.</p><p>Здесь также возможно смешение. Некоторые разработчики используют нижнее подчёркивание для функций и названий классов, но предпочитают camelCase при написании названий методов класса:</p><p>Повторюсь: нет «лучшего» стиля. Просто будьте последовательны.</p><h3>5. Принцип DRY</h3><p>DRY — аббревиатура от английского Don’t Repeat Yourself (не повторяйтесь). Иногда используется вариант DIE — Duplication Is Evil (повторение – это зло).</p><p>Принцип гласит: «Каждый элемент знания должен иметь в системе единственное, не вызывающее сомнений и авторитетное значение».</p><p>Цель большинства приложений (или компьютеров в целом) — автоматизировать повторяющиеся задачи. Этого принципа нужно придерживаться в любом коде, даже когда речь идёт о веб-приложениях. Один фрагмент не должен повторяться в коде снова и снова.</p><p>Например, бОльшая часть веб-приложений состоит из нескольких страниц. Вероятность того, что эти страницы будут содержать одинаковые элементы, весьма высока. Обычно для этой цели используются header и footer. Не самой лучшей идеей будет копировать их для каждой страницы.</p><p>Вот как создаются шаблоны в CodeIgniter:</p><h3>6. Избегайте глубокой вложенности кода</h3><p>Слишком большое количество уровней вложения затрудняет чтение и понимание кода.</p><p>Ради удобства чтения можно изменить код, чтобы уменьшить количество уровней вложения:</p><h3>7. Ограничьте длину строки</h3><p>Нашим глазам удобнее читать длинные и узкие колонки текста. Именно поэтому статьи в газетах обычно выглядят так:</p><figure><img src="https://media.tproger.ru/uploads/2016/06/newspaper.jpg" alt="" /></figure><p>Избегать длинных строк кода — хорошая практика.</p><p>Кроме того, если кому-то потребуется читать код из окна терминала (как, например, пользователям Vim), то будет разумно ограничить длину строки 80 символами.</p><h3>8. Организация файлов и папок</h3><p>Технически возможно написать приложение полностью в одном файле. Но чтение и поддержка такого проекта превратятся в кошмар.</p><p>На своих первых проектах я знал об идее создания «включённых файлов», но я тогда был не очень организованным человеком. Я создал папку “inc” с двумя файлами: db.php и functions.php. Но приложения росли, файл с функциями стал огромным, и поддерживать его стало невозможно.</p><p>Чтобы избежать этого можно или использовать фреймворк, или имитировать файловую структуру. Вот так, например, выглядит CodeIgniter:</p><figure><img src="https://media.tproger.ru/uploads/2016/06/readable_code_3.png" alt="" /></figure><h3>10. Последовательность во временных именах</h3><p>Как правило, названия переменных описывают их суть и состоят из нескольких слов. Но это не всегда относится ко временным переменным, которые иногда могут состоять из одного символа.</p><p>Нужно поддерживать последовательность имён для временных переменных, у которых есть определённая роль. Вот несколько примеров, которые я использую в коде:</p><h3>11. Пишите специальные слова SQL заглавными буквами</h3><p>Взаимодействие с базой данных — существенная часть большинства веб-приложений. Если вы пишете SQL-запросы, то будет разумно сделать читаемыми и их.</p><p>Несмотря на то, что специальные слова и названия функций SQL нечувствительны к регистру, их обычно пишут заглавными буквами, чтобы отличать от названий таблиц и колонок.</p><h3>12. Разделение кода и данных</h3><p>Это ещё один принцип, который относится практически ко всем языкам программирования во всех средах разработки. В случае веб-разработки «данные» обычно обозначают вывод HTML.</p><p>Много лет назад, во время первого релиза PHP, это было реализовано как движок шаблонов. Тогда HTML-файлы с несколькими строчками на PHP были привычным делом. В любом случае, с течением времени ситуация сильно изменилась и сайты стали более динамичными и функциональными. Сейчас код составляет значительную часть веб-приложений, и соединять его с HTML уже будет неразумно.</p><p>Вы можете или самостоятельно применить этот принцип к своему приложению, или использовать сторонние инструменты (шаблонизаторы, фреймворки, CMS) и следовать их договорённостям.</p><p>Популярные PHP фреймворки:</p><ol><li>CodeIgniter</li><li>Zend Framework</li><li>Cake PHP</li><li>Symfony</li></ol><p>Популярные шаблонизаторы:</p><ol><li>Smarty</li><li>Dwoo</li><li>Savant</li></ol><h3>13. Изменяйте синтаксис внутри шаблонов</h3><p>Вы можете не использовать модные шаблонизаторы, ограничиваясь плоским PHP внутри своих файлов шаблонов. Это не обязательно будет нарушением принципа разделения кода и данных, если вложенный код напрямую относится к выводу и он читаем. В таком случае вам будет нужно изменить синтаксис для контрольных структур.</p><p>Приведу пример:</p><p>Это позволяет избежать многих фигурных скобок. Кроме того, по отступам и структуре код становится похож на HTML-разметку.</p><h3>14. Объектно-ориентированное против процедурного</h3><p>Объектно-ориентированное программирование позволяет писать хорошо структурированный код, но это не значит, что вы должны полностью отказаться от процедурного программирования. На самом деле смешивание этих подходов может дать хорошие результаты.</p><p>Объекты можно использовать для представления данных, обычно они располагаются в базе данных.</p><p>Процедуры и функции можно использовать для отдельных задач, которые могут выполняться отдельно.</p><h3>15. Читайте Open Source код</h3><p>Open Source проекты создаются как результат труда многих людей. Такие проекты должны быть очень доступными для чтения, чтобы команда могла работать максимально эффективно. Следовательно, будет очень полезно просматривать код таких проектов, чтобы понять, какие методики применяют их разработчики.</p><figure><img src="https://media.tproger.ru/uploads/2016/06/open_source.png" alt="" /></figure><h3>16. Рефакторинг</h3><p>Когда вы проводите рефакторинг, то меняете код, не изменяя возможности системы. Это можно представить как “чистку” кода для повышения читаемости и качества.</p><p>Рефакторинг не относится к багфиксингу или добавлению функционала. Можно рефакторить код, который был написан вчера, пока он ещё свеж в вашей голове, чтобы он был более читаемым и доступным для переиспользования, когда вы вернётесь к нему два месяца спустя. Как гласит старая истина «рефакторьте раньше, рефакторьте чаще».</p><p>Вы можете использовать любые из перечисленных «лучших практик» в процессе рефакторинга.</p><p>Перевод подготовлен международной IT-компанией Noveo.</p>]]></content:encoded>
    </item>
    <item>
      <title>20 вещей, которые отличают PHP-программиста от обезьянки</title>
      <link>https://tproger.ru/translations/20-tips-for-php-prof</link>
      <comments>https://tproger.ru/translations/20-tips-for-php-prof?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Лапа]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/20-tips-for-php-prof</guid>
      <description><![CDATA[<p>Советы по читаемости кода и проектированию для тех, кто пишет серверную часть на PHP и не хочет собирать систему из кусков со Stack Overflow.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/20-tips-for-php-prof">20 вещей, которые отличают PHP-программиста от обезьянки</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[PHP]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 02 Jun 2016 22:58:09 GMT</pubDate>
      <content:encoded><![CDATA[<p>PHP — самый популярный язык для написания кода серверной части. Одной и той же цели на нем можно достичь несколькими путями: можно спроектировать красивую и легко поддерживаемую систему, а можно быстро слепить вместе куски кода со Stack Overflow, не забивая себе чересчур голову такими вещами, как правила проектирования и читаемость кода.</p><p>Конечно, даже если вы пока еще не гуру разработки, вы все равно захотите писать код, из-за которого окружающим не захочется плакать. Tproger вас выручит — в этой статье собрано 20 советов, каждый из которых поможет вам улучшить читаемость кода и за следование которым вам потом скажут спасибо. А в перспективе прилежное следование этим советам поможет вам стать ближе к статусу опытного и внимательно относящегося к деталям разработчика.</p><h3>Используйте <p>Не используйте &lt;? ?&gt; и прочие способы размещения в файле php-скриптов. Да, может быть, у вас все работает, а вот на другом сервере — не факт. На некоторых серверах короткие тэги вообще отключены. Не рискуйте, используйте только &lt;?php. И кстати, не ставьте закрывающий php-тег — это признак дурного тона. А еще закрывающий тэг в конце может привести к неожиданным проблемам, связанным со случайно поставленным пробелом или переводом строки в конце вывода.</p><h3>Отделяйте файлы с параметрами</h3><p>Нет ни одной достаточно веской причины, которая бы оправдала хранение настроек в одном файле со скриптом. Всегда создавайте отдельный файл и в самом начале скрипта его подключайте. Вы поймете, как это важно, когда вам придется редактировать кучу файлов из-за изменения одного параметра. Это ведь совсем несложно:</p><p>include("config.php");</p><h3>Комментарии — ваши друзья</h3><p>Конечно, если вы спешите или набиваете код на волне вдохновения, становится как-то не до комментариев. Но код, написанный давно, понимать трудно — даже если писали его вы. Лучше помогите себе парой комментариев в ключевых местах, чтобы потом сократить время на понимание очередного скрипта.</p><p>Правда, просто? Еще стоит обратить внимание на <a href="https://ru.wikipedia.org/wiki/PHPDoc">PHPDoc</a>.</p><h3>Грамотно форматируйте код</h3><p>Нет ничего хуже огромной стены кода, автор которого явно не знал о существовании кнопки Tab. Не спасут даже комментарии — отступы придумали для того, чтобы логически отделять друг от друга фрагменты кода. А использование или неиспользование отступов много говорит о вас как о программисте. Вот этот код отформатирован неправильно:</p><p>А вот это — тот же самый код, но с правильным форматированием:</p><p>Если вы хотите точно знать, какой способ форматирования кода правильный — почитайте <a href="http://www.php-fig.org/psr/psr-2/">PSR-ы</a>.</p><h3>Давайте переменным понятные имена</h3><p>Конечно, к единому мнению по этому вопросу прийти нельзя. camelCase или under_score? Нужна ли <a href="https://ru.wikipedia.org/wiki/%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B0%D1%8F_%D0%BD%D0%BE%D1%82%D0%B0%D1%86%D0%B8%D1%8F">Венгерская нотация</a>? Важно здесь одно: раз и навсегда определитесь, что вам ближе. А даже если вам и захочется изменить стиль, то пожалуйста, не делайте это посреди проекта! Разные варианты именования переменных в одном проекте или, что еще хуже, в одном файле — это ужасно. И никаких магических чисел! Не поленитесь использовать константы.</p><h3>Инициализируйте переменные</h3><p>Конечно, PHP автоматически создает переменные при попытке к ним обратиться. Но вам не кажется, что пользоваться этой особенностью довольно рискованно? Хорошей практикой считается всегда инициализировать переменные еще перед первым использованием. Это сделает код понятнее и поможет убедиться, что вы не обращаетесь случайно к неинициализированной переменной.</p><h3>Булева переменная ложна, иначе — истинна</h3><p>Если вы проверяете какое-то условие и потом результат сравнения сохраняете в булевом значении, при инициализации переменной для результата (мы ведь всегда заранее инициализируем переменную, помните?) сначала присваивайте ей false. То есть вот так делать не надо:</p><p>Лучше вот так:</p><p>Зачем это? Представьте, что вы проверяете данные перед запросом к базе. Если по какой-то причине блок if вдруг не выполнится, то значение переменной останется false — так вы подстрахуете себя от попадания в базу ошибочных данных. В коде порой приходится иметь дело с конфиденциальными данными, так что лучше сначала исходить из того, что все данные ошибочны, пока не доказано обратное. Это правило практически написано кровью.</p><p>Кстати, лучше проверять, являются ли данные такими, как надо нам, чем являются ли они такими, как нам не надо.</p><h3>Используйте кавычки, когда обращаетесь к элементам массива</h3><p>В коде разных разработчиков можно увидеть два варианта доступа к элементам ассоциативного массива:</p><p>Во время выполнения второго варианта PHP сначала попытается найти константу с именем marc. И только если такой не найдется, marc будет сконвертировано в строку и передано в таком виде. Лучше не думать о том, что может случиться, если вдруг такая константа будет существовать… Всегда ставьте кавычки, чтобы такого не происходило.</p><h3>Используйте запятые, чтобы обратиться к нескольким строкам в одном вызове</h3><p>Если вам надо, например, в одном вызове функции обратиться к значению переменной и к строке, лучше используйте запятые, а не точки. Почему? Точка — оператор конкатенации строк, эта операция будет выполняться медленнее. <a href="http://www.electrictoolbox.com/php-echo-commas-vs-concatenation/">Доказательство</a>.</p><p>Еще раз. Так надо:</p><p>echo "Hello, my name is ", $name;</p><p>А вот так — не надо:</p><p>echo "Hello, my name is " . $name;</p><h3>Пользуйтесь тернарными операторами</h3><p>Если у вас в коде какое-то очень простое сравнение, желательно использовать тернарный оператор, чтобы не растягивать простой код на несколько строк. Вот так может выглядеть ваш простой if:</p><p>Но можно записать его и так:</p><p>Обобщенно тернарный оператор работает следующим образом:</p><h3>Используйте для сравнения с булевыми значениями строгое сравнение</h3><p>Если вы проверяете переменную на true или false, используйте ===, а не ==, которое задействуется в остальных сравнениях. Строгое сравнение из трех знаков равенства сравнит еще и типы переменных.</p><h3>Используйте инкремент и декремент</h3><p>Если вам нужно просто увеличить или уменьшить на 1 значение переменной, ни к чему писать эту громоздкую конструкцию:</p><p>Куда лаконичнее такой вариант:</p><p>А главная прелесть этих операций — в том, что одновременно с ними можно выполнять еще какое-нибудь действие (например, if или while). В зависимости от того, написано ли -- или ++ до или после самого названия переменной, очередность операций изменяется.</p><h3>Используйте сокращенные операторы присваивания</h3><p>Если переменную надо увеличить или уменьшить на число, не равное 1, то и в этом случае код можно сократить. Например, у вас в коде может быть такое:</p><p>А используя сокращенные операторы, этот же код можно будет записать так:</p><p>Со строками, кстати, это тоже работает. Если понадобится присоединить к существующей строке какую-то часть, сделайте это так:</p><h3>Создайте отдельную функцию для var_dump</h3><p>Иногда бывает нужно во время активной отладки часто выводить прямо на страницу значение какой-то переменной. Конечно, лучше лишний раз так не делать, но если все-таки нужно, то имеет смысл себе помочь. Функция может выглядеть так:</p><p>Тэг pre используется, чтобы сделать значение более читаемым. Кстати, такое странное имя функции дано неслучайно — оно короткое, хоть и неочевидное. Набрать ее название будет быстро. Только потом не забудьте убрать эту функцию, когда будете подчищать код в конце разработки.</p><p>Но лучше всего забыть этот совет и научиться пользоваться XDebug.</p><h3>Пользуйтесь константами</h3><p>Если у вас есть переменная, значение которой изменять не стоит, имеет смысл использовать вместо нее константу. Константы можно использовать, чтобы хранить в них пути, сообщения об ошибках и так далее. Имя константам стоит давать капсом — так их будет просто отличить, и вы будете уверены, что вызываете то, что нужно.</p><h3>Пользуйтесь $_GET и $_POST</h3><p>$_REQUEST лучше не использовать. Четко разделяйте данные: $_GET — это параметры, переданные из адресной строки, $_POST — это, например, полученные из формы данные. И не вздумайте передавать в скрипт пароли, особенно незашифрованные, GET-запросом!</p><p>Пользователи могут руками заменить значения в адресной строке на любые произвольные и доставить вам немало хлопот.</p><h3>Используйте объекты, а не функции</h3><p>PHP — все-таки в том числе и объектно-ориентированный язык. Если вы работаете над большим проектом, сотни строк функционального кода вам точно быстро надоедят. А если вам нужно хранить множество однотипных параметров, то тем более задумайтесь об использовании соответствующего класса.</p><h3>Вызывайте методы цепочками</h3><p>Если вы подряд вызываете несколько методов одного объекта, имеет смысл сократить код, не выписывая каждый раз название этого объекта. Если есть вот такой класс:</p><p>… то обращаться к его методам можно так:</p><p>Чтобы лучше понять, как это работает и при каких обстоятельствах можно это пользоваться, почитайте <a href="http://www.wisereport.ru/method_chaining/">статью</a>.</p><h3>Не повторяйте себя</h3><p>Всегда оборачивайте в функцию код, который используете чаще одного-двух раз. Если этого не делать, проект распухнет и будет состоять из кучи однотипных строчек.</p><p>Почитайте о методах <a href="https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself">DRY</a> и WET.</p><h3>Стремитесь к слабой связанности и сильной сцепленности</h3><p>Связанность — это способ проектирования проекта, когда изменение одного компонента требует изменения другого. Другими словами, если вы измените одну функцию, придется ли менять другую? Чем свободнее связь, тем проще будет менять компоненты, не перелопачивая половину кода.</p><p>Сцепленность же — это когда вместе отдельные части образуют значимую единицу. У вас есть одна функция или метод на весь проект, которая делает вообще все возможное и невозможное, или есть много функций или методов, каждый из которых выполняет свой участок работы? Особенно это касается ООП. Дробите методы, магические методы на десятки и сотни строк недопустимы.</p><p>Как опытный программист, вы должны стремиться к тому, чтобы компоненты мало зависели друг от друга и не брали на себя слишком много работы. Такой код будет куда проще расширять и поддерживать. Создавая функцию, задумывайтесь о том, насколько она удобна для использования в будущих проектах.</p><p>Проиллюстрировать этот совет можно так. Возьмем этот код:</p><p>Главный минус этой функции в том, что она сама осуществляет проверку данных, а потом выводит на экран значение. Да и такое поведение не совсем очевидно — согласитесь, столь избирательно работающее сложение вам вряд ли еще где-то повторно понадобится. А если вам еще и захочется поменять сообщение для вывода? Этот код лучше переписать так:</p><p>Теперь каждая функция выполняет только свою работу: add складывает числа, result выводит результат.</p></h3>]]></content:encoded>
    </item>
    <item>
      <title>15 правил написания качественного кода</title>
      <link>https://tproger.ru/translations/15-rules-for-writing-quality-code</link>
      <comments>https://tproger.ru/translations/15-rules-for-writing-quality-code?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/15-rules-for-writing-quality-code</guid>
      <description><![CDATA[<p>Набор из 15 правил, которые поднимают уровень кода: следование стандарту оформления языка, отступы и скобки, именование объектов и комментарии.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/15-rules-for-writing-quality-code">15 правил написания качественного кода</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 06 May 2015 09:59:29 GMT</pubDate>
      <content:encoded><![CDATA[<p>Есть мириады способов написать плохой код. К счастью, чтобы подняться до уровня качественного кода, достаточно следовать 15 правилам. Их соблюдение не сделает из вас мастера, но позволит убедительно имитировать его.</p><h3>Правило 1. Следуйте стандартам оформления кода.</h3><p>У каждого языка программирования есть свой стандарт оформления кода, который говорит, как надо делать отступы, где ставить пробелы и скобки, как называть объекты, как комментировать код и т.д.</p><p>Например, в этом куске кода в соответствии со стандартом есть 12 ошибок:</p><p>Изучайте стандарт внимательно, учите основы наизусть, следуйте правилам как заповедям, и ваши программы станут лучше, чем большинство, написанные выпускниками вузов.</p><p>Многие организации подстраивают стандарты под свои специфические нужды. Например, Google разработал стандарты для более чем 12 языков программирования. Они хорошо продуманы, так что <a href="https://code.google.com/p/google-styleguide/">изучите их</a>, если вам нужна помощь в программировании под Google. Стандарты даже включают в себя настройки редактора, которые помогут вам соблюдать стиль, и специальные инструменты, верифицирующие ваш код на соответствию этому стилю. Используйте их.</p><h3>Правило 2. Давайте наглядные имена.</h3><p>Ограниченные медленными, неуклюжими телетайпами, программисты в древности использовали контракты для имён переменных и процедур, чтобы сэкономить время, стуки по клавишам, чернила и бумагу. Эта культура присутствует в некоторых сообществах ради сохранения обратной совместимости. Возьмите, например, ломающую язык функцию C wcscspn (wide character string complement span). Но такой подход неприменим в современном коде.</p><p>Используйте длинные наглядные имена наподобие complementSpanLength, чтобы помочь себе и коллегам понять свой код в будущем. Исключения составляют несколько важных переменных, используемых в теле метода, наподобие итераторов циклов, параметров, временных значений или результатов исполнения.</p><p>Гораздо важнее, чтобы вы долго и хорошо думали перед тем, как что-то назвать. Является ли имя точным? Имели ли вы в виду highestPrice или bestPrice? Достаточно ли специфично имя, дабы избежать его использования в других контекстах для схожих по смыслу объектов? Не лучше ли назвать метод getBestPrice заместо getBest? Подходит ли оно лучше других схожих имён? Если у вас есть метод ReadEventLog, вам не стоит называть другой NetErrorLogRead. Если вы называете функцию, описывает ли её название возвращаемое значение?</p><p>В заключение, несколько простых правил именования. Имена классов и типов должны быть существительными. Название метода должно содержать глагол. Если метод определяет, является ли какая-то информация об объекте истинной или ложной, его имя должно начинаться с «is». Методы, которые возвращают свойства объектов, должны начинаться с «get», а устанавливающие значения свойств — «set».</p><h3>Правило 3. Комментируйте и документируйте.</h3><p>Начинайте каждый метод и процедуру с описания в комментарии того, что данный метод или процедура делает, параметров, возвращаемого значения и возможных ошибок и исключений. Опишите в комментариях роль каждого файла и класса, содержимое каждого поля класса и основные шаги сложного кода. Пишите комментарии по мере разработки кода. Если вы полагаете, что напишете их потом, то обманываете самого себя.</p><p>Вдобавок, убедитесь, что для вашего приложения или библиотеки есть руководство, объясняющее, что ваш код делает, определяющий его зависимости и предоставляющий инструкции для сборки, тестирования, установки и использования. Документ должен быть коротким и удобным; просто README-файла часто достаточно.</p><h3>Правило 4. Не повторяйтесь.</h3><p>Никогда не копируйте и не вставляйте код. Вместо этого выделите общую часть в метод или класс (или макрос, если нужно), и используйте его с соответствующими параметрами. Избегайте использования похожих данных и кусков кода. Также используйте следующие техники:</p><ul><li>Создание справочников API из комментариев, используя Javadoc и Doxygen.</li><li>Автоматическая генерация Unit-тестов на основе аннотаций или соглашений об именовании.</li><li>Генерация PDF и HTML из одного размеченного источника.</li><li>Получение структуры классов из базы данных (или наоборот).</li></ul><h3>Правило 5. Проверяйте на ошибки и реагируйте на них.</h3><p>Методы могут возвращать признаки ошибки или генерировать исключения. Обрабатывайте их. Не полагайтесь на то, что диск никогда не заполнится, ваш конфигурационный файл всегда будет на месте, ваше приложение будет запущено со всеми нужными правами, запросы на выделение памяти всегда будут успешно исполнены, или что соединение никогда не оборвётся. Да, хорошую обработку ошибок тяжело написать, и она делает код длиннее и труднее для чтения. Но игнорирование ошибок просто заметает проблему под ковёр, где ничего не подозревающий пользователь однажды её обнаружит.</p><h3>Правило 6. Разделяйте код на короткие, обособленные части.</h3><p>Каждый метод, функция или блок кода должн умещаться в обычном экранном окне (25-50 строк). Если получилось длиннее, разделите на более короткие куски. Даже внутри метода разделяйте длинный код на блоки, суть которых вы можете описать в комментарии в начале каждого блока.</p><p>Более того, каждый класс, модуль, файл или процесс должен выполнять определённый род задач. Если часть кода выполняет совершенно разнородные задачи, то разделите его соответственно.</p><h3>Правило 7. Используйте API фреймворков и сторонние библиотеки.</h3><p>Изучите, какие функции доступны с помощью API вашего фреймворка. а также что могут делать развитые сторонние библиотеки. Если библиотеки поддерживаются вашим системным менеджером пакетов, то они скорее всего окажутся хорошим выбором. Используйте код, удерживающий от желания изобретать колесо (при том бесполезной квадратной формы).</p><h3>Правило 8. Не переусердствуйте с проектированием.</h3><p>Проектируйте только то, что актуально сейчас. Ваш код можно делать довольно обобщённым, чтобы он поддерживал дальнейшее развитие, но только в том случае, если он не становится от этого слишком сложным. Не создавайте параметризованные классы, фабрики, глубокие иерархии и скрытые интерфейсы для решения проблем, которых даже не существует — вы не можете угадать, что случится завтра. С другой стороны, когда структура кода не подходит под задачу, не стесняйтесь рефакторить его.</p><h3>Правило 9. Будьте последовательны.</h3><p>Делайте одинаковые вещи одинаковым образом. Если вы разрабатываете метод, функциональность которого похожа на функциональность уже существующего, то используйте похожее имя, похожий порядок параметров и схожую структура тела. То же самое относится и к классам. Создавайте похожие поля и методы, делайте им похожие интерфейсы, и сопоставляйте новые имена уже существующим в похожих классах.</p><p>Ваш код должен соответствовать соглашениям вашего фреймворка. Например, хорошей практикой является делать диапазоны полуоткрытыми: закрытыми (включающими) слева (в начале диапазона) и открытыми (исключающими) справа (в конце). Если для конкретного случая нет соглашений, то сделайте выбор и фанатично придерживайтесь его.</p><h3>Правило 10. Избегайте проблем с безопасностью.</h3><p>Современный код редко работает изолированно. У него есть неизбежный риск стать мишенью атак. Они необязательно должны приходить из интернета; атака может происходить через входные данные вашего приложения. В зависимости от вашего языка программирования и предметной области, вам возможно стоит побеспокоиться о переполнении буфера, кросс-сайтовых сценариях, SQL-инъекциях и прочих подобных проблемах. Изучите эти проблемы, и избегайте их в коде. Это не сложно.</p><h3>Правило 11. Используйте эффективные структуры данных и алгоритмы.</h3><p>Простой код часто легче сопровождать, чем такой же, но изменённый ради эффективности. К счастью, вы можете совмещать сопровождаемость и эффективность, используя структуры данных и алгоритмы, которые даёт ваш фреймворк. Используйте map, set, vector и алгоритмы, которые работают с ними. Благодаря этому ваш код станет чище, быстрее, более масштабируемым и более экономным с памятью. Например, если вы сохраните тысячу значений в отсортированном множестве, то операция пересечения найдёт общие элементы с другим множеством за такое же число операций, а не за миллион сравнений.</p><h3>Правило 12. Используйте Unit-тесты.</h3><p>Сложность современного ПО делает его установку дороже, а тестирование труднее. Продуктивным подходом будет сопровождение каждого куска кода тестами, которые проверяют корректность его работы. Этот подход упрощает отладку, т.к. он позволяет обнаружить ошибки раньше. Unit-тестирование необходимо, когда вы программируете на языках с динамической типизацией, как Python и JavaScript, потому что они отлавливают любые ошибки только на этапе исполнения, в то время как языки со статической типизацией наподобие Java, C# и C++ могут поймать часть из них во время компиляции. Unit-тестирование также позволяет рефакторить код уверенно. Вы можете использовать <a href="https://en.wikipedia.org/wiki/XUnit">XUnit</a> для упрощения написания тестов и автоматизации их запуска.</p><h3>Правило 13. Сохраняйте код портируемым.</h3><p>Если у вас нет особой причины, не используйте функциональность, доступную только на определённой платформе. Не полагайтесь на то, что определённые типы данных (как integer, указатели и временные метки) будут иметь конкретную длину (например, 32 бита), потому что этот параметр отличается на разных платформах. Храните сообщения программы отдельно от кода и на зашивайте параметры, соответствующие определённой культуре (например, разделители дробной и целой части или формат даты). Соглашения нужны для того, чтобы код мог запускаться в разных странах, так что сделайте локализацию настолько безболезненной, насколько это возможно.</p><h3>Правило 14. Делайте свой код собираемым.</h3><p>Простая команда должна собирать ваш код в форму, готовую к распространению. Команда должна позволять вам быстро выполнять сборку и запускать необходимые тесты. Для достижения этой цели используйте средства автоматической сборки наподобие <a href="https://en.wikipedia.org/wiki/Make_(software)">Make</a>, <a href="http://maven.apache.org/">Apache Maven</a>, или <a href="http://ant.apache.org/">Ant</a>. В идеале, вы должны установить интеграционную систему, которая будет проверять, собирать и тестировать ваш код при любом изменении.</p><h3>Правило 15. Размещайте всё в системе контроля версий.</h3><p>Все ваши элементы — код, документация, исходники инструментов, сборочные скрипты, тестовые данные — должны быть в системе контроля версий. <a href="http://git-scm.com/">Git</a> и <a href="http://github.com/">GitHub</a> делают эту задачу дешёвой и беспроблемной. Но вам также доступны и многие другие мощные инструменты и сервисы. Вы должны быть способны собрать и протестировать вашу программу на сконфигурированной системе, просто скачав её с репозитория.</p><h3>Заключение.</h3><p>Сделав эти 15 правил частью вашей ежедневной практики, вы в конце концов создадите код, который легче читать, который хорошо протестирован, с большей вероятностью запустится корректно и который будет гораздо проще изменить, когда придёт время. Вы также убережёте себя и ваших пользователей от большого числа головных болей.</p><p>Перевод статьи «15 Rules for Writing Quality Code»</p>]]></content:encoded>
    </item>
    <item>
      <title>Учимся правильно оформлять код на C на примере open source проектов</title>
      <link>https://tproger.ru/translations/learn-basic-c-coding-rules-from-open-source-projects</link>
      <comments>https://tproger.ru/translations/learn-basic-c-coding-rules-from-open-source-projects?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/learn-basic-c-coding-rules-from-open-source-projects</guid>
      <description><![CDATA[<p>Единый стиль исходников большого проекта облегчает чтение кода, а учиться оформлению удобно на проверенном временем проекте с открытым исходным кодом.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/learn-basic-c-coding-rules-from-open-source-projects">Учимся правильно оформлять код на C на примере open source проектов</a>»</p>]]></description>
      <category><![CDATA[Язык Си]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 18 Feb 2015 16:20:23 GMT</pubDate>
      <content:encoded><![CDATA[<p>В каждом проекте есть свои соглашения по написанию и оформлению кода. Некоторые менеджеры ограничиваются только базовыми правилами, некоторые составляют подробные списки рекомендаций. В некоторых проектах правил оформления кода нет совсем, и каждый разработчик следует своему стилю.</p><p>Если исходники большого проекта написаны в одном стиле, их гораздо легче понимать.</p><p>Научиться правильному оформлению кода можно, например:</p><ul><li>из книг и журналов;</li><li>из руководств в сети;</li><li>из общения с коллегами;</li><li>на собственном опыте.</li></ul><p>Другой, не менее интересный, подход — взять проверенный временем открытый проект и разобраться в том, какие решения принимали его разработчики. Хорошим примером в этом случае будет <a href="https://github.com/torvalds/linux">ядро Linux</a>.</p><p>Для новичка или даже для опытного разработчика, разбор кода ядра Linux может оказаться непростой задачей. Однако наша цель не присоединиться к ним, а просто рассмотреть детали реализации.</p><p>Давайте посмотрим на пример реализации функции из исходного кода Linux:</p><p>Код выглядит чистым и понятным:</p><ul><li>Он короткий, всего несколько строк.</li><li>Подробная сигнатура функции.</li><li>Код хорошо документирован.</li><li>Код правильно и последовательно структурирован.</li><li>Понятные имена переменных.</li></ul><p>Тот же код, написанный другим разработчиком, может выглядеть так:</p><p>Стиль написания кода очень сильно влияет на его читаемость. Поэтому время, потраченное на тренировку и периодические код-ревью, всегда окупится.</p><p>Давайте теперь посмотрим на код ядра Linux с помощью <a href="http://www.cppdepend.com">CppDepend</a> и попробуем разобраться, какими правилами руководствовались разработчики.</p><h3>Модульность</h3><p>Модульность — это техника дизайна приложений, которая обеспечивает повторное использование кода и облегчает его поддержку.</p><p>Для процедурного языка, такого, как C, в котором нет пространств имен, классов или компонентов, мы можем разделять модули, помещая код в отдельные файлы и директории.</p><p>Мы можем использовать два подхода:</p><ul><li>Положить все исходники в одну директорию</li><li>Объединить файлы, относящиеся к одному модулю в одну директорию.</li></ul><p>В случае с ядром Linux директории и поддиректории используются для обеспечения модульности кода ядра.</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic01-300x278.jpg" alt="" /></figure><h3>Инкапсуляция</h3><p>Инкапсуляция — это скрытие внутренних деталей реализации. В C инкапсуляция обеспечивается за счет ключевого слова static. Функции и переменные, помеченные как статические, позволяют обращаться к ним только из того же файла.</p><p>Давайте посмотрим на статические функции с помощью следующего запроса в CQLinq:</p><p>Мы можем использовать панель Метрик (Metric view) чтобы оценить код в целом. На этой панели код представлен в виде дерева (Treemap). Древовидная структура, используемая в CppDepend показывает иерархию кода:</p><ul><li>Директории в проекте.</li><li>Файлы в директориях.</li><li>Структуры, функции и переменные в файлах.</li></ul><p>Дерево проекта позволяет наглядно представить результаты запроса CQLinq.</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic02.jpg" alt="" /></figure><p>Видно, что множество функций — статические.</p><p>Теперь давайте найдем статические поля:</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic010.jpg" alt="" /></figure><h3>Используйте структуры для своих данных</h3><p>В C функции используют переменные для работы. Переменные могут быть:</p><ul><li>статическими;</li><li>глобальными;</li><li>локальными;</li><li>полями структур.</li></ul><p>В каждом проекте есть модель данных, которая используется в различных модулях. Использование глобальных переменных для представления этой модели — это возможное решение, но плохое. Используйте структуры для группировки данных.</p><p>Давайте найдем все глобальные переменные с примитивным типом:</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic04.jpg" alt="" /></figure><h3>Функции должны быть краткими и понятными</h3><p>Вот совет из <a href="https://www.kernel.org/doc/Documentation/CodingStyle">linux coding style</a> по поводу длины функции:</p><blockquote>Функции должны быть короткими и понятными, делать только одну вещь. Они должны занимать один или, максимум, два экрана текста (экран по ISO/ANSI имеет размер 80×24). Функция должна делать одну вещь, и делать ее хорошо.Максимальная длина функции обратно пропорциональна ее сложности и количеству уровней вложенности. Так, если у вас, например, простая функция с одним, но большим case-выражением, она может быть длинной.</blockquote><p>Давайте найдем все функции, длина которых больше 30 строк:</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic05.jpg" alt="" /></figure><p>Всего немного методов занимает больше 30 строк.</p><h3>Количество параметров функции</h3><p>Функции с количеством параметров большим, чем 8 (NbParameters &gt; 8), трудно вызывать. Также, их вызов плохо сказывается на производительности. Вместо этого мы можем передавать в них структуру с необходимыми значениями.</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic06.jpg" alt="" /></figure><p>Только два метода принимают больше, чем 8 параметров.</p><h3>Количество локальных переменных</h3><p>Методы, в которых используются более 8 локальных переменных (значение NbVariables) тяжело понимать и поддерживать. Методы, в которых 15 и более локальных переменных очень сложны и их следует разбивать на более мелкие (кроме тех случаев, когда код сгенерирован сторонним инструментом).</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic07.jpg" alt="" /></figure><p>Только в пяти функциях используется более 15 локальных переменных.</p><h3>Избегайте сложных функций</h3><p>Существует много метрик для определения сложности функции. Количество строк кода, локальных переменных и параметров — только некоторые из них.</p><p>Есть несколько более комплексных метрик:</p><ul><li>Cyclomatic complexity — популярная метрика, показывающая количество ветвлений в коде.</li><li>Nesting Depth — is a metric defined on methods that is relative to the maximum depth of the more nested scope in a method body.</li><li>Max Nested loop — максимальный уровень вложенности в методе.</li></ul><p>Максимально допустимые значения этих метрик устанавливаются руководителем, здесь нет стандартных значений.</p><p>Давайте посмотрим на функции, которые можно упростить:</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic08.jpg" alt="" /></figure><p>Только небольшое количество функций можно признать сложными.</p><h3>Соглашения об именовании</h3><p>Не существует единого стандарта именования элементов программы, поэтому каждый менеджер проекта может устанавливать свои правила, однако важно, чтобы эти правила были последовательны.</p><p>К примеру, в коде ядра Linux имена структур должны начинаться со строчной буквы. Мы можем проверить соответствие кода соглашению с помощью такого запроса:</p><figure><img src="https://media.tproger.ru/uploads/2015/02/pic09.jpg" alt="" /></figure><p>Имена только 4 структур начинаются с «_» вместо строчной буквы.</p><h3>Отступы и выравнивание</h3><p>Отступы очень важны для того, чтобы код был читаем. Вот что пишут об этом на странице <a href="https://www.kernel.org/doc/Documentation/CodingStyle">linux coding style</a>:</p><blockquote>Обоснование: Основная идея отступов состоит в том, чтобы показать где начинается и заканчивается логический блок кода. Когда вы смотрите на один и тот же код в течение 20 часов, трудно не заметить пользу отступов.Некоторые могут возразить, что отступ в 8 пробелов делает код слишком широким, особенно на 80-знаковой строке терминала. Ответ: Если вам понадобилось более трех уровней отступа, вы что-то делаете неправильно и вам следует переписать этот участок.</blockquote><h3>Заключение</h3><p>Чтение кода open-source проектов всегда идет на пользу вашему опыту. При этом нет необходимости скачивать и собирать проект, достаточно просто просматривать код, например, на GitHub.</p><p>Перевод статьи “Learn basic “C” coding rules from open source projects”</p>]]></content:encoded>
    </item>
    <item>
      <title>Не комментируйте свой код — перепишите его</title>
      <link>https://tproger.ru/translations/dont-comment-your-code-rewrite-it</link>
      <comments>https://tproger.ru/translations/dont-comment-your-code-rewrite-it?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/dont-comment-your-code-rewrite-it</guid>
      <description><![CDATA[<p>Обилие комментариев чаще указывает на плохо написанный код: программист рассказывает, как поменял отношение к комментированию по мере опыта.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/dont-comment-your-code-rewrite-it">Не комментируйте свой код — перепишите его</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 06 Feb 2015 12:46:29 GMT</pubDate>
      <content:encoded><![CDATA[<p>Комментирование кода — это один из аспектов, к которому я изменил своё отношение в процессе профессионального развития. Когда я был еще новичком, я считал, что нужно комментировать чуть ли не каждую строчку кода, каждый даже самый небольшой его участок. Казалось, это поможет быстрее разобраться в том, что и где происходит. Комментарии ведь на обычном человеческом языке, а код такой сложный и непонятный. Но позже я осознал, что это был просто плохо написанный код, и вся моя головная боль не от плохих комментариев или их отсутствия, а от сотен невнятных строк подряд в одной функции и переменных в стиле x, y, или i.</p><p>Я считаю, что комментарии относятся к признакам «<a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B4_%D1%81_%D0%B7%D0%B0%D0%BF%D0%B0%D1%88%D0%BA%D0%BE%D0%BC">кода с запашком</a>» и должны использоваться крайне экономно и только там, где они на самом деле нужны.</p><h3>Так что же нужно комментировать?</h3><p>Вообще, я не сказал, что комментарии не нужны совсем, в программировании довольно редко используются какие-либо абсолютные соглашения. Вы должны быть уверены, что есть на самом деле весомая причина использования пояснений в коде. Я использую их как предупреждающие знаки о том, что программисту стоит обратить особое внимание на этот участок. Скорее всего, он чем-то опасен или делает какую-то неочевидную вещь. Можно ли сказать то же самое про любой кусок кода, который чем-то сложен и сильно запутан? Да, можно! По этой причине я часто использую комментарии в legacy-коде, над которым не ведётся активная работа. Т.к. из-за внешних бизнес-условий мы не всегда можем проводить рефакторинг так часто, как хотелось бы, да и иногда лучше просто не трогать то, что и так работает, то комментарии могут быть полезны. Я считаю, что в данном случае это необходимое зло.</p><h3>Почему же комментарии — это зло?</h3><p>Короткий ответ в том, что они часто врут нам. Они говорят, что делает данный код и часто могут не изменяться в последующих ревизиях. Например, есть функция, которая возвращает string, и я так и написал в комментариях. Но затем потребовалось изменить её, и какой-то другой программист внёс быстрые правки, поменяв тип возвращаемого значения на int, но забыл обновить комментарии. Это довольно распространённый случай. Вот мы и пришли к ситуации, когда комментарии говорят одно, а происходит на самом деле совсем другое.</p><p>Мы знаем, что правда всегда на стороне кода. Ведь это именно то, что будет происходить в реальном продукте. Так зачем же читать комментарии, которые потенциально могут быть ошибочны и тратить время на них, когда можно просто посмотреть на код и понять, что он делает?</p><blockquote>Код никогда не лжёт, комментарии иногда делают это. — Ron Jeffries</blockquote><h3>Как писать код так, чтобы комментарии были не нужны?</h3><p>В проектах, которые активно разрабатываются, я стараюсь писать код так, чтобы он выражал то, что он должен делать. Это, пожалуй, то, на что я трачу большую часть своего времени. Иногда мне со значительным трудом даётся выбор названий. Обычно я стараюсь выбирать такое имя для функции или класса, которое напрямую отражает то, что они делают, а позже переименовываю, если это необходимо.</p><p>Отрывок выше является хорошим примером выразительного кода. Даже ребёнок сможет понять, что это собака, и она может лаять. Конечно, в большинстве случаев реальный код намного сложнее и далеко не так очевидно, как написать его правильно, но общие принципы везде одинаковые. Старайтесь давать имена сущностям так, как будто вам надо будет объяснить это ребёнку. В данном примере мы можем описать код как «собака умеет лаять». Точно так же можно сказать «пользователь может залогиниться» или «пользователь может изменить данные своего профиля».</p><blockquote>Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте. — Martin Golding</blockquote><p>Эта цитата всегда казалась мне забавной, пока я сам не столкнулся с сопровождением кода, написанного просто ужасно. Мне на самом деле хотелось как следует врезать его автору за то, что он сделал код настолько сложным для сопровождения. Простые изменения, которые заняли бы минут 20 в коде с хорошей архитектурой, растянулись на 4 часа.</p><h3>Внимательно относитесь к именам переменных, функций и классов</h3><p>Нет ничего необычного в том, чтобы в процессе разработки изначальное название функции или переменной изменялось несколько раз. Особенно, если цикл разработки продолжается более, чем один день. Если мне пришла в голову мысль о том, как можно более правильно назвать что-либо, я вернусь к этому участку кода и потрачу время на его изменение. Всякий раз, когда мне кажется, что комментарий был бы здесь очень кстати, я возвращаюсь на шаг назад и еще раз смотрю на написанный код. Иногда даже консультируюсь с коллегой, чтобы понять, насколько комментарии всё-таки оправданы здесь. Иногда комментарии побеждают, но обычно, если это не какой-то очень специфичный участок кода, они всё-таки не нужны.</p><blockquote>Любой дурак может написать код, понятный компьютеру. Хорошие программисты пишут код, понятный людям. — Martin Fowler</blockquote><p>В этой цитате Мартин Фаулер описал всю суть того, почему нужно избегать комментариев. Ваш код должен быть настолько хорошо читаемым, что любой другой программист смог бы разобраться в нём. А комментарии просто кричат о том, что вы не сможете понять эту строчку без дополнительных пояснений. Вот почему я избегаю их, и вам советую поступать так же.</p><p>В следующий раз, когда вы будете писать код, постарайтесь делать это без комментариев вообще. Затем, через некоторое время, взгляните на программу и подумайте, насколько легко её читать. Если возникают трудности и вы не можете понять, что вы сами же написали без комментариев, просто выкиньте всё и перепишите с нуля.</p><p>Перевод статьи «Don’t Comment Your Code – Rewrite It»</p>]]></content:encoded>
    </item>
  </channel>
</rss>