Банда из четырех!

Как насчет того, чтобы начать обсуждение с их цитаты?

Их знаменитая книга «Шаблоны проектирования, элементы многоразового объектно-ориентированного программного обеспечения»; и это Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес.

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

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

Тем не менее, опытные объектно-ориентированные дизайнеры делают хорошие проекты. Тем временем новые дизайнеры перегружены доступными вариантами и склонны прибегать к необъектно-ориентированным методам, которые они использовали раньше. Новичкам требуется много времени, чтобы понять, что такое хороший объектно-ориентированный дизайн. Опытные дизайнеры явно знают что-то, чего не знают неопытные. Что это?"

Этот вводный абзац заканчивается знаком вопроса.

Я всегда буду призывать вас прочитать саму книгу; обязательно к прочтению, однако в то же время я хотел бы начать нашу дискуссию, оставив этот вопросительный знак на заднем плане — «Очевидно, что опытные дизайнеры знают что-то, чего не знают неопытные. Что это?"

Я не сомневаюсь, что «принцип единой ответственности» или SRP — одна из самых важных концепций в объектно-ориентированном проектировании, которую опытные дизайнеры знают и соблюдают с самого начала, а неопытные дизайнеры не понимают этой основной концепции. И это действительно большая разница.

Давайте начнем с основной концепции, лежащей в основе SRP — классы не должны делать слишком много вещей. Да, класс может многое сделать для объекта; но вы не можете злоупотреблять этой силой. Это может нанести неожиданный вред организации кода в целом. Когда легкое постукивание молотком работает нормально, зачем забивать гвоздь с огромной силой? Это может иметь эффект бумеранга.
Думать заранее и правильно проектировать — это совсем другое дело, чем заставить программное обеспечение работать. Мы всегда стараемся, чтобы наш код работал быстро; не оставляя места для организации и чистоты.

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

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

Надеюсь, вы начали догадываться, как Composer вписывается в эту общую картину. На самом деле это причина, по которой каждый хороший фреймворк PHP, такой как Symfony или Laravel, зависит от этой системы управления зависимостями. Более того, Composer теперь стал стандартом управления зависимостями.

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

//код 1
ss@ss-Lenovo-3000-G530:/$ php -r copy('«https://getcomposer.org/installer', 'composer-setup.php');»
сс @ сс-Lenovo-3000-G530: / $ PHP -r , если (hash_file ( 'SHA384', 'композитор-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') {эхо 'Установщик проверяется'; } else { echo ‘Установщик поврежден’; развязать('композитор-setup.php'); } echo PHP_EOL;
Установщик проверен
ss@ss-Lenovo-3000-G530:/$ php composer-setup.php
Все настройки верны для использования Composer
Загрузка…

Композитор (версия 1.6.5) успешно установлен на: //composer.phar
Используйте его: php composer.phar

ss@ss-Lenovo-3000-G530:/$ sudo php composer-setup.php — install-dir=/usr/local/bin — filename=composer
Все настройки верны для использования Composer
Загрузка…

Composer (версия 1.6.5) успешно установлен в: /usr/local/bin/composer
Используйте его: php /usr/local/bin/composer

В первой половине я загрузил установщик Composer в свой корневой каталог и проверил продукт. После этого я выбрал каталог «usr/local/bin/composer», чтобы настроить его так, чтобы я мог использовать его глобально.
Далее проверю работает или нет.

В каталоге «var/www/html» я создал папку с именем «test-composer» и инициализировал в ней только что установленный композитор.
//код 2
ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ composer init

Добро пожаловать в генератор конфигурации Composer

Эта команда поможет вам создать конфигурацию composer.json.

Имя пакета (‹vendor›/‹name›) [root/test-composer]: ss/mvc
Описание []: mvc
Автор [, n для пропуска]: n
Минимальная стабильность []: стабильный
Тип пакета (например, библиотека, проект, метапакет, композитор-плагин) []: проект
Лицензия []:

Определите свои зависимости.

Хотели бы вы определить свои зависимости (требовать) в интерактивном режиме [да]? y
Найдите пакет: cocur/slugify
Введите требуемое ограничение версии (или оставьте поле пустым, чтобы использовать последнюю версию):
Использование версии ^3.1 для cocur/slugify
Найдите пакет:
Хотите ли вы определить свои зависимости разработки (require-dev) в интерактивном режиме [да]?
Поиск пакета:

{
«имя»: «ss/mvc»,
«описание»: «mvc»,
«тип»: «проект»,
«требуется»: {
«cocur/slugify»: «³.1»
},
«минимальная стабильность»: «stable»
}

Вы подтверждаете поколение [да]? Д

Нажав кнопку «Ввод», я успешно создал файл «composer.json» внутри тестовой папки. Теперь я могу установить Composer.

//код 3
ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ composer install
Загрузка репозиториев композитора с информацией о пакете
Обновление зависимостей (включая require -dev)
Операции с пакетами: 1 установка, 0 обновлений, 0 удалений
— Установка cocur/slugify (v3.1): Загрузка (100%)
Запись файла блокировки
Генерация автозагрузка файлов
ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$

Композитор успешно установлен. Мы можем проверить список каталогов.

//код 4
ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ ls
composer.json composer.lock поставщик

Теперь вы можете использовать объект slugify, чтобы преобразовать любую строку в слаг. Он может обеспечить хорошую поддержку нашей шаблонной структуры MVC. Мало того, нам нужно использовать ресурсы других полезных пакетов, доступных в Packagist — The PHP Package Repository (https://packagist.org/).
Решение каждой проблемы из первых принципов не вообще хорошая идея.

Эффективные шаблоны всегда повторно используют решения, которые сработали для них в прошлом, чтобы мы могли использовать их снова и снова. Комбинация Composer и других пакетов PHP решает большую проблему, с которой мы сталкивались в течение долгого времени.
Во многих объектно-ориентированных системах существуют повторяющиеся шаблоны классов и взаимодействующих объектов, однако доступность этих шаблонов была крайне ограничена. в прошлом. Мы не проделали достаточной работы по записи опыта, чтобы это могли сделать другие. Если бы они это сделали, не было бы хорошего общего ресурса для извлечения из него повторяющихся шаблонов.

Используя комбинацию Composer и Packagist, теперь мы можем найти не только пакет, но и все его зависимости и связанные с ним библиотеки, метапакеты и композитор-плагин. Даже пакеты PEAR существуют, чтобы помочь в процессе принятия решений по вашему проекту.

Композитор и разделение интересов

Одним из основных принципов дизайна является «разделение задач».

Composer помогает нам довольно легко реализовать этот принцип проектирования программного обеспечения. Этот принцип напоминает нам о двух основных факторах: первый заключается в том, что каждый класс должен нести единственную ответственность. Во-вторых, единственная ответственность любого класса должна быть инкапсулирована самим этим классом. Давайте посмотрим, как это работает.
Прежде чем писать коды, давайте спроектируем его должным образом. В конце этой книги мы создадим фреймворк MVC с нуля. Имея это в виду, позвольте мне сначала создать папку в моем каталоге «/var/www/html». Назовем эту папку «mymvc».

Давайте отделим вывод от логики нашего приложения. Итак, мы создаем две папки «src» и «public» в нашем приложении «mymvc». В «общедоступной» папке у нас есть три папки — «css», для хранения наших файлов стилей CSS; «js» для файлов JavaScript; и «images» для хранения изображений. У нас также есть файл «index.php» в нашей «общедоступной» папке, поскольку он будет действовать как точка входа в наше веб-приложение MVC.

Теперь давайте подумаем о папке «src» (на самом деле она представляет собой слово «источник» или «ресурс»). У нас должны быть папки «контроллеры», «модели» и «представления» для хранения связанных классов. Я создал еще одну специальную папку под названием «karnel», чтобы хранить специальные классы для сохранения разделения задач. У нас также будет файл «init.php» для инициализации логики приложения.
Давайте посмотрим, как с помощью Composer мы можем сохранить это разделение задач.
Файл «composer.json» выглядит так:

//код 5
//composer.json

{
«автозагрузка»: {

«psr-4»: {
«Приложение\\»: «src/»,
«Контроллер\\»: «src/controllers»,
«Karnel\\»: «src/karnel»,
«Model\\»: «src/models»,
«View\\»: «src /просмотры»

}

}
}

Файловая структура довольно проста. Теперь мы можем запустить Composer и создать файл «../vendor/autoload.php».

Точка входа нашего приложения, то есть файл «index.php», должна требовать этот файл «init.php», чтобы мы могли создать там экземпляр нашего «Приложения».
Код файла index.php выглядит так:

//код 6
//public/index.php

‹?php
require_once ‘../src/init.php’;
используйте Karnel\Apply как Apply;
$app = new Apply;

Здесь «$ app» представляет экземпляр нашего приложения. А код файла «init.php» выглядит так:

//код 7
‹?php
require_once ‘../vendor/autoload.php’;

используйте Karnel\Error как ошибку;
$error = new Error;

Мы хотим отображать ошибки на каждой нашей рабочей странице, чтобы правильно следовать потоку. Итак, мы держим для этого отдельный класс «Ошибка» в нашей папке «karnel». В некоторых случаях модули display_errors закомментированы в файле php.ini. Этот пример «$ error» также поможет нам понять принцип разделения ответственности.

Код страницы «Error.php» такой.

//код 3.8
//src/Karnel/Error.php

‹?php пространство имен Karnel;

/*
* Для отображения ошибок PHP на каждой странице
*/

class Error
{
public function __construct() {

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
> error_reporting(E_ALL);

}
}

Этот класс «Ошибка» мог бы быть прекрасным примером единой ответственности, если бы он не нарушал принцип разделения ответственности. Но это нарушает принцип разделения интересов.

Почему? Это связано с тем, что при каждой инициализации часть логики нашего приложения напрямую попадает на вывод. То же самое верно и для нашего экземпляра приложения. Давайте посмотрим на код класса «Применить».

//код 3.9
//src/Karnel/Apply.php

‹?php
пространство имен Karnel;

/*
* Этот класс Apply от Karnel определяет типы объекта нашего фреймворкового приложения
*/

class Apply
{
public function __construct() {

$url = $this-›parsingURL();

}
< br /> public function parsingURL() {

if (isset($_GET['url'])) {
$string = filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL);
$url = Explosion('/', $string);
print_r($url);

}

}

}

Теперь, если мы введем в браузере следующее:
http://localhost/mymvc/public/hello/world/from/sanjib
Мы получим следующий вывод:
Массив ( [0] =› привет [1] =› мир [2] =› из [3] =› санджиб )

Существуют и другие механизмы, такие как использование файла «.htaccess» в нашей «общедоступной» папке. Чтобы мы могли разобрать URL-адрес в нашем классе «Применить». Код файла «.htaccess» такой:

//код 10
//публичный/.htaccess

Параметры - Мультивиды

RewriteEngine включен

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

Правило перезаписи ^(.+)$ index.php?url=$1

Я не буду объяснять код здесь, потому что я предполагаю, что у вас есть начальное обучение PHP, чтобы понять эту идею.

Для этого обсуждения давайте сосредоточимся на выводе, который я получил в своем браузере. Это массив, в котором $url[0] является «домом». $url[1] является индексом и так далее. Теперь мы можем сделать одну вещь из этого вывода. Мы можем сделать этот «дом» нашим основным контроллером; это может быть «домашний» контроллер, а «индекс» — его метод. Более того, мы можем передавать другие значения массива в качестве параметров метода index.

Я могу создать класс контроллера «Home» и с помощью метода «index» передать значение на страницу «view». Все, что мне нужно, это заботиться об одном. Класс Controller не должен знать «слишком много». Это нарушит наш принцип «разделения интересов», который является ключевым фактором эффективных шаблонов в PHP.

Здесь я хочу подчеркнуть один ключевой аспект Composer. Это помогает нам, позволяя нам использовать «пространство имен» и «структуру файлов» для достижения принципа разделения задач. При создании классов контроллера мы должны позаботиться об одном — контроллер не должен знать, откуда берутся данные и куда они уходят. Он не должен напрямую попадать в базу данных. Он не должен быть тесно связан.

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

Если вам интересно, вы можете получить весь пример кода в моем репозитории GIT: https://github.com/sanjibsinha/mymvc