Clases de utilidad en MVC - ASP.NET

15

Así que me preguntaba hoy, ¿dónde pondrían las clases de utilidad en una aplicación ASP.NET MVC? Por clases de utilidad me refiero a clases que pueden ser estáticas y solo se usan para realizar una función. Al igual que una clase para enviar un correo electrónico que toma la dirección de correo electrónico, el asunto y el cuerpo como argumentos.
Supongo que tal vez crear una carpeta y un espacio de nombres separados sería lo suficientemente bueno, pero quería obtener la opinión de todos

usuario60812
fuente
3
¿Por qué crear clases de utilidad en cualquier tipo de proyecto? ¿Por qué MVC se destaca en su pregunta?
Finalizado el
1
Bueno, me preguntaba acerca de MVC porque de alguna manera fuerza la estructura. Y en cuanto a la utilidad, tenía la impresión de que todos los usaban :) Si tengo un código de remitente de correo electrónico, y lo divido en una clase separada para trabajar con varias partes del sistema, ¿no es eso una clase de utilidad o estoy? ¿Me confundí? Pensé clases de utilidad una vez fueron reutilizable en cualquier programa que no están vinculados en el código
user60812
Personalmente, consideraría enviar un servicio por correo electrónico, resumido por decir la interfaz IUserNotificationSender más o menos ... con un manejo adecuado de errores, configuración de smtp, etc. que realmente no cabe en una función de utilidad ...
Max
@Max, entonces, ¿qué se consideraría una función de utilidad? Estoy tratando de entender, ya que me parece que estoy muy confundido
user60812
Bueno, en mi opinión, una función de utilidad adecuada es una función muy pequeña con un alcance muy definido y sin dependencias externas ... como una función para eliminar espacios en blanco, recortar una cadena u obtener el enésimo elemento de una colección ...
Max

Respuestas:

11

Usted no Y su propio ejemplo es perfecto para mostrar por qué no.

¿Quieres enviar correos electrónicos, verdad? Entonces creas en algún lugar una clase estática CommunicationUtilitiescon una estática SendEmail(). Utiliza este método de alguna clase que hace un montón de cosas, por ejemplo, restablece la contraseña de un usuario y le envía una nueva por correo electrónico. Perfecto.

Ahora, ¿qué pasa si quieres probar tu clase en una unidad? No puede, porque cada vez que desea probar el método que restablece la contraseña, cambia la base de datos (que no es adecuada para una prueba unitaria) y, además, envía un correo electrónico (que es aún peor).

Es posible que haya leído sobre Inversión de control, que tiene la ventaja de facilitar las pruebas unitarias. Los artículos sobre IoC le explicarán que en lugar de hacer algo como:

void ResetPassword(UserIdentifier userId)
{
    ...
    new MailSender().SendPasswordReset(userMail, newPassword);
}

tú lo haces:

void ResetPassword(IMailSender sender, UserIdentifier userId)
{
    ...
    sender.SendPasswordReset(userMail, newPassword);
}

que permite usar simulacros y trozos.

Intenta aplicar IoC a tu CommunicationUtilities. Bien, no puedes. Por eso está roto.

Arseni Mourzenko
fuente
Hola MainMa, así que si entiendo correctamente, es apropiado hacer una clase de fondo de voz con todas las tuberías, y luego abstraerla con una interfaz y pasar la interfaz a la función en lugar de llamar directamente desde la clase como en su primer fragmento.
user60812
1
@ user60812: en resumen, lea sobre IoC. Sería difícil explicar todo el tema en un simple comentario.
Arseni Mourzenko
1
¿Qué pasa con una función de utilidad verdaderamente genérica, como un truncador de cadena?
jbyrd
2
@MainMa - lo siento, no te sigo. Eso es lo que quiero, sí. Pero Truncate () no está integrado en c #, por lo que me preguntaba si tendría sentido incluir ese tipo de función de utilidad genérica en algún tipo de clase de utilidades.
jbyrd
2
Esta respuesta define el problema al señalar que en este caso particular no es necesaria ninguna clase de utilidad. Pero, en general, siempre hay algunos métodos de estilo "auxiliar" que no caben en ningún lado.
usr
9

La pregunta es válida, incluso si el ejemplo dado no lo es. La respuesta dada por Maina es perfecta, en un contexto muy específico, que no es para mí, el contexto adecuado para dichas clases de "utilidad" .

Personalmente, creo una carpeta Helpersen la que pongo funciones simples para llamar desde casi cualquier lugar, como extensiones, en cuyo caso, sí, son estáticas.

Ahora, si hay una mejor manera, estaré encantado de aprender, pero hasta ahora:

  • No veo nada malo con las extensiones.
  • No veo nada de malo en agruparlos en una carpeta específica.

Ahora, una extensión es solo azúcar sintáctico, también podría ser una función clásica.

BernardG
fuente
6

Ninguna de las respuestas dadas anteriormente aborda la pregunta real. user60812 simplemente preguntó dónde colocaría una clase de utilidad dentro de un proyecto MVC. Todos escucharon el ejemplo singular y se quejaron de todo, excepto la pregunta en cuestión.

@ user60812, dependiendo del nivel de abstracción que desee, yo haría:

  • A) Cree una carpeta y cree la clase de utilidad dentro de esa carpeta
  • B) Cree un proyecto para contener las clases de utilidad (suponiendo el deseo de reutilización del ensamblaje).
  • C) Extrapolar sus utilidades en una arquitectura de servicio y llamarlas

Aquí hay un enlace a una pregunta similar con mejores respuestas.

En mi humilde opinión

Spencer Sullivan
fuente
1

No cree clases estáticas para utilidades. La estática es mala en la mayoría de los casos. No los llames gerentes tampoco. Independientemente de lo que esté trabajando, debe colocarse en un espacio de nombres lógico.

Por ejemplo:

namespace Application.Notifications.Email
{
   public interface ISendEmailCommand
   {
      void Execute(Email email);
   }
}

La dirección de correo electrónico, el asunto y el cuerpo son una preocupación separada, por lo tanto, tendría una estructura de clase para eso, de ahí por qué lo he usado Email emailen el ejemplo anterior.

CodeART
fuente
Por favor explique por qué las clases estáticas son malas para contener métodos de utilidad Tengo una curiosidad genuina sobre tu razonamiento.
Spencer Sullivan