Si tiene una lógica que debe compartirse entre dos controladores, ¿dónde la guarda?

10

Tengo un conjunto de funciones de propósito único que necesito en dos controladores separados. En este momento solo tengo un código duplicado y quiero deshacerme de él. Este código es parte del controlador y no pertenece a mi capa de servicio. ¿Dónde lo pondrías?

Irlanda
fuente
CakePHP los llama Componentes: book.cakephp.org/2.0/en/controllers/components.html tal vez sea algo de inspiración.
Luc Franken

Respuestas:

12

No dijiste qué tipo de lógica es la que estás compartiendo. En resumen, ¿es esta lógica del controlador o una función auxiliar? Los dos métodos para tratar esto en un lenguaje orientado a objetos son la herencia y la composición. La herencia tiene sentido si hay una acción compartida entre los dos controladores. La composición tiene sentido el resto del tiempo. El ejemplo del uso de la herencia se encuentra en mi respuesta original debajo del divisor.

No es raro tener una clase de utilidad o una clase auxiliar según su marco. Por ejemplo, en los marcos web Java y C # puede que tenga un paquete / espacio de nombres para utilidades. En Ruby on Rails, puede estar aprovechando la Helperclase que comparte lógica entre controladores y vistas. Básicamente, se vería así:

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

Alternativamente, puede convertirlo en una clase que instancia. La clave del patrón de clase estática anterior es hacer que sus funciones sean funciones puras. En otras palabras, pasa cualquier estado que necesite para hacer su trabajo, y la función no hace referencia a ningún otro estado estático en el sistema.

En cualquier caso, accedería a cada uno de sus controladores de la siguiente manera:

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

Respuesta original

No dijiste cuál era tu plataforma, ya que eso puede afectar la respuesta. Suponiendo que es un lenguaje orientado a objetos, el enfoque más común es crear una clase base que extiendan ambos controladores. Por ejemplo, en Ruby on Rails podría tener:

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

class Controller1 < BaseController
    # ...
end

class Controller2 < BaseController
    # ...
end

También puedes traducir la idea a otros idiomas. El mismo enfoque funcionará para ASP.NET MVC, Apache Wicket, Grails o cualquier otro marco web orientado a objetos. Si su lenguaje no está orientado a objetos, entonces realmente depende de cómo esté diseñado el marco para el mejor enfoque.

Berin Loritsch
fuente
3
La alternativa es encapsular la lógica en una clase separada, luego instanciar esa clase y llamar a la lógica desde ambos controladores.
Kramii
55
Sí siempre a favor de la composición sobre la herencia
Reno
1
Haga la sugerencia de Kramii en lugar de agregar una capa adicional de herencia. Pero creo que su pregunta real era en qué parte de la solución se dirige esa clase.
Nadie
1
Depende de cuál sea la función y el marco. En rieles, podría pertenecer a la clase Helper. En ASP.NET o Java, es posible que tenga una clase de utilidad para ese tipo de función. Realmente depende de qué tan cerca del controlador necesite vivir.
Berin Loritsch
Es la lógica del controlador. Simplemente lo necesito en dos lugares. Lo que tengo ahora es una clase de extensión que uso para poner la lógica en una ubicación.
Erin