WEB-Программист
Переключить навигацию

Язык

  • Русский
  • Русский
Связаться с нами

Поиск

  • Книги
  • JavaScript
  • HTML и CSS
  • Другие
  • SEO
  • wordpress
  • Дизайн
  • Laravel
  • Phyton
  • React js
  • Android
  • SQL и языки запросов
  • Yii
  • Шрифты
  • Статьи
  • Laravel
  • wordpress
  • Темы Wordpress
  • Интернет магазин
  • JavaScript
  • © 2015-2026 Andrii Beznosko

  • Hosting CityHost

Преимущества использования Репозиториев в Laravel

  • Описания
  • Описание/Скачать

Что такое репозитории?

Если вы читали мои предыдущие посты, то вы, наверное, уже знаете, что из себя представляют репозитории.

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

Я считаю, что есть 4 базовых преимущества в использовании паттерна Репозиторий в приложении.

1. Хранилище данных как деталь приложения

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

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

База данных — это деталь вашего приложения. Вы должны проектировать ваше приложение, обходя знания о том, как будете хранить ваши данные.

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

Например, у вас может быть следующий интерфейс UserRepository:

interface UserRepository {
    public function findUserById($id);

    public function findUserByUsername($username);

    public function add(User $user);

    public function remove($id);
}

 

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

class InMemoryUserRepository implements UserRepository {

    /** @var */
    private $users;

    public function findUserById($id)
    {
        return $this->users[$id];
    }

    public function findUserByUsername($username)
    {
        return array_filter($this->users, 
        function (User $user) use ($username) {
            return $user->username === $username;
        });
    }

    public function add(User $user)
    {
        $this->users[$user->id] = $user;
    }

    public function remove($id)
    {
        unset($this->users[$id]);
    }
}

 

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

2. Намного проще тестировать

Ещё одно отличное преимущество, связанное с первым — использование паттерна Репозиторий делает тестирование вашего кода куда проще.

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

Например, вы, наверное, не захотите писать следующий код в вашем приложении:

    public function find($id)
    {
        $repository = new EloquentUserRepository;

        return $repository->findUserById($id);
    }

 

При создании нового экземпляра EloquentUserRepository прямо в методе вы привязываете эту зависимость к вашему коду.

Вместо этого вы можете внедрить объект, который удовлетворяет требованиям интерфейса:

  public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }

    public function find($id)
    {
        return $this->repository->findUserById($id);
    }

 

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

 public function test_find_user()
    {
        $repository = new InMemoryUserRepository;
        $controller = new UserController($repository);

        $user = $controller->findUserById(1);

        $this->assertInstanceOf('User', $user);
    }

 

3. Односторонняя зависимость

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

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

Дальше у нас есть слой HTTP, который принимает пользовательские данные и направляет их туда, куда они должны попасть.

Затем в приложении идёт слой, который координирует и определяет, какой сервис нам нужен для удовлетворения запроса страницы.

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

И, наконец, в самом низу у нас есть база данных.

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

Каждый слой также фактически никак не зависит от слоя ниже. Пользовательский интерфейс не заботится о том, написано ли приложение на PHP, Ruby или Java. Так же, как и слой HTTP может посылать и принимать запросы, это всё что для него имеет важность.

Слой HTTP не знает ничего о том, как слой Приложения будет удовлетворять его запрос. Он заботится только об отправке соответствующего ответа.

Приложение не заботится о том, как слой Домена в соответствии с бизнес-правилами решает, что правильно, а что — нет, слой Приложения не знает понятия «бизнес-правила».

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

Как вы можете увидеть, каждый слой ничего не знает о слое ниже.

Использование паттерна Репозиторий позволяет нам создавать одностороннюю зависимость между доменом и слоями хранения данных.

4. Иллюзия хранилища в памяти

Если мы посмотрим на определение Репозитория из книги «Patterns of Enterprise Application Architecture», то увидим следующую цитату:

Посредничество между доменом и хранилищем данных осуществляется посредством интерфейса-коллекции для доступа к объектам домена.

Одна из самых важных характеристик паттерна Репозиторий — это тот факт, что он предоставляет интерфейс коллекции.

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

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

Но мы должны мыслить о данных, как если бы они хранились в коллекциях, а не позволять терминологии баз данных влезать в наше приложение.

Это значит, что, например, вместо метода save(User $user) у нас должен быть add(User $user).

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

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

Пишем первый репозиторий

Немного раньше мы ознакомились с паттерном Спецификация.

Паттерн Спецификация — это способ инкапсулирования бизнес-правил вокруг выборки объектов в нашем приложении. Для выборки этих объектов нам нужен способ обращения к базе данных.

В предыдущем руководстве мы внедрили интерфейс UserRepository в наш объект спецификации.

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

Сегодня мы посмотрим на первые пробные шаги написания интерфейса UserRepository.

Создадим файл Cribbb\Domain\Model\Identity с названием UserRepository.php:

<?php namespace Cribbb\Domain\Model\Identity;
	 
interface UserRepository {}

 

Первые два метода, которые я добавлю, будут искать пользователя по E-Mail и username. Они нужны объекту спецификации:

   /**
     * Find a user by their email address
     *
     * @param Email $email
     * @return User
     */
    public function userOfEmail(Email $email);

    /**
     * Find a user by their username
     *
     * @param Username $username
     * @return User
     */
    public function userOfUsername(Username $username);

 

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

Как указано выше, я должен думать о Репозитории, как если бы была коллекция в памяти, а не база данных:

    /**
     * Add a new User
     *
     * @param User $user
     * @return void
     */
    public function add(User $user);

 

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

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

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

  /**
     * Return the next identity
     *
     * @return UserId
     */
    public function nextIdentity();

 

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

UserRepository — это часть бизнес-логики приложения. Тем не менее, реальная реализация этого Репозитория относится к инфраструктуре.

Поэтому, когда я пишу реализацию UserRepository, я помещу её под пространством имён внутри инфраструктуры:

<?php namespace Cribbb\Infrastructure\Repositories;

use Doctrine\ORM\EntityRepository;
use Cribbb\Domain\Model\Identity\UserRepository;

class UserDoctrineORMRepository extends EntityRepository implements UserRepository {}

 

Заключение

Репозитории важны не только на техническом уровне, но и на уровне концептуального размышления о различных слоях приложения.

Использование Репозиториев в нашем приложении имеет множество преимуществ.

Во-первых, они предотвращают вас от попадания в болото технических деталей инфраструктуры проекта.

Во-вторых, они делают проще тестирование различных компонентов, взаимодействующих с вашей базой данных.

В-третьих, они предоставляют одностороннюю зависимость между слоями, предотвращая их размытость.

И наконец, они предоставляют иллюзию коллекции в памяти, так что терминология постоянных хранилищ не вкрадывается в язык нашего приложения.

Для меня работа с репозиториями делает аспект взаимодействия с хранилищем в приложении намного проще.

Комментарии
Всего комментариев: 0
Оставить комментарий Отменить ответ

Ваш email не будет опубликован.

Жанр: Главная » Статьи » Laravel » Преимущества использования Репозиториев в Laravel
Статус: Для продвинутых программистов
Ссылка на оригинал статьи (Если указана или эта статья не авторская) Скачать
На сайт предоставил Сен 18, 2015 14:44 Andriy

Статьи опубликованные на сайте WEB-Программист указаны со ссылками на источник. Администрация сайта не несет ответственность за их использование Вами

Laravel
Previous Next

Смотри также:

Отладка запросов в Laravel

Laravel предоставляет отличный конструктор запросов и ORM — Eloquent. Это позволяет писать запросы невероятно простым и понятным способом. Тем не менее, бывают случаи, когда вам нужно создать сложный запрос и увидеть, какой SQL в действительности сгенерируется. В этом руководстве мы...

Создание пакетов для Laravel

Prosper Otemuyiwa недавно написал статью о том, как создавать пакеты для Laravel 5 в своём блоге. Хотя его способ абсолютно правильный и может вам подходить, я предпочитаю немного иной способ создания пакетов. Сначала я создаю новый репозиторий на GitHub. В...

Интеграционное тестирование в Laravel 5.1: Фабрики моделей

При тестировании кода часто приходится создавать тестовые записи одной или нескольких моделей. Вы могли использовать нечто такое: $post = new Post; $post->title = 'Fake Blog Post Title'; $post->body = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lorem erat,...

Магия Laravel: динамические where

Laravel предоставляет нам возможность получать данные из базы вызывая методы классаIlluminate\Database\Query\Builder на наших моделях. Сегодня речь пойдёт об одном из таких методов, а именно о динамическом where. Благодаря нему мы можем выбирать данные, фильтруя их по различным атрибутам нашей модели....

Работа с nullable полями в Eloquent в Laravel

Вступление Если у вас есть несколько моделей в Laravel с одним nullable полем, создание мутатора для этого поля — процесс достаточно тривиальный: public function setNicknameAttribute($nickname) { $this->attributes['nickname'] = trim($nickname) == '' ? null : trim($nickname); }   Здесь мы проверяем...

Связаться с нами

- Премиум темы и плагины WP Star бесплатно -

We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Cookie settingsACCEPT
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT