Разделы
Теги | RSS © 2008 – 2017
Контакты
email: igor@veselov.sumy.ua
skype: utz0r2

10. Коротко ООП PHP - Шаблоны (паттерны) ООП. Типы шаблонов


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

Порождающие (Creational) - описывают механизм создания объекта и пытаются создать их в порядке, подходящем к ситуации.
Структурные (Structural) - упрощают проектирование путем выявления простого способа реализовать отношения между субъектами.
Поведенческие (Behavioral) - решают вопросы эффективного и безопасного взаимодействия между объектами.

Порождающие шаблоны
- Abstract Factory (Абстрактная фабрика) - позволяет создавать целые группы взаимосвязанных объектов, которые, будучи созданными одной фабрикой, реализуют общее поведение.
- Builder (Строитель) - используется для отделения процесса конструирования сложного объекта от его представления, так что в результате одного и того же конструирования могут получаться различные объекты. Этот паттерн очень похож на абстрактную фабрику, но в нем акцентируется пошаговое конструирование объекта - в отличие от фабрики, где конструируется семейство классов.
- Factory Method (Фабричный метод) - предоставляет подклассам интерфейс для создания экземпляров некоторого класса.
- Prototype (Прототип) - используется для задания вида создаваемых объектов на основе объекта прототипа, от которого происходит передача внутреннего состояния (создаёт новые объекты путём копирования прототипа).

Структурные шаблоны
- Adapter (Адаптер) - предназначен для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.
- Bridge (Мост) - используется для отделения абстракции от ее реализации так, чтобы и то и другое можно было изменять независимо.
- Composite (Компоновщик) - используется для компоновки объектов в древовидные структуры для представления иерархий, позволяя одинаково трактовать индивидуальные и составные объекты.
- Decorator (Декоратор) - используется для динамического расширения функциональности объекта. Является гибкой альтернативой наследованию.
- Facade (Фасад) - представляет собой унифицированный интерфейс вместо набора интерфейсов некоторой подсистемы. Паттерн фасад определяет интерфейс более высокого уровня, который упрощает использование подсистем.
- Flyweight (Приспособленец) - используется для уменьшения затрат при работе с большим количеством мелких объектов.
- Proxy (Прокси) - который предоставляет объект, который контролирует доступ к другому объекту, перехватывая все вызовы (выполняет функцию контейнера).

Поведенческие шаблоны
- Chain of responsibility (Цепочка обязанностей) - служит для ослабления связи между отправителем и получателем запроса. При этом сам по себе запрос может быть произвольным.
- Command (Команда) - представляет собой действие. Объект команды заключает в себе само действие и его параметры.
- Interpreter (Интерпретатор) - решает часто встречающуюся, но подверженную изменениям, задачу.
- Iterator (Итератор) - представляет собой объект, позволяющий получить последовательный доступ к элементам объекта-агрегата без использования описаний каждого из агрегированных объектов.
- Mediator (Медиатор) - обеспечивает взаимодействие множества объектов, формируя при этом слабую связанность и избавляя объекты от необходимости явно ссылаться друг на друга.
- Memento (Хранитель) - позволяет, не нарушая инкапсуляцию, зафиксировать и сохранить внутреннее состояние объекта так, чтобы позднее восстановить его в это состояние.
- Observer (Наблюдатель) - создает механизм у класса, который позволяет получать экземпляру объекта этого класса оповещения от других объектов об изменении их состояния, тем самым наблюдая за ними.
- State (Состояние) - используется в тех случаях, когда во время выполнения программы объект должен менять свое поведение в зависимости от своего состояния.
- Strategy (Стратегия) - предназначен для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путем определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют.
- Template Method (Шаблонный метод) - определяет основу алгоритма и позволяет наследникам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом.
- Visitor (Посетитель) - описывает операцию, которая должна быть выполнена над каждым объектом из некоторой произвольной структуры.

Подробно о каждом шаблоне с примерами UML диаграммами и тестами, можно прочитать здесь:
https://nixsolutions.github.io/design-patterns/
http://designpatternsphp.readthedocs.io/ru/latest/
https://github.com/kamranahmedse/design-patterns-for-humans

9. Коротко ООП PHP - Создание комментариев documentor


Считаеться что писать комментарии в коде, это плохо. Код должен быть понятен сам по себе. А единственные комментарии которые должны присутвовать это документирование с помощью докблоков ( всегда начинаеться с /** )
/**
 * It is
 * a PHP docblock
 */

Стандарт PHPDoc взят с языка Java. Важной составляющей докблоков являются теги и аннотации.
В PHP с помощью докблоков можно документировать такие элементы:
- функции;
- константы;
- классы;
- интерфейсы;
- трейты;
- константы классов;
- свойства;
- методы.
/**
 * Rabbit Class
 *
 * @version 0.1.0
 */
class Rabbit implements RabbitInterface
{
    const STATUS_RUNNING = 'running';
 
    /**
     * @var string $status Status
     */
    private $status;
 
    /**
     * Set `running` status for the rabbit
     *
     * @return $this
     */
    public function run()
    {
        $this->status = self::STATUS_RUNNING;
 
        return $this;
    }
}

@api (метод) — обозначает стабильные публичные методы, которые не будут менять свою семантику до следующего мажорного релиза.
@author (в любом месте) — указывает имя и имейл автора, который написал следующий код.
@copyright (в любом месте) — используется, чтоб поставить свой копирайт в коде.
@deprecated (в любом месте) — полезный тег, символизирует, что данный элемент исчезнет в будущих версиях. Обычно рядом пишут, какой код следует использовать взамен. Также большинство IDE подсвечивают использование устаревших методов отдельным стилем. Когда нужно подчистить устаревший код для нового релиза, то легко искать по этому тегу.
@example (в любом месте) — используется для размещения ссылки на файл или веб-страницу, где показан пример использования кода. На данный момент phpDocumentor заявляет о неполной поддержки возможностей этого тега.
@filesource (файл) — этот тег можно размещать только на самом начале php-файла, так как тег применим только к файлу и включит весь код файла в сгенерированную документацию.
@global (переменная) — на данный момент этот тег не поддерживается, возможно, будет реализован в следующих версиях, когда он будет переосмыслен.
@ignore (в любом месте) — докблок, где указан этот тег, не будет обрабатываться во время генерации документации, даже если в нем есть другие теги.
@internal (в любом месте) — чаще всего используется вместе с тегом @api, чтоб показать, что код предназначен для внутренней логики этой части программы. Элемент, обозначенный этим тегом, не будет включен в документацию.
@license (файл, класс) — что же он еще может делать, если не указывать тип лицензии для написанного кода.
@link (в любом месте) — используется для вставки ссылок, но, как пишет документация, полностью функциональность тега пока не поддерживается.
@method (класс) — применяется к классу и служит для описания магических методов, которые обрабатываются магической функцией __call().
@package (файл, класс) — разбиение кода на логические подгруппы. Когда вы помещаете классы в один namespace, вы тем самым показывает их функциональную схожесть. Если классы лежат в разных неймспейсах, но имеют одинаковый логический признак, их можно сгруппировать с помощью этого тега, например, если у вас классы работающие с корзиной заказа разбросаны по разным местам. Но лучше отказаться от такой практики, по код стайлу Symfony, например, этот тег не должен использоваться.
@param (метод, функция) — предназначен для описания входящих параметров функции. Важно также отметить, что если вы уже взялись описывать входящие параметры для конкретной функции через докблоки, то нужно описывать все, а не только первый или второй.
@property (класс) — так же, как и @method, этот тег размещается в докблоке для класса, но описывает свойства, доступ к которым будет обрабатываться через магические методы __get() и __set().
@property-read, @property-write (класс) — аналогично предыдущему тегу, но обрабатывают только один магический метод, __get() или __set() соответственно.
@return (метод, функция) — предназначен для описания значения, которое возвращает функция. Можно указать его тип, и PhpStorm подхватит его и будет выдавать подсказки, но об этом чуть позже.
@see (в любом месте) — с помощь этого тега можно вставлять ссылки на внешние ресурсы, как и с помощью @link, но также вставлять относительные ссылки на классы и методы.
@since (в любом месте) — можно указать версию, в которой появился кусок кода.
@source (в любом месте, кроме начала файла) — с помощью этого тега можно помещать в документацию участки исходного кода (задается строка начала и конца).
@throws (метод, функция) — используется для указания исключений, которые могут быть вызваны в данной функции.
@todo (в любом месте) — самый оптимистически тег, используется программистами, чтоб напомнить себе доделать что-то, когда-то в каком-то участке кода. IDE умеют распознавать этот тег и группируют все участки кода в отдельном окне, удобно для будущего поиска. Это общепринятый стандарт и используется очень часто.
@uses (в любом месте) — предназначен для отображения связи между разными участками кода. Он чем-то похож на @see, но разница в том, что @see создает однонаправленную ссылку, т.е. после перехода на новую страницу документации у вас не будет ссылки назад, а @uses в процессе его обработки ставит обратную ссылку, т.е. ссылку для обратной навигации.
@var (переменная) — используется для указания типа и описания переменных, как тех, что встречаются внутри функций, так и свойств класса. Следует учесть разницу между этим тегом и тегом @param. Тег @param используется только в докблоках для функций и описывает входящие параметры, а @var используется для документирования обычных переменных.
@version (в любом месте) — обозначает текущую версию программы, в которой появился данный класс, метод и т.д.

8. Коротко ООП PHP - Пространства имен (namespace use)


Пространства имен PHP предоставляют возможность группировать логически связанные классы, интерфейсы, функции и константы.
В PHP пространства имен используются для решения двух проблем, с которыми сталкиваются авторы библиотек и приложений при создании повторно используемых элементов кода, таких как классы и функции:
1. Конфликт имен между вашим кодом и внутренними классами/функциями/константами PHP или сторонними.
2. Возможность создавать псевдонимы (или сокращения) для Ну_Очень_Длинных_Имен, чтобы облегчить первую проблему и улучшить читаемость исходного кода.
Вот статья которая доступным языком объясняет простраства имен, зачем, как и почему https://habrahabr.ru/post/212773/

7. Коротко ООП PHP - Автозагрузка (autoload). Что такое PSR


PSR (Proposing a Standards Recommendation - Предлагаемые рекомендации стандартов). Группа разработчиков путем голосования создают стандарты для php.
Данные стандарты абсолютно независимы друг от друга и разработчик сам может выбирать следовать им или нет.
http://www.php-fig.org/psr/ здесь список на мемент написания статьи, PSR-0 устаревший, с 1,2,3,4,6,7 стандарты приняты, и 5,8,9,10,11 в черновиках еще.
PSR-0: устаревший смотреть PSR-4.
PSR-1: Основные стандарты кодирования
Секция описывает общие правила оформления кода:
- Использование только тэгов <?php и <?=
- Только UTF-8 без BOM для пхп кода
- Не стоит мешать разный функционал в одном файле
- NS и классы должны следовать psr-0
- классы объявляются в `StudlyCase`
- методы объявляются в lower `camelCase`
- константы объявляются в ТАКОМ_ВИДЕ
PSR-2: Стандарты оформления кода
Собственно представляет собой требования к оформлению кода:
- код должен пользовать 4 пробела вместо ТАБ для отделения кода
- длина строки не более 80 символов, ну 120 в крайнем случае
- пустая строка после объявления NS и USE блока
- открывающая скобка `{` объявления класса и методов должна находится на следующей строке, а закрывающая `}` на следующей строке после кода
- для всех свойств и методов обязательно указывать видимость;
ключевые слова `abstract` и `final` указываются до объявления видимости, а `static` после
- После управляющих ключевых слов (команд языка) должен ставиться пробел, не ставится после вызова методов и функций
- Открывающие скобки `{` для команд ставятся на одной строке с ключевым словом, а закрывающая `}` на следующей строке после кода
- Скобки команд `()` не должны начинаться и заканчиваться пробелами
Остальные стандарты можете посмотреть на http://www.php-fig.org/psr/
Пример автозагрузчиков на основе PSR-4 https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-4-autoloader-examples.md

6. Коротко ООП PHP - Исключения (throw catch exception)


Исключения это условия вызывающееся обычно когда ошибка. Они показывают на то, что в процессе выполнения скрипта пошло что-то не так, при этом выполнение скрипта не обязательно останавливается.
<?php

// функция 1 делим на число
function inverse($x) {
	// делить на ноль нельзя
    if ( !$x ) {
        throw new Exception('Деление на ноль.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Выброшено исключение: ',  $e->getMessage(), "\n";
}

// Продолжение выполнения
echo "Hello World\n";
В php 7 появился новый класс Throwable, который является родительским интерфейсом для всех объектов, выбрасывающихся с помощью выражения throw, включая классы Error и Exception.

5. Коротко ООП PHP - Абстрактные классы (abstract) и интерфейсы объектов (interface), их отличие


Методы, объявленные абстрактными, несут, по существу, лишь описательный смысл и не могут включать реализации. При наследовании от абстрактного класса, все методы, помеченные абстрактными в родительском классе, должны быть определены в классе-потомке; кроме того, область видимости этих методов должна совпадать (или быть менее строгой).
Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости описывания их функционала. Тела методов интерфейсов должны быть пустыми.
Интерфейс - это абстрактный класс, у которого все методы не реализованы, все публичные и нет переменных класса.
Абстрактный класс - это как ЗАГОТОВКА.
Интерфейс - это как КОНТРАКТ, что обязан выполнять класс.
А теперь в чем же отличие:
- Интерфейсы, в отличии от абстрактных классов, поддерживают множественное наследование. Т.е. класс-потомок может реализовывать 2 или более интерфейсов одновременно: class A implements Int1, Int2, но class A extends AbstrB
- Интерфейс содержит исключительно объявления методов, но не содержит реализации.
- Интерфейс не может включать в себя свойства
- Класс-потомок обязан реализовывать все методы интерфейса
- В интерфейсе все методы открытые
abstract
<?php

abstract class Car {
	public $x;
	public $y;

    public function __construct($x, $y) {
      $this->x = $x;
      $this->y = $y;
    }
	
	abstract public function move ($x, $y);

}

class BMW extends Car {
	
    public function move($x, $y) {
		echo "Движение BMW из координат ($this->x, $this->y) в координаты ($x, $y)<br />";
		$this->x = $x;
		$this->y = $y;
    }
	
}

$auto = new BMW(10, 20);
echo $auto->x;
echo "<br />";
echo $auto->y;
echo "<br />";
$auto->move(5, 15);
interface
<?php

interface Parsed {
	public function Parsed($blah);
}

interface DotSyntax {
	public function UsesDotSyntax();
}

interface Compiled {
	public function isCompiled();
}



class Java implements DotSyntax, Compiled {
	public function __construct() {
		echo 'Java was created<br/>';
		$this->UsesDotSyntax();
		$this->isCompiled();
	}

	public function UsesDotSyntax() {
		echo 'Yes, UsesDotSyntax<br/>';
	}

	public function isCompiled() {
		echo 'Yes, isCompiled<br/>';
	}
}

class PHP implements Parsed {
	public function __construct() {
		echo 'PHP was created<br/>';
		$this->Parsed('Yes, Parsed<br/>');
	}
	public function Parsed($blah) {
		echo $blah;
	}
}

$php = new PHP();
$java = new Java();
«»
Вверх