архитектура веб приложений php

Построение гибких PHP приложений

Эра фулстэк фрэймворков в прошлом. Современные разработчики фрэймворков разделяют свои монолитные репозитории на компоненты с помощью ответвлений в Git, позволяя разработчику выбрать то, что действительно необходимо его проекту. Это означает, что вы можете построить свое приложение на топовых Zend Service Manager, Aura Router, Doctrine ORM, Laravel (Illuminate) Eloquent, Plates, Monolog, Symfony Cache или любых других компонентах, которые можно установить через Composer.

архитектура веб приложений php. 9acdbed47ffacd36b80143aed62c3194. архитектура веб приложений php фото. архитектура веб приложений php-9acdbed47ffacd36b80143aed62c3194. картинка архитектура веб приложений php. картинка 9acdbed47ffacd36b80143aed62c3194.

Надежная структура проекта

Основным шагом является создание и поддержка строгой структуры проекта, с целью установки и комбинирования компонентов из инфраструктуры любых фрэймворков. Я посвятил этому целую статью, чтобы охватить вопросы структуры каталогов, организации и группировки исходников, соглашений об именовании и прочим связанным вещам.

Выбор правильного инструмента для работы

В течении разработки проекта, необходимо всегда уделять внимание бизнес логики ядра. Для всех общих задач, которые необходимо реализовать в вашем проекте, вы должны использовать различные open source решения, компоненты и библиотеки, который облегчат процесс разработки приложения. DBAL, ORM, routing, mailer, cache, logger – это далеко не полный список примеров того, что не нужно заново создавать.

Напомню, что вы можете использовать компоненты независимо от фрэймворка (Zend Framework, Symfony, Laravel, Aura и т.д.) Соответственно, зависимости в созданном composer.json могут выглядеть так:

Составляющие фрэймворка

Использование различных компонентов фрэймворка дает нам большое преимущество, но, если пользоваться ими не обдуманно, это может привести к безвыходным ситуациям. Главной, но не простой задачей, является разделение вашей бизнес логики фрэймворка или библиотеки для автономного использования. Если не уделить этой задаче достаточно внимания, то у вас могут возникнуть проблемы при попытке перейти на компонент другого разработчика или, даже, при обновлении версии текущего компонента.

Невозможно на 100% разделить код от фрэймворка, только если вы совсем не используете его, но вы можете значительно уменьшить связанности. Создайте интерфейсный уровень абстракций и разделите ваш код на внешние зависимости или используете PSR интерфейсы для того, чтобы снизить трудозатраты при переходе на альтернативные имплементации компонента. Короче говоря, создание интерфейсов – является лучшей практикой, который вы должны овладеть и уметь применять ее на деле.
В идеале, вот список того, где у вас могут быть прямые зависимости:

Управление конфигурацией

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

Основным недостатком такого подхода является дублирование параметров в нескольких конфигурационных файлах.

Я предпочитаю другой способ для работы с конфигурацией сред, который практикует Zend Framework (о нем хорошо написано в документации). При использовании этого метода, структура конфигурационных файлов выглядит так:

В этом примере параметры могут быть четко распределены по разным конфигурационным файлам, основываясь на их назначении, при этом они переопределяются в зависимости от среды окружения. Такие конфигурационные файлы содержат только переопределяемые параметры. Эти файлы объединяются в единую конфигурацию с помощью glob brace.

Инъекция зависимостей

Практическое использование инъекции зависимостей (Dependency Injection) очень важна для гибкости и надежности вашего кода. DI контейнер – это ключевая концепция, которая управляет логикой при построении блоков вашего приложения.

Вот что должно быть определено в DI контейнере:

Другие группы классов представляют такие типы как доменные объекты, сущности, значения объектов. Думайте о User, Post, DateTime, как о конкретных примерах этих классов. Все они не являются сервисами, поэтому не должны определятся в контейнере.

Настройка DI контейнера

Вместо того, чтобы программно заполнять DI контейнер, логичнее определить все зависимости внутри конфигурации:

Некоторые DI контейнеры, такие как, например, Zend Service Manager, поддерживают такой подход из коробки, в противном случае вам придется написать простую логику для его заполнения на основе массива конфигурации.

Возможно вы заметили, что я предпочитаю использовать полное имя интерфейса в качестве имени сервиса на котором реализуется интерфейс. В местах, где нет интерфейса, я использую полное имя класса. причина проста, извлечение служб из контейнеров не только делает код более читаемым, но и облегчает для пользователя понимание того с чем он работает.

Бутстрэппинг

Код, который загружает конфигурацию и инициализирует DI контейнер обычно содержится в, так называемом, сценарии начальной загрузки. В зависимости от конфигурации и реализации DI контейнера, он может принимать следующие формы:

DI контейнер – это конечный результат операции начальной загрузки, через который реализуются все дальнейшие действия.

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

Phoundation

Логика бутстрэппинга может быть достаточно громоздкой и дублироваться между проектами, поэтому я создал библиотеку Phoundation, благодаря которой у меня получается более компактный загрузочный файл:

Полный пример

Чтобы получить общую картину, возьмите, в качестве примера, это простое приложение для работы с блогами, которым можно воспользоваться как через браузер (public/index.php), так и через командную строку (bin/app). Он использует микро-фреймворк Slim для вэб части приложения и Symfony Console для CLI.

Подводя итоги

Описанная концепция — это скелет, оболочка вокруг ядра кодовой базы, состоящая из логики домена, поддерживаемой различными компонентами общего назначения. Эта оболочка является фундаментом для создания приложений с использованием библиотек и инструментов на свой вкус.

Когда приступаешь к новому проекту, вопрос должен быть не в том «какой фреймворк мне использовать?», а в том «какие компоненты я буду использовать в проекте?».

Источник

Пошаговый алгоритм создания архитектуры PHP-сайта

Разработка архитектуры должна начинаться в тот момент, когда вам в голову пришла идея «хочу сайт такой-то» или кто-то вложил идею «нужен сайт такой-то». К сожалению, большинство разработчиков сразу приступают к написанию кода, причём даже не того, какого нужно.

Прежде чем писать код, вооружитесь листочком с ручкой, вордпадом, вордом, райтером или даже вашим редактором кода и выполните пару шагов.

Шаг 1. Постановка главной задачи

Архитектура разрабатывается сверху вниз. Что это значит? Это значит, что сперва вы продумываете самые главные подсистемы, прежде чем приступить к обслуживающим их или более техническим.

Многие программисты начинают разработку сайтов с роутеров, подключения к БД, обработки ошибок, что приводит к необходимости переписывания их кода в будущем или обильной вставке в код костылей, как только они натыкаются на то, что не смогли предусмотреть.

Всё предусмотреть невозможно, для этого и нужно разрабатывать систему сверху вниз. Наличие работающих высокоуровневых классов практически автоматически определяет все необходимые требования к обслуге.

Это не единственный метод, но по опыт знаю, что самый оптимальный для тех, кто не чувствует себя, как рыба в воде среди паттернов проектирования или даже совсем про них не знает.

Итак, вам нужен блог, интернет-магазин, сайт стоматологической клиники.

Определитесь, что на вашем сайте самое главное, ради чего всё затевается.

Для блога — это, очевидно, записи. Для магазина — товары. Для сайта поликлиники — услуги.

Уже можем написать немного кода, с которого и начнётся разработка сайта:

или class товары <>, или class услуги<>

Это ваша главная подсистема. Сразу же можно написать, чем именно она будет управлять.

или class товар <>, или class услуга<>

Шаг 2. Определить, что ваша система умеет делать

Мы создали главную подсистему «записи». Следующий шаг: определить, что она будет уметь, чему мы хотим научить наш сайт.

Очевидно, она должна уметь создавать записи, удалять записи и получать записи.

Забудьте, что вы пишите код сайта, забудьте про пользователей, url-адреса, оформление страниц. Работайте с голыми данными: строками, числами, массивами, объектами.

Шаг 3. Понять, с чем имеем дело

Что такое запись? Что такое услуга? Что такое товар? Для вас, как программиста — это просто совокупность данных. В третьем шаге определяем, что это за совокупность.

Не стремитесь предусмотреть всё, что понадобится когда-то в будущем. Берите самый-самый минимальный набор. Для этого мы и строим архитектуру приложения, чтобы в будущем её было легко нарастить.

Очевидно, запись — это заголовок и текст записи. Услуга и товар — название, описание и цена.

Компьютер — не очень умное создание, по сравнению с человеком, вы не сможете сказать ему: «а покажи-ка мне запись, ту, где про зелёного котёнка написано», поэтому ему всегда необходим какой-то уникальный код, чтобы он среди множества записей узнал именно ту, которую вы хотите.

Это либо порядковый номер (id), уникальный для каждой записи или некое, столь же уникальное, строковое значение.

Значит наша запись — это идентификатор записи (id), заголовок, текст.

Больше нам ничего не нужно.

Шаг 4. Определение необходимых знаний

Теперь для каждого действия системы нам нужно понять, что системе нужно знать, чтобы это действие выполнить.

Для действия «создать_запись» нужно знать заголовок и текст записи. Внутренний идентификатор нужен только компьютеру, поэтому пусть сам его и придумывает.

Для действий «удалить_запись» и «получить_запись» нужно знать только тот самый идентификатор записи, который был ей присвоен компьютером при создании.

То, что получилось называется интерфейсом вашего класса/модуля/подсистемы.

Шаг 5. Определение результатов

Также, как мы узнали необходимые знания для выполнения того или иного действия, нужно понять, чем эти действия будут оканчиваться.

Для всех ситуаций, когда что-то не получилось поведение программы должно быть одинаковым во всех модулях/классах/подсистемах вашей системы. PHP предоставляет всего два варианта: trigger_error и throw new Exception. Можете придумать свой, но не стоит изобретать велосипеды, пока вы не научились ездить на существующих. throw new Exception — самый оптимальный вариант.

Читайте раздел «исключения» в официальном мануале.

Шаг 6. Снова с начала

В шаге первом, кроме создания системы управления записями, мы создали ещё класс и самой записи: class запись <>

Для неё нужно сделать тоже самое, что и для главной, те же самые шаги с 1 по 5.

Если вы всё сделали правильно, то у вас должно получиться что-то похожее.

Шаг 7. Пишем код

Теперь, когда всё создано можно приступать к кодированию. Если вы знакомы с PHP никаких проблем у вас не возникнет.

Сколько затратили времени? Совсем чуть-чуть, и ещё ощутите в будущем всюпользу от произошедшего.

То, что у вас получится в итоге скрывается под буквой M в страшной аббревиатуре MVC.

Заключение

Я не учёл много нюансов, их хватит на десять таких же статей, но базис для вашей разработки уже есть. Это — самые основы и это в любом случае лучше, чем мешать PHP с HTML в одном файле или плодить кучу функций по мере написания кода.

C M разобрались. Что касается V и C. Это тема для других статей. Поэтому вкратце. Если вы достаточно сообразительны, то другие статьи вам и не понадобятся.

C — это место, в котором система реагирует на действия пользователя. Вот там и нужно думать, что будет делать пользователь. Захотел пользователь создать запись в блоге, заполнил форму создания, а у вас уже всё готово, чтобы выполнить его команду. Захотел, прочитать запись и снова вы выполняете его просьбу в одну строчку. Там главная задача (шаг 1) — понять, что хочет пользователь.

V — изучите любой шаблонизатор: Smarty или Twig. Много споров ведётся про то использовать шаблонизаторы или нет, много убедительных доводов с той и с другой стороны. Правда в том, что для web-разработчика непростительно не уметь работать с шаблонизаторами. Поэтому осваивайте их, а потом уже откажетесь, если не понравится.

Как уже было отмечено выше, на русском языке почти нет достойный литературы на эту тему.
Единственную книгу, которую могу посоветовать прочитать: Стив МакКоннелл «Совершенный код».

Если кто-то знает другие материалы киньте в меня ссылочкой. С удовольствием прочитаю и буду рекомендовать новичкам.

Источник

Что почитать об архитектуре приложений и фреймворков на php?

В целом сразу вас расстрою, то что вы хотите нельзя «разобрать» за пару месяцев. На это уйдет пару тройку лет. И книги которые стоит по этой теме прочитать имеет смысл перечитывать. Ну и практика практика практика.

но совершенно не имею представления о правильной архитектуре приложений на php

«Правильно» не бывает, все зависит от задачи. «Правильная» архитектура является:

Вот и все. Далее уже есть принципы SOLID (читать Роберта Мартина), GRASP (Крэйг Ларман), GoF (лучше тут почитать head first design patterns или даже начать с Мэта Зандстры, у него помимо паттернов еще про процессы мельком рассказано).

Ну и смысла в этом всем нет если вы еще до конца не осознали что есть инкапсуляция и полиморфизм. Многие могут рассказать что значат эти термины, но на практике эти знания они не могут применить (чаще всего страдает инкапсуляция)

или написании чего-то своего с нуля на чистом php

Такое решение может принимать только разработчик у которого уже есть за плечами хотя бы пяток лет опыта работы с различными (не одним) фреймворком и языками. В противном случае вы только будете заниматься бесполезным велосипедостроительством.

идеально было бы вообще подробно расписанное сравнение внутреннего устройства нескольких фреймворков

Берете Symfony или Zend и вперед. Все остальные фреймворки «проще». То есть скрывают больше от разработчика. После них уже можно брать что угодно.

Источник

Архитектура сложных веб-приложений. С примерами на Laravel

Эта книга не пособие. Много шаблонов описаны поверхностно, с целью просто познакомить читателя с ними. Более подробное описание можно найти по ссылкам в конце.

Книга читается легко и с интересном, никакой воды, наоборот, иногда хочется продолжения и углубления в тему, больше примеров, но Адель оставляет нам это на самостоятельную проработку.

Вот некоторые из интересных вопросов, рассмотренных в книге.

Какие ограничения несёт в себе мышление в стиле Create, Read, Update, Delete (CRUD)?

Забавно, что в одном из подкастов, который я когда-то слушал (уже не вспомню какой точно), создатель Laravel, Taylor Otwell подметил, что все его приложения отлично укладываются в модель CRUD, а если нужно что-то иное, какой-то отличное от этого действие, то скорее он что-то делает не так. Вот такая полярность мнений.

Опасность наследования и концепция: класс должен быть либо финальным, либо абстрактным. Сильно поддерживаю, не раз обжигался на наследовании конкретных реализаций и с опытом пришел к такому же выводу: если наследоваться, то только от абстрактного класса.

Польза от внедрения зависимостей и когда оно не нужно? А статические методы — есть ли для них место под солнцем?

Трейты. Адель рассмотрел трейты со всех сторон, когда они уместны и когда бесполезны.

Однако, приведу небольшую цитату, к которой у меня остались вопросы:

Я не люблю Трейты. Они могут с успехом использоваться в классах тестов, поскольку там нет хорошей причины организовывать полноценное DI, но лучше избегать их использования в главном коде приложения. Трейты — это не ООП, а чистые ООП решения всегда будут более естественными.

Тут хочется переспросить, что такое «чистые ООП решения»? Борцы за чистоту ООП скажут, что наше ООП — это вообще не ООП, которое имел в виду отец-основатель настоящего ООП Алан Кей! С другой стороны, напирают адепты настоящего ООП, прочитавшие книгу Elegant Objects Егора Бугаенко.

Поэтому я всегда насторожено отношусь к формулировкам, которые делают отсылки к определению ООП. Трейты — это не ООП? Зависит от вашей ООП конфессии!

Отлично описаны вопросы передачи данных запроса внутрь приложения с помощью DTO.

А также валидация. Валидация с помощью Form Requests, валидация непосредственно в сервисах, валидация с помощью аннотаций в Symfony, и валидация в конструкторах Value Objects.

Если мыслить объектами и грамотно применять Value Objects для представления данных — это всё усложнит или всё упростит, в чём профит?

Обработка ошибок, что выбрать — повсеместно использовать исключения или возвращать Optional значения? Вообще, возврат Optional имеет много плюсов и активно используется в функциональных языках программирования, но несколько чужд нам, в экосистеме PHP.

Про исключения Адель отлично разложил по полочкам чем отличаются проверяемые и не проверяемые исключения — это два типа исключений, которые явно реализованы в синтаксисе Java. В PHP явного деления нет, но PhpStorm даёт нам подсказки, опираясь на ту же модель проверяемых и не проверяемых исключений. Очень полезная глава для понимания, как обрабатывать различные типы ошибок.

События и чем неудобны события Eloquent. Лучше использовать свои собственные доменные события.

Тестирование. С Unti тестированием простых чистых функций всё просто, но что делать с тестирование сервисов, имеющих много зависимостей и как не утонуть в коде, конфигурирующем все эти зависимости в виде моков и стабов? Из-за желания написать Unit тесты на относительно сложные сервисы, иногда мы обрастаем излишними абстракциями, код самого приложения становится сложнее чем хотелось бы и чем он мог бы быть.

Что делать? Менять подход к написанию сервисов и отделить слой приложения от доменной логики. Читая книгу, мы от unti-тестирования сервисов плавно переходим к DDD и возвращаемся к unit-тестированию, но уже доменного слоя и тут всё встаёт на свои места. Только от этого не становится легче, т.к. это уже не похоже на типичное Laravel приложение. Кажется, что уже проще писать сразу на Symfony, чтобы все эти советы применить.

Вынесение доменной логики — это большой шаг в эволюции проекта. Намного более практично делать его в самом начале, но архитектор должен оценить сложность этой логики. Если приложение — это простой CRUD с очень небольшой дополнительной логикой, то от доменного слоя будет мало толку.

Вспоминая слова Тейлора, что он практически любую логику своих приложений успешно вписывает в CRUD, всё становится на свои места.

Последние две главы про CQRS и Event Sourcing с неплохими примерами.

Так что рекомендую к прочтению: «Архитектура сложных веб-приложений. С примерами на Laravel», автор Adel Faizrakhmanov. Книга доступна на русском и на английском.

В заключение, оставлю заключение к самой книге:

Эта книга просто некий обзор практик, которые мне показались полезными при разработке приложений. Возможно, кому-то она поможет выбрать нужную для своего проекта. Главное, понять, что книга не о том, что надо каждое приложение взять и переписать с использованием, например, Event Sourcing. К каждому приложению нужен свой подход и одни и те же практики отлично подходят к одним приложениям, но будут вредны для других.

Источник

Архитектура и ООП

архитектура веб приложений php. blog promo e872632493a971b3ba0722ccffaec76d1df333a297017200dadbff257e5959c1. архитектура веб приложений php фото. архитектура веб приложений php-blog promo e872632493a971b3ba0722ccffaec76d1df333a297017200dadbff257e5959c1. картинка архитектура веб приложений php. картинка blog promo e872632493a971b3ba0722ccffaec76d1df333a297017200dadbff257e5959c1.

Изначально этот материал планировался как урок в PHP-курсе по полиморфизму. Но он, в конце концов, перерос сам урок, и я решил сделать из него отдельную статью. В ней практически ничего PHP-специфичного, поэтому рекомендуется для прочтения всем без исключения.

Напомню, что модель классов PHP взята из Java. Наличие интерфейсов и всех сопутствующих элементов очень сильно влияет на способ организации кода в PHP. Этот способ часто отличается от того, как организуется код в JavaScript, Ruby или Python. И ещё больше отличается от таких языков, как Clojure или Elixir. И всё это на фоне того, что в каждом из этих языков есть ООП.

ООП в этих языках настолько разное, что PHP-программисты, попадающие в Ruby или JavaScript, не понимают, как так можно писать, ведь многие подходы противоречат их представлениям о мире. То же самое происходит и в обратной ситуации.

Так где же правда? Правда в том, что есть вещи, которые действительно определяют архитектуру кода. И это не структура классов, не наличие интерфейсов и не использование полиморфизма.

Возьмём тот же MVC. В нём говорится о слоях, об их задачах (зонах ответственности) и способе взаимодействия друг с другом. Это крайне важно для модульности. В модульной системе отсутствуют циклические зависимости. В MVC ничего не говорится про классы и ООП в целом, потому что между этими понятиями нет связи. Реализовать MVC можно в любом языке общего назначения, каким бы он ни был. То же самое можно сказать обо всех других архитектурных шаблонах.

Архитектура опирается на особенности среды, в рамках которой она применяется, а не на конструкции языка. Например, в вебе господствует HTTP, который построен вокруг концепции «запрос-ответ». Именно поэтому микрофреймворки разных языков выглядят так похоже, независимо от того, есть там ООП или нет: в каждом микрофреймворке есть запрос, ответ и обработчик ответа.

В современной разработке ООП стало чем-то вроде культа карго. Это негативно влияет на неокрепшие умы. Если погуглить по запросу «какой паттерн применить», то можно найти много интересного и грустного:

Подобные вопросы появляются только от непонимания того, что человек делает, и попытка заткнуть проблему паттерном дорого обойдётся проекту.

Читайте также Лучшие книги для начинающих программистов по версии наставников Хекслета

Это не значит, что ООП и паттерны знать не нужно. Нужно, особенно если вы работаете в классовых языках, но это всего лишь одна из многих и не самых критичных частей. Те же ООП-паттерны (это не архитектурные паттерны, например MVC — не ООП-паттерн) чаще применяются в локальных ситуациях. То есть их влияние на архитектуру сильно ограничено.

Архитектура кода

Ниже попробуем разобраться с тем, как всё же стоит писать код, на что обращать внимание и что за чем следует в порядке важности.

Основные части приложения

По каждому указанному ниже аспекту можно написать целую книгу. Найти множество исключений и особых ситуаций, в которых эти подходы не применимы. Либо применимы, но со множеством уточнений. Прошу понять и простить.

Модель предметной области

В ядре любой системы лежит модель предметной области. Это алгоритмическая часть программы (то место, где происходят вычисления), которая отражает бизнес-задачу. Например, на Хекслете предметная область — это образовательная система. Внутри этой области есть понятия, такие как «курс», «урок», «профессия», «студенты». Все они могут взаимодействовать по определённым правилам.

Перед тем, как приниматься за кодирование предметной области, хорошо бы её понимать, представлять набор сущностей, с которыми она работает, и связи между ними. Однако, в вебе модель предметной области не проектируется «от и до» перед кодированием. Обычно берётся только тот кусок, над которым идёт работа прямо сейчас, и только он переносится на код. В дальнейшем, по мере надобности, добавляются и другие части.

Сущности в коде представляются разными структурами, здесь уже всё зависит от языка. В некоторых языках это структуры, в других — объекты, в третьих — записи. Но какой бы способ и язык не были выбраны, пользователь останется пользователем, а курс — курсом! И для этого не обязательно иметь объекты.

Эта часть, в идеале, не знает ничего про среду использования, находимся мы в браузере или на бекенде или внутри банкомата. Таким образом достигается модульность, система разбита на слои, которые замкнуты относительно своих операций и не знают про окружение. На практике добиться полной изоляции сложно и, скорее всего, не нужно. Но нужно избегать протекания абстракции, то есть слой верхнего уровня знает про слой лежащий под ним (и использует его), а вот нижний слой не может знать про то как им пользуются. В примере с Хекслетом, код внутри слоя, отвечающего за операции с курсом, не может знать про существование http и веб-фреймворка.

Среда

Следующая важная часть – среда исполнения. Она определяет основную архитектуру приложения. Если мы работаем в браузере, то это событийная модель, если в бекенде по http — то «запрос-ответ», а в командной строке — прямой запуск кода на исполнение. Есть и другие среды со своими особенностями. Для каждой из них наработано большое количество архитектурных подходов, которые придумывать не нужно — они уже реализованы во фреймворках. В первую очередь это MVC. Причём в зависимости от среды либо MVC1 либо MVC2.

Для хорошего понимания правил работы в данном слое нужно знать операционные системы и сети. Например, невозможно построить хорошее API, не зная протокол HTTP, не имея понятия об идемпотентности и гарантиях доставки сообщений в распределённых системах.

Основные принципы структурирования кода

Изолируйте побочные эффекты от чистого кода

Всё, что связано с вводом/выводом, должно быть не внутри, а, желательно, на самом верхнем уровне. Причём чаще всего в начале работы программы происходит чтение необходимых данных, потом — большой блок основной логики (чистый код) и на выходе — снова побочный эффект, например, запись в файл. В вебе это «запрос-ответ».

Следите за идемпотентностью

Если операцию возможно реализовать так, что она может быть перезапущена в случае ошибки и это не приведёт к проблемам, то операция должна быть реализована именно так. В первую очередь это относится к периодическим и асинхронным задачам.

Используйте автоматное программирование

Программирование на флагах — индикатор кода, который нужно переписывать. Автоматы можно применять крайне широко. Фактически, любой процесс, протекающий внутри системы — потенциальный конечный автомат. Например:

Избегайте глобальных переменных.

Ими могут выступать и объекты, и классы, имеющие внутреннее состояние, которое может поменяться в процессе жизни приложения.

Избегайте ненужного состояния и разделяемого состояния (shared state)

Первое особенно часто проявляется тогда, когда объекты наделяются внутренним состоянием в ситуациях, где это не нужно. Например, при сохранении промежуточных данных между разными вызовами. Используйте формальный метод для проверки того, нужно ли в данной ситуации внутреннее состояние или нет. Проверьте, можно ли объект, выполняющий операцию, заменить функцией? И если ответ «да» — то состояния (кроме конфигурации) быть не должно.

Выделяйте абстракции по необходимости

Одно из ключевых правил в обучении программированию: не делайте ничего лишнего до тех пор, пока не начнёт болеть. Разбивайте и выделяйте, только когда почувствовали, что текущее положение дел мешает быть эффективным. Только в этом случае придёт понимание, когда стоит что-то делать, а когда — нет. В ином случае очень легко перейти черту и превратиться в «архитектурного астронавта» (overengineering)

Возможно, это контринтуитивно. Но гораздо проще изменять код, который находится в одном месте и не разбит на множество мелких частей. Разбивать имеет смысл тогда, когда архитектура устаканилась и все граничные случаи учтены. А до этого момента пусть оно будет неделимым.

Изолируйте технический долг

Не любой технический долг растёт. Если абстракция хороша и не протекает, то не принципиально, как написан код внутри. Его можно будет переписать, когда придёт время. Иногда приходит время — и код просто удаляется за ненадобностью. Простой пример: функция сортировки массива.

Разбивайте приложение на слои

Используйте уровневое проектирование (посмотрите модель OSI). Нижние слои не должны знать про сущности верхних слоев, а верхние слои работают на базе нижних. Пример разбиения.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *