Dienstprogrammklassen in MVC - ASP.NET

14

Ich habe mich heute gefragt, wo Sie Dienstprogrammklassen in eine ASP.NET MVC-App einfügen würden. Mit Utility-Klassen meine ich Klassen, die statisch sein können und nur zum Ausführen einer Funktion verwendet werden. Wie eine Klasse zum Senden einer E-Mail, die E-Mail-Adresse, Betreff und Text als Argumente verwendet.
Ich würde annehmen, dass das Erstellen eines separaten Ordners und Namespaces vielleicht gut genug wäre, aber ich wollte alle Meinungen einholen

user60812
quelle
3
Warum sollten Sie in jedem Projekt Utility-Klassen erstellen? Warum wird MVC in Ihrer Frage herausgegriffen?
Oded
1
Nun, ich habe mich über MVC gewundert, weil es in gewisser Weise die Struktur erzwingt. Und was das Hilfsprogramm anbelangt, hatte ich den Eindruck, dass sie alle verwendet haben :) Wenn ich einen E-Mail-Absendercode habe und ihn in eine separate Klasse aufspalte, um mit verschiedenen Teilen des Systems zu arbeiten, ist das nicht eine Hilfsprogrammklasse oder? Ich verwirrt? Ich dachte, dass Utility-Klassen einmal in jedem Programm wiederverwendbar sind, das nicht an den Code gebunden ist
user60812
Ich persönlich würde in Betracht ziehen, per E-Mail einen Dienst zu senden, der beispielsweise durch die Schnittstelle IUserNotificationSender oder so abstrahiert wird. Mit der richtigen Fehlerbehandlung, der SMTP-Konfiguration usw., die nicht wirklich in eine Dienstprogrammfunktion passt ...
Max
@Max also was wäre eine Utility-Funktion? Ich versuche zu verstehen, wie es mir scheint, bin ich sehr verwirrt
user60812
Nun, eine richtige Utility-Funktion ist meines Erachtens eine sehr kleine Funktion mit einem sehr definierten Umfang und ohne externe Abhängigkeiten. Zum Beispiel eine Funktion zum Entfernen von Leerzeichen oder zum Trimmen eines Strings oder zum Abrufen des n-ten Elements einer Auflistung.
Max

Antworten:

11

Das tust du nicht. Und Ihr eigenes Beispiel ist perfekt, um zu zeigen, warum nicht.

Sie möchten E-Mails verschicken, oder? Sie erstellen also irgendwo eine statische Klasse CommunicationUtilitiesmit einer darin enthaltenen statischen SendEmail(). Sie verwenden diese Methode aus einer Klasse, die eine Reihe von Aufgaben ausführt, z. B. das Kennwort eines Benutzers zurücksetzt und ihm eine neue per E-Mail sendet. Perfekt.

Was passiert nun, wenn Sie Ihre Klasse einem Unit-Test unterziehen möchten? Dies ist nicht möglich, da jedes Mal, wenn Sie die Methode testen möchten, mit der das Kennwort zurückgesetzt wird, die Datenbank geändert wird (was nicht für einen Komponententest geeignet ist) und außerdem eine E-Mail gesendet wird (was noch schlimmer ist).

Möglicherweise haben Sie etwas über Inversion of Control gelesen, was das Testen von Einheiten erleichtert. Artikel über IoC erklären Ihnen, dass Sie nicht etwa Folgendes tun müssen:

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

Sie machen:

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

was erlaubt, Mocks und Stubs zu verwenden.

Versuchen Sie, IoC auf Ihren anzuwenden CommunicationUtilities. Richtig, das kannst du nicht. Deshalb ist es kaputt.

Arseni Mourzenko
quelle
Hallo MainMa, wenn ich das richtig verstehe, ist es angebracht, mit all den Pipes noch eine "say background" -Klasse zu erstellen und sie dann mit einer Schnittstelle zu abstrahieren und die Schnittstelle an die Funktion zu übergeben, anstatt direkt von der Klasse wie in Ihrem ersten Snippet aufzurufen.
user60812
1
@ user60812: Kurz gesagt, lesen Sie über IoC. Es wäre schwierig, das ganze Thema in einem einfachen Kommentar zu erklären.
Arseni Mourzenko
1
Was ist mit einer wirklich generischen Utility-Funktion wie einem String-Truncator?
Jbyrd
2
@MainMa - Entschuldigung, ich folge nicht. Das entspricht genau dem, was ich will, ja. Da Truncate () jedoch nicht in c # integriert ist, habe ich mich gefragt, ob es sinnvoll ist, diese Art von generischer Dienstprogrammfunktion in eine Art Dienstprogrammklasse aufzunehmen.
Jbyrd
2
Diese Antwort definiert das Problem, indem sie feststellt, dass in diesem speziellen Fall keine util-Klasse erforderlich ist. Aber im Allgemeinen gibt es immer einige "Helfer" -Stilmethoden, die nirgendwo passen.
USR
9

Die Frage ist gültig, auch wenn das angegebene Beispiel nicht zutrifft. Die Antwort von Maina ist perfekt, in einem sehr spezifischen Kontext, der für mich nicht der richtige Kontext für diese "Utility" -Klassen ist.

Persönlich erstelle ich einen Ordner, Helpersin dem ich einfache Funktionen ablege, die von überall aus aufgerufen werden können, z. B. Erweiterungen. In diesem Fall sind sie statisch.

Wenn es einen besseren Weg gibt, werde ich mich freuen zu lernen, aber soweit:

  • Ich sehe nichts falsch mit Extensions.
  • Ich sehe nichts falsch daran, sie in einem bestimmten Ordner zu gruppieren.

Nun, eine Erweiterung ist nur syntaktischer Zucker, es könnte auch eine klassische Funktion sein.

BernardG
quelle
6

Keine der zuvor gegebenen Antworten befasst sich mit der eigentlichen Frage. user60812 fragte einfach, wo man eine Utility-Klasse innerhalb eines MVC-Projekts platzieren würde. Alle hielten an dem einzigartigen Beispiel fest und schwärmten über alles außer der vorliegenden Frage.

@ user60812, abhängig von der gewünschten Abstraktionsebene würde ich:

  • A) Erstellen Sie einen Ordner und erstellen Sie die Utility-Klasse in diesem Ordner
  • B) Erstellen Sie ein Projekt, in dem die Dienstprogrammklassen gespeichert werden (vorausgesetzt, Sie möchten die Assembly erneut verwenden).
  • C) Extrapolieren Sie Ihre Dienstprogramme in eine Dienstarchitektur und rufen Sie sie an

Hier ist ein Link zu einer ähnlichen Frage mit besseren Antworten.

meiner bescheidenen Meinung nach

Spencer Sullivan
quelle
1

Erstellen Sie keine statischen Klassen für Dienstprogramme. Die Statik ist in den meisten Fällen schlecht. Nennen Sie sie auch nicht Manager. Was auch immer Sie gerade bearbeiten, es sollte in einem logischen Namespace abgelegt werden.

Beispielsweise:

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

E-Mail-Adresse, Betreff und Text sind ein separates Anliegen, daher hätte ich eine Klassenstruktur dafür, weshalb ich Email emailim obigen Beispiel verwendet habe .

CodeART
quelle
Erklären Sie bitte, warum statische Klassen schlecht für Utility-Methoden sind. Ich bin aufrichtig neugierig auf Ihre Argumentation.
Spencer Sullivan