стандарт написания кода php
PSR Стандарты
PSR — Чуть больше, чем стиль оформления кода.
Как показала практика, многие PHP-разработчики знакомы с аббревиатурой PSR. Однако большинство все еще ограничены знанием, что PSR это стандарт оформления кода.
Ребята из PHP-FIG (PHP Framework Interop Group), группа концепций совместимости PHP, которые занимаются развитием PSR (PHP Standards Recommendations) шагнули далеко вперед. Поэтому давайте разберемся, что из себя представляет PSR…
За последние полгода мне пришлось провести множество собеседований на позицию Middle PHP-Developer.
Один из вопросов, который я задавал всем кандидатам, был:- «Знаете ли Вы, что такое PSR?»
Как оказалось, практически всем кандидатам была знакома эта аббревиатура. Однако пытаясь рассказать подробнее, почти все разработчики указывали в основном на то, что это стандарт оформления кода (code style). Только некоторые упоминали про PSR-4 автозагрузку (использует Composer) и PSR-3 Logger Interface (в сети очень много однородных статей про PSR-0-1-2-3-4).
Мне кажется это весьма странным, так как термин PSR существует достаточно давно (уже более 10 лет) и каждый год набирает все большую популярность. Поэтому, думаю, будет неплохо собрать все в кучу и сделать обзор PSR стандартов.
PHP-FIG и PSR
PHP-FIG (PHP Framework Interop Group) — организованная в 2009 году группа разработчиков, основная идея которой находить способы совместной работы, выделяя общие концепции в разработке проектов на PHP.
Проще говоря, ребята стараются выделить что-то общее между различными проектами на разных фреймворках и сформировать некие стандарты (рекомендации) для дальнейшего периспользования.
Участники PHP-FIG
ReactPHP, Composer, Laminas Project (переименованный Zend Framework), Yii framework, CakePHP, Slim, Joomla, Magento, Drupal, phpBB, phpDocumentor и другие.
PSR (PHP Standards Recommendations) — описывает общие концепции, которые уже были проверены и отработаны. Вероятно при создании PSR, группа PHP-FIG вдохновлялась Java Community Process, а первый стандарт был принят в 2010 году.
Список PSR стандартов расширяется новыми, а сами стандарты делятся на категории:
Автозагрузка, Интерфейсы, HTTP и Стиль кодирования,
каждому из которых присваивается определенный статус:
Принят, Устаревший, Черновик и Заброшенный.
Далее мы рассмотрим принятые PSR стандарты по категориям:
Автозагрузка
Разработчики, которые «недолго» работают с PHP, вероятно не знакомы с проблемами импорта классов, ведь есть пространства имен, а сейчас вообще трудно представить проект без менеджера зависимостей Composer, которой решает все вопросы с автозагрузкой классов.
Однако так было не всегда, пространства имен появились только в PHP 5.3 (это был 2009 год), а первый релиз Composer состоялся в марте 2012 года. Но вот сам PHP существует гораздо дольше, как Personal Home Page с 1995 года и как Hypertext Preprocessor с 1998 года, однако только PHP 5 включает «полноценную объектную модель», релиз которого был в июле 2004 года. Бородатым разработчикам того времени приходилось как-то сражаться со всеми возникшими проблемами при импорте классов.
Не самый плохой пример импорта классов на PHP 14-ти летней давности:
(Напишите в комментариях, если узнали где использовался данный подход).
В дополнение, оставлю ссылку на статью, которая подробно описывает работу с пространством имен, решенные проблемы и PSR-4.
Интерфейсы
PHP развивается, набирает все большую популярность, а его инфраструктура пополняется огромным количеством различных инструментов.
Появляются проблемы с изучением и переиспользованием однотипного функционала, а менеджер зависимостей может затянуть целую кучу несвязанных однотипных зависимостей. (тут JavaScript разработчик улыбнется).
Поэтому принято решение стандартизировать некоторые общие концепции:
Если Ваш проект нуждается в расширенном функционале, МОЖНО расширять данный интерфейс, но СЛЕДУЕТ сохранять совместимость с описанными в данном стандарте правилами. Это позволит сторонним библиотекам, применяемых при разработке приложения, использовать централизованную систему логирования.
Это привело к ситуации, когда многие библиотеки реализуют свои собственные системы кэширования с различными уровнями функциональности. Эти различия заставляют разработчиков изучать несколько систем, которые могут предоставлять или не предоставлять необходимую им функциональность. Кроме того, разработчики кеширующих библиотек сами сталкиваются с выбором между поддержкой только ограниченного числа платформ или созданием большого количества классов адаптеров.
Чтобы решить эти проблемы был принят общий стандарт для библиотек реализующих кэширование, он включает в себя несколько интерфейсов:
Пользователи НЕ ДОЛЖНЫ передавать контейнер в объект, чтобы объект мог получить свои собственные зависимости. Это означает, что контейнер используется в качестве Service Locator, который обычно не рекомендуется использовать.
Отсюда, возникает простой вопрос: «Как это вообще работает»?
На самом деле все просто, на помощь приходит паттерн Factory, который возьмет на себя задачу создания объекта. А вот сам класс фабрики уже может принимать ContainerInterface и передавать в создаваемый объект необходимые зависимости.
Поэтому был принят PSR-16. Этот более простой подход направлен на создание стандартизированного оптимизированного интерфейса для общих случаев.
В списке реализаций все тот-же Symfony Cache и Laminas Cache (бывший Zend).
Если речь идет о WEB-приложении, то не важно на сколько сложная в нем бизнес-логика, по факту оно делает всего 2 вещи — принимает Request и отдает Response. Это значит, что так или иначе, приходится реализовывать эти объекты у себя в проекте.
Пожалуй, одной из самых сложных задач, которая нередко возникает является переиспользование кода между различными проектами. Если хорошо абстрагированные участки бизнес логики, некоторые компоненты и модули перенести возможно (с минимальными затратами), то с переносом более высокого уровня фреймворков (например контроллеров) возникают сложности.
Группа PHP-FIG пытается исправить данную проблему и предоставляет стандарты абстракции над HTTP.
А более детальное описание с примерами можно разобрать в статье «PSR-7 в примерах».
Если не вдаваться во все тонкости, то по сути это возможность писать некие абстрактные контроллеры для последующего переиспользования между различными проектами.
PSR-7 не содержит рекомендации о том, как создавать HTTP-объекты. Это может приводить к трудностям при необходимости их создания внутри компонентов, которые не привязаны к конкретной реализации PSR-7.
Интерфейсы, описанные в этой спецификации, описывают методы, с помощью которых можно создавать PSR-7 объекты.
Это может сделать библиотеки более пригодными для повторного использования, так как уменьшает количество зависимостей и снижает вероятность конфликтов версий.
Также в спецификации указано, что HTTP-клиенты могут быть заменены согласно принципу подстановки Лисков. Это означает, что все клиенты ДОЛЖНЫ вести себя одинаково при отправке запроса.
Пример реализации PSR-18 можно увидеть в библиотеке Symfony HTTP-client.
Предложенная абстракция над HTTP — это весьма серьезная заявка на попытку реализовывать действительно переиспользуемые и не зависящие от конкретных библиотек и фреймворков полноценные решения.
На практике, конечно все на много сложнее и есть свои нюансы и подводные камни, однако PHP-FIG делает значительный шаг вперед в этом направлении.
Стиль кодирования
До появления стандартов стиля кодирования, каждый из разработчиков оформлял свой код по-разному: одни писали CLASSNAME, другие ClassName, а третьи Class_Name, вечный спор относительно табов и пробелов, а еще StudlyCaps vs сamelCase vs snake_case и так далее.
Цель следующих PSR стандартов уменьшить когнитивное искажение при чтении кода от разных авторов.
Стандарт написания кода php
Цель данных рекомендаций — снижение сложности восприятия, поддержки, тестирования и расширения кода, написанного разными авторами; она достигается путём рассмотрения серии правил и ожиданий относительно написания PHP-кода.
Слова «НЕОБХОДИМО» / «ДОЛЖНО» («MUST»), «НЕДОПУСТИМО» («MUST NOT»), «ТРЕБУЕТСЯ» («REQUIRED»), «НУЖНО» («SHALL»), «НЕ ПОЗВОЛЯЕТСЯ» («SHALL NOT»), «СЛЕДУЕТ» («SHOULD»), «НЕ СЛЕДУЕТ» («SHOULD NOT»), «РЕКОМЕНДУЕТСЯ» («RECOMMENDED»), «МОЖЕТ» / «ВОЗМОЖНО» («MAY») и «НЕОБЯЗАТЕЛЬНО» («OPTIONAL») в этом документе следует понимать так, как это описано в RFC 2119 (и его переводе).
1.1. Базовый стандарт оформления кода
Код ДОЛЖЕН быть оформлен согласно всем правилам, указанным в стандарте PSR-12.
Жесткое ограничение строки ДОЛЖНО составлять 120 символов. В случае превышения этого ограничения автоматические системы проверки стиля ДОЛЖНЫ считать это ошибочной ситуацией, для таких ситуаций НЕОБХОДИМО явно отключать проверку стиля с помощью аннотаций:
1.3. Выравнивание присвоений переменных и элементов массива
Блок присвоений ДОЛЖЕН быть выровнен по самому длинному присвоению в блоке. Если операция присвоения превышает максимальную длину строки НЕОБХОДИМО:
При объявлении многострочного массива в конце последнего объявления ДОЛЖНА ставиться запятая, для однострочного массива запятую ставить НЕДОПУСТИМО.
1.5. Последовательность вызовов (Chaining)
Каждый элемент вызова для последовательностей, состоящих из трех и более элементов ДОЛЖЕН находиться на новой строке. В случае превышения максимальной длины строки каждый элемент последовательности вызовов ДОЛЖЕН находиться на новой строке.
1.6. Выделение управляющих инструкций
2.1. Базовый стандарт для оформления документации в коде
Код ДОЛЖЕН быть оформлен согласно правилам, указанным в стандарте PSR-19.
2.2. Дублирование типов в docblock
2.3. Массивы в docblock
Типы элементов массивов РЕКОМЕНДУЕТСЯ уточнять в docblock.
2.4. Неопределенные типы аргументов и возвращаемых результатов
В случае, если аргумент (или возвращаемый результат) метода может быть разных типов НЕОБХОДИМО перечислить все допустимые типы в docblock.
Если ожидаемый тип переменной явно не определен НЕОБХОДИМО определить его с помощью однострочного docblock комментария. Так же необходимо указывать ожидаемый тип, если IDE не может его определить, или определяет не корректно.
Свойства класса ДОЛЖНЫ содержать либо декларацию типа, либо docblock для всех возможных типов значений, которое они могут содержать. ДОПУСТИМО указывать декларацию типа и docblock только в случаях, когда dockblock уточняет декларацию, либо при наличии комментария. Если docblock МОЖЕТ быть описан одной строкой — ДОЛЖЕН использоваться однострочный docblock.
2.7. Методы и функции
Docblock для методов и функций ДОЛЖНЫ быть многострочными.
3. Объявление констант, свойств и методов
3.1. Последовательность объявлений констант, свойств и методов
В классе ДОЛЖНА соблюдаться последовательность объявлений элементов согласно следующему списку:
3.2. Именование свойств
Названия свойств ДОЛЖНЫ описывать предназначение данных, которые они хранят.
3.3. Разделение свойств
Каждое свойство ДОЛЖНО отделяться от других свойств, констант и методов одной пустой строкой. Если свойство объявляется, как первый элемент класса — пустая строка перед ним НЕДОПУСТИМА. Если свойство объявляется, как последний элемент класса — пустая строка после него НЕДОПУСТИМА.
3.4. Модификаторы доступа для свойств
Для модификаторов доступа к свойствам ДОЛЖНЫ выполняться следующие правила:
Свойства класса ДОЛЖНЫ содержать либо декларацию типа, либо docblock для всех возможных типов значений, которое они могут содержать.
3.6. Именование методов
Названия методов ДОЛЖНЫ описывать предназначение их использования внешним кодом, а не детали реализации.
3.7. Разделение методов
Каждый метод ДОЛЖЕН отделяться от других методов, свойств и констант одной пустой строкой. Если метод объявляется, как первый элемент класса — пустая строка перед ним НЕДОПУСТИМА. Если метод объявляется, как последний элемент класса — пустая строка после него НЕДОПУСТИМА.
3.8. Модификаторы доступа для методов
Для модификаторов доступа к свойствам ДОЛЖНЫ выполняться следующие правила:
3.9. Порядок аргументов в методе
Аргументы метода ДОЛЖНЫ объявляться в следующей последовательности:
3.10. Массив в виде аргумента
4.1. Неявные приведения типов
Неявное приведение типов НЕДОПУСТИМО.
Неявное приведение типов — один из наиболее распространенных источников ошибок. Проблемы, возникающие при неявном приведении типов сложно отслеживать, так же они могут приводить к непредсказуемым последствиям.
4.2. Сравнения с преобразованием типов
Проблемы тут те же, что и при неявном приведении типов.
4.3. Инструкция switch
Использовать инструкцию switch НЕОБХОДИМО с гарантией корректности типов каждого проверяемого выражения.
Инструкция switch при выполнении проверок case использует сравнения с приведением типов. Это может привести к тем же проблемам, что и неявное приведение типов.
4.4. Присвоения в условных операциях
Создание ошибок с помощью trigger_error НЕДОПУСТИМО, вместо этого ДОЛЖНЫ использоваться исключения.
4.6. Оператор управления ошибками @
Оператор @ ДОЛЖЕН быть использован для выражений, которые могут бросить ошибку, для остальных ситуаций его использование НЕДОПУСТИМО. В случае подавления ошибки ДОЛЖНО быть брошено исключение с описанием причин возникновения ошибки.
Использование инструкции goto НЕДОПУСТИМО.
Оператор goto используется для перехода в другую часть программы, чем усложняет чтение и понимание кода.
Использование инструкции eval НЕДОПУСТИМО.
4.9. Глобальные переменные и global
Использование инструкции global НЕДОПУСТИМО.
Глобальные переменные являются неявными аргументами функции, или метода, не гарантирующими ни тип, ни значение, ни даже своего существования.
4.10. Статические свойства
Использование статических свойств НЕДОПУСТИМО.
Статические свойства, по аналогии с глобальными переменным являются неявными аргументами функции, или метода, не гарантирующими ни тип, ни корректного состояния.
4.11. Суперглобальные переменные
Использование суперглобальных переменных ДОЛЖНО быть сведено к минимуму. Данные из суперглобальных переменных РЕКОМЕНДУЕТСЯ получать на этапе инициализации.
4.12. Динамическая подстановка имен
Динамическая подстановка имен переменных, свойств, функций и методов НЕДОПУСТИМА.
Динамическая подстановка имен сильно усложняет чтение и отладку кода потому, что конечные имена определяются только в рантайме.
4.13. Магические методы
Использование следующих магических методов НЕДОПУСТИМО:
Данные методы усложняют чтение и понимание кода, как следствие его поддержку.
4.14. Валидация аргументов
Каждый аргумент публичного метода, защищенного метода, или функции ДОЛЖЕН быть проверен на корректность типа и граничные значения. Каждый аргумент приватного метода ДОЛЖЕН быть проверен на корректность типа, проверять граничные значения РЕКОМЕНДУЕТСЯ. Если аргумент не валиден — штатное выполнение метода (функции) невозможно, по этой причине ДОЛЖНО быть брошено исключение.
4.16. Обработка часовых поясов
В случае хранения или обработки времени со смещением по часовому поясу есть большая вероятность возникновения ошибок связанных с несоответствием часовых поясов.
Для подстановки параметров в SQL запросы НЕОБХОДИМО использовать псевдопеременные.
Подстановка параметров с помощью конкатенации ведет к целому классу проблем безопасности: sql-инъекции.
5. Принципы программирования
Принцип Здравого Смысла разрешает отмену любого правила данных рекомендаций, в случае, когда правило приводит к чрезмерному усложнению поддержки кода. Этот принцип МОЖНО использовать, но очень осторожно.
РЕКОМЕНДУЕТСЯ следовать принципу YAGNI.
Код ДОЛЖЕН следовать принципам SOLID.
Принципу DRY СЛЕДУЕТ придерживаться только в случае, когда он не противоречит SOLID и Здравому смыслу.
Примеры, когда не стоит следовать принципу DRY:
У вас есть две разных сущности, отвечающие разным доменам с некой общей функциональностью. В такой ситуации не стоит наследовать сущности одну от другой, или общую функциональность выносить в абстрактный класс, или трейт. Дело в том, что общая функциональность является общей только в текущий момент времени, в будущем же она может измениться в каждом домене по своему. Фактически вам придется в общей функциональности реализовывать ее разделение, в зависимости от домена.
В тестах DRY может привести к ложно позитивным и ложно негативным ошибкам.
Принципу KISS СЛЕДУЕТ придерживаться только в случае, когда он не противоречит другим правилам данных рекомендаций.
Примеры, когда не стоит следовать принципу KISS:
Методы должны быть «не большого размера». Здесь проблемы те же, что и у классов. Разделяя метод на множество маленьких вы расширяете интерфейс класса, что в будущем может привести к излишней связанности, как с данным классом, так и с его наследниками.
Принцип TMTOWTDI НЕ РЕКОМЕНДУЕТСЯ использовать.
Множество способов реализации одного и того же алгоритма ведет к тому, что правки алгоритма придется выполнять в каждой реализации, что в свою очередь усложняет поддержку и увеличивает вероятность ошибок.
РЕКОМЕНДУЕТСЯ следовать принципам GRASP.
6. Антишаблоны проектирования
ActiveRecord объединяет сущности, представляющие домен вместе с инфраструктурой, в виде логики работы с базой данных. Такое поведение нарушает принципы SRP и ISP из SOLID, и приводит к следующим последствиям.
Проблема Singleton заключается в том, что состояние объекта, как правило, хранится в статическом свойстве, и является не явным аргументом метода, или функции, см. пункт 4.10. данных рекомендаций.
Каждый метод (функция) ДОЛЖНЫ быть покрыты тестами для всех возможных вариантов выполнения метода (функции).
7.2. Стратегия тестирования
Код ТРЕБУЕТСЯ покрывать, согласно «белому ящику». В случае чрезмерной сложности использования «белого ящика» СЛЕДУЕТ использовать стратегию «черного ящика».
7.3. Разделение тест методов
Каждый тест метод ДОЛЖЕН иметь полностью независимое состояние, относительно других тест методов. Каждый тест метод ДОЛЖЕН проверять конкретное поведение тестируемого метода (функции), тест методы, которые проверяют несколько аспектов поведения НЕДОПУСТИМЫ.
Принцип DRY для тестов не применяется, что бы минимизировать ложно позитивные и ложно негативные результаты.
7.4. Тестируемый объект
7.5. Проверка результатов
Проверку результатов НЕОБХОДИМО выполнять на тождество, т.е. и на тип и на значение. Числа с плавающей точкой ДОЛЖНЫ проверяться с учетом погрешности. Значения времени, зависящие от текущего времени ДОЛЖНЫ проверяться с учетом погрешности.
8.1. Именование тестовых классов
Тестовый класс ДОЛЖЕН состоять из префикса Test и названия тестируемого класса.
8.1. Именование тест методов
8.2. Структура теста
Каждый тест ТРЕБУЕТСЯ оформлять согласно структуре, описанной ниже (каждый блок отделяется от остальных пустой строкой).
ДОПУСКАЕТСЯ отклонение от данной структуры, в случае, если полное следование ей невозможно. Например, когда значение переменной [3] определяется только после вызова конструктора тестируемого класса [6].
8.3. Переменные, используемые в тесте
Переменные, используемые в тесте ДОЛЖНЫ следовать следующим правилам.
Mock-объект ДОЛЖЕН быть объявлен, согласно следующим правилам.
8.5. Инкременты вызовов mock-объектов
8.6. Поведение методов mock-объектов
Поведение методов mock-объектов ДОЛЖНО описываться согласно одной из следующих структур.
8.7 Порядок утверждений для одного значения
В случае когда для проверки одного значения требуется несколько утверждений, эти утверждения ДОЛЖНЫ быть описаны в порядке от максимально информативных до минимально информативных, далее от общих к частным.
8.8. Проверка утверждений на основании результатов собственных проверок
Проверка утверждений на основании результатов собственных проверок ДОПУСКАЕТСЯ только в случае, когда отсутствует assert* метод, включающий эту проверку. Во всех остальных случая НЕОБХОДИМО использовать assert* метод.
Распространенной ошибкой является «ручная» проверка значения и утверждение о ее ложном, или положительном результате. В следствии такого подхода, срабатывание утверждения не покажет информацию о том, что же пошло не так.
8.9. Проверки значений на основании TestCase::callback
8.10. Проверка утверждений для числовых значений
Для проверок числовых значений с учетом погрешности ДОЛЖЕН использоваться метод assertEqual с обязательным указанием погрешности.
8.11. Проверка утверждений для \DateTimeImmutable
Для проверок \DateTimeImmutable зависящих от текущего времени ДОЛЖЕН использоваться метод assertEqual с обязательным указанием погрешности.
В случае проверок данных на основании текущего времени высока вероятность ложно позитивных и ложно негативных результатов. Дело в том, что сам процесс выполнения теста требует некоторого времени, как результат это время является неявной и не контролируемой переменной в тесте.
Для разработки php проектов РЕКОМЕНДУЕТСЯ использовать PhpStorm.
9.1. Inspections и Code Style
hipot
hipot srew
Последний раз редактировалось:
25.11.2010 13:00 (вер.1.06)
Стандарт написания кода — это очень важно
Опыт многих проектов показывает, что при использовании стандартов кодирования управление и разработка идет легко и гладко. Но достаточно ли стандарта для успешного проекта? Конечно, нет, но они помогают. А мы должны использовать все инструменты, которые упрощают нам жизнь! Поверьте, многие протесты против стандарта кодирования исходят из чьего-то ущемленного самолюбия. Но для того, чтобы следовать стандартам необходимо минимальное усилие над собой, а также необходимо помнить, что любой проект — это коллективная работа.
Хороший стандарт кодирования важен в любом проекте, и особенно там, где множество разработчиков работают над одним проектом. Наличие стандарта кодирования помогает гарантировать, что код высокого качества, с меньшим количеством ошибок, и легко поддерживается. Правила форматирования кода должны быть едиными во всем проекте. И крайне желательно, чтобы они были очень похожими между проектами.
Содержание
Отступы
Использовать tab вместо пробелов, т.к. обычно редактор настраивается, сколько пробелов проставлять за tab. Делаем отступов столько, сколько необходимо, но не больше. Существует правило о максимуме числа отступов. Если вложенность в коде больше, чем 4 или 5 уровней, то следует задуматься о переработке такого кода. Конечно, это рекомендация, в реальной жизни уменьшить число вложений до 5ти не всегда возможно, поэтому будем надеяться на мудрость программиста при написании кода.
#2. Соглашения по именованию
Хорошее именование в коде имеет определяющее значение при отладке, поиске ошибок и дальнейшей работе с кодом.
Имена файлов
Классы
Интерфейсы (пока бог нас от них уберег, однако:)
Именование функций и методов
Именование методов в классах
Именование переменных
Префиксы имен переменных для удобочитаемости
Использование префиксов является строго рекомендуемым, однако в частных случаях разрешено отступать от них. PHP — не особо типизированый язык и в нем различаются по смыслу три группы типов: скалярные, массивы и объекты. Скалярные типы следует начинать с префиксов всегда, если точно известно, что они имеют заданный тип:
Константы
#3. Стиль кодирования
Строковые литералы
Конкатенация строк
Массивы с числовыми индексами
Ассоциативные массивы
Определение класса
Классы должны определяться по следующей схеме:
Переменные-члены классов
Переменные-члены классов должны определяться по следующей схеме:
Определение функций и методов
Функции должны определяться по следующей схеме:
Использование функций и методов
Функции должны определяться по следующей схеме:
Управляющие структуры и простановка скобок
Использование комбинации « else if » вместо конструкции elseif допускается.
Альтернативный синтаксис рекомендуется использовать только в частях, которые используют прерывания на вывод html-кусков (напр. для шаблонов вывода). Просто в отформатированном PHP-коде строго не рекомендуется использовать альтернативный синтаксис, т.к. теряется учет открытых-закрытых скобок (к тому же многие среды разработки позволяют легко найти открывающуюся скобку по закрытой, но не позволяют найти начало if (…): по его окончанию — endif; ). Пример:
Правила написания switch-конструкции
Тернарный оператор ’?:’
Использование коротких тегов ’ short_open_tag конфигурационного файла php.ini. Для вывода в шаблоне одной переменной или результата выражения удобно пользоваться записью ’ ’ вместо ’ ’. Для длинных выражений (более одного тернарного оператора) использование такой записи практически не оправдано. Пример:
Пробелы вокруг знаков операций
Любые операторы / знаки операций (например =, ==, =>, >, и т.п.) обязательно отделяются пробелами с обоих сторон. В арифметических выражениях количество пробелов вокруг знаков операций можно варьировать, чтобы подчеркнуть приоритет операций. Примеры:
Пробелы вокруг сложных индексных выражений
В случае, если Вы обращаетесь к элементу массива по индексу и индексное выражение достаточно сложное, отделяйте его пробелами для улучшения удобочитаемости. Если выражение простое — пробелы не обязательны.
Декларативный блок желательно выравнивать по правому краю
Данный подход упрощает читаемость и понятность кода. Используем пробелы после знака присвоения для этих целей.
Каждый оператор должен быть на новой строке
Необходимо, чтобы в каждой строчке присутствовало только одно выражение.
Напр. допустимо: Не допустимо:
Всегда документировать пустое выражение
Пустые строки для дробления кода на логические блоки
Пустые строки помогаю разбивать код приложения на логические сегменты. Несколькими строками могут отделяться секции в исходном файле. Одной пустой строкой отделяются друг от друга методы, логические секции внутри метода для более удобного чтения.
Перед логической секцией рекомендуется вставить комментарий, в котором будет указано назначение этой секции. Удобно в этом случае пользоваться тегом @todo из стандарта PHPDocumentor’a: (см. раздел «Встроенная документация»)
Подключение файлов: include или require?
Встроенная документация и комментарии
Комментарии внутри кода классов должны соответствовать синтаксису комментариев PHPDoc, который напоминает Javadoc. За дополнительной информацией о PHPDoc обращайтесь сюда: http://www.phpdoc.org/
Дополнительные комментарии, кроме тех, что предусмотрены PHPDoc, только приветствуются. Основное правило в данном случае — каждая часть кода повышенной сложности должна быть прокомментирована до того, как вы забыли, как она работает.
Подходят комментарии в стилях C ( /**/ ) и C++ ( // ). Использование комментариев в стиле Perl/shell ( # ) не рекомендуется.
Встроенная документация — Файлы
В каждый файл, содержащий PHP-код, желательно размещать заголовочный блок в начале файла, содержащий как минимум следующие phpDocumentor-теги:
Встроенная документация — Классы
Встроенная документация — Функции
Для функций и методов документация в виде phpDocumentator обязательна. Каждая функция, включая методы объектов, должна иметь doc-блок, содержащий как минимум:
#4. Дополнительные частные случаи, на которые следует обратить внимание
Не следует делать реальную работу в конструкторе
Напр. если мы хотим открыть соединение c БД, то делаем метод Open(), в котором и совершаем открытие. Причина: конструктор не может вернуть значение (напр. ошибку).
Короткие методы
Желательно, чтобы метод (функция) занимал не более одной страницы кода. Большой метод необходимо делить на кучу маленьких, в таком случае мы добиваемся преждевременной оптимизации кода за счет продумывания структуры одной большой задачи и разделение их на подзадачи (структурный подход к построению решения)
Рефакторинг
Не живите с «разбитыми окнами»!
Не оставляйте «разбитые окна» (неудачные конструкции, неверные решения или некачественный текст программы) без внимания. Как только Вы их обнаружите — чините сразу. Часто безошибочные, функциональные системы быстро портились, как только окна начали разбиваться. Не давайте энтропии победить себя.
Старайтесь повторно использовать свой и чужой труд
Очень часто разработчики ленятся делать библиотеки классов & методов, которые упрощают жизнь и себе и команде. Очень хорошо, когда программист собирает себе библиотеку с кодом для последующего использования. Конечно, это идеальная картина, когда в студии существует хорошо задокументированная библиотека наработок и о том, что в ней находится, знают все разработчики студии.
Do not Repeat Youself — не повторяй самого себя!
Подумайте о повторном использовании кода. Зачем тратить впустую усилия мысли на одноразовые программы, если в будущем вам может потребоваться что-то подобное снова? Подумайте над обобщением вашего кода. Подумайте над написанием модуля или класса. Подумайте, не предложить ли Ваш код другим.
Don’t Reinvent Wheel — Не переизобретайте колесо!
Не переизобретайте колесо — если подобное колесо уже существует, просто адаптируйте его для своих нужд. Вероятно, для решения данной проблемы уже существует стандартный модуль в ядре PHP или API CMS, или модуль, разработанный другими людьми внутри организации. Иногда не составляет труда найти нужный код в интернете.
Куски кода и ответственность
Каждый человек должен отвечать за свои куски кода. Соответственно, если в них возникают ошибки, то человек, который написал код, идет исправлять ошибку. Тем более если из-за части чьего-то кода перестает работать вся целая система, то за эту часть «создатель» должен нести ответственность.