Если у вас есть логика, которую нужно разделить между двумя контроллерами, где вы ее храните?

10

У меня есть набор одноцелевых функций, которые мне нужны в двух отдельных контроллерах. Сейчас у меня просто дублированный код, и я хочу от него избавиться. Этот код является частью контроллера и не принадлежит моему уровню обслуживания. Где бы вы это положили?

Erin
источник
CakePHP называет их Компонентами: book.cakephp.org/2.0/en/controllers/components.html возможно, это вдохновляет.
Люк Франкен

Ответы:

12

Вы не сказали, что это за логика, которой вы делитесь. Короче говоря, это логика контроллера или вспомогательная функция? Два метода решения этой проблемы в объектно-ориентированном языке - наследование и композиция. Наследование имеет смысл, если между двумя контроллерами существует совместное действие. Композиция имеет смысл в остальное время. Пример использования наследования лежит в моем первоначальном ответе под делителем.

Нередко бывает, что в зависимости от вашей среды есть вспомогательный класс или вспомогательный класс. Например, в веб-инфраструктурах Java и C # у вас может быть пакет / пространство имен для утилит. В Ruby on Rails вы можете использовать Helperкласс, который разделяет логику между контроллерами и представлениями. По сути, это будет выглядеть так:

// NOTE: group similar functions
static class LoginUtility
{
    static bool IsLoggedIn(Request request) { /* ... */ }
}

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

В любом случае вы получите доступ к нему на каждом из ваших контроллеров, как это:

void MyAction()
{
    if (LoginUtiltiy.IsLoggedIn(Request))
    {
        // Do something ...
    }
}

Оригинальный ответ

Вы не сказали, какая у вас платформа, так как это может повлиять на ответ. Предполагая, что это объектно-ориентированный язык, наиболее распространенный подход заключается в создании базового класса, который расширяют оба контроллера. Например, в Ruby on Rails вы можете иметь:

class BaseController < ApplicationController
    def my_special_function
        # ...
    end
end

class Controller1 < BaseController
    # ...
end

class Controller2 < BaseController
    # ...
end

Вы также можете перевести эту идею на другие языки. Тот же подход будет работать для ASP.NET MVC, Apache Wicket, Grails или для любой другой объектно-ориентированной веб-среды. Если ваш язык не является объектно-ориентированным, то это действительно зависит от того, как спроектирована структура для наилучшего подхода.

Берин Лорич
источник
3
Альтернатива состоит в том, чтобы заключить логику в отдельный класс, затем создать экземпляр этого класса и вызвать логику из обоих контроллеров.
Крамий
5
Да, я всегда предпочитаю композицию, а не наследство
Рено,
1
Сделайте предложение Крамия, а не добавьте дополнительный уровень наследования. Но я думаю, что его реальный вопрос был в том, где в решении идет этот класс.
Никто не
1
Это зависит от того, какие функции и рамки. В рельсах он может принадлежать к классу Хелпер. В ASP.NET или Java у вас может быть служебный класс для функций такого типа. Это действительно зависит от того, насколько близко он должен жить.
Берин Лорич
Это логика контроллера. Мне просто нужно это в двух местах. Теперь у меня есть класс расширения, который я использую, чтобы разместить логику в одном месте.
Эрин