agorlov.github.io

My homepage

View My GitHub Profile

Декларативный PHP (он же Объектный PHP)

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

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

На текущий момент не существует языков “тех.заданий”, когда машина будет понимать, что нужно сделать прочитав ТЗ. Декларативный подход - это переходная парадигма от машинных языков к естественным.

Основные принципы

Преимущества

Недостатки

Пример набора объектов

Набор объектов представляющих Пользователя в программе. Все они реализуют интерфейс User.

Интерфейс:

/**
 * Пользователь.
 */
interface User
{
    /**
     * Информация о пользователе
     *
     * @return array
     */
    public function info(): array;
}

Базовая реализация:

/**
 * Пользователь по user.id
 */
class UserStd implements User
{
    private $db;
    private $userId;

    public function __construct($userId, $db = null)
    {
        $this->userId = $userId;
        $this->db = null === $db ? getDB() : $db;
    }


    /**
     * Информация пользователя
     *
     * @return array $info
     */
    public function info(): array
    {
        $info = $this->db->query(
            "SELECT * FROM users WHERE id=" . $this->db->quote($this->userId)
        )->fetch();

        if ($info === false) {
            throw new \Exception("Не существует пользователя с id = " . $this->userId);
        }

        return $info;
    }
}

Группирующая оболочка:

/**
 * Пользователь - обертка
 */
class UserWrap implements User
{
    private $orig;

    /**
     * Конструктор.
     *
     * @param User|callable
     */
    public function __construct(User $orig)
    {
        if (is_callable($orig)) {
            $this->orig = $orig;
        } else {
            $this->orig = function () use ($orig) {
                return $orig;
            };
        }
    }

    /**
     * Информация о пользователе
     *
     * @return array
     */
    public function info(): array
    {
        return $this->orig->call($this)->info();
    }
}

Пользователь по логину (в Java это было бы реализовано вторым конструктором):

/**
 * Пользователь по Login-у
 */
class UserByLogin extends UserWrap
{
    /**
     * Конструктор.
     *
     * @param string $login логин пользователя
     * @param PDO $db база
     */
    public function __construct(string $login, $db = null)
    {
        parent::__construct(function () use ($login, $db) {
            $db = $db ?? getDB();

            $userId = $db->query(
                "SELECT id FROM users WHERE login=" . $db->quote($login)
            )->fetchColumn();

            if ($userId === false) {
                throw new \Exception("Не существует пользователя с login = " . $login);
            }

            return new UserStd($userId, $db);
        });
    }
}

Патерны

Декоратор

Наращивает или видоимзеняет возможности базового объекта.

Оболочка (Envelope)

Содединяет несколько объектов в группу.

Отложенная загрузка (Lazy Loading)

Позволяет избавиться от исполняемого кода в конструкторах

Smart-объекты

Дополняют функционал объекта.

Overloading

В Java есть возможность объявлять множество конструкторов. В PHP придется на каждый конструктор создавать новый объект.

Что такое хорошо и что такое плохо?

С точки зрения описываемого подхода:

Плохо: null, static, extends, trait, singleton, new вне конструктора

Хорошо: interface, immutable, final, class

Источники