Ich habe die letzten Stunden damit verbracht, mich über die Verwendung von static
Klassen zu informieren und herauszufinden, ob ich sie verwenden sollte oder nicht, bin aber immer noch zu keinem Ergebnis gekommen. Es scheint, dass das Argument in beide Richtungen gehen könnte. In meiner Anwendung habe ich sogenannte "Hilfsklassen" erstellt, die Methoden enthalten, die sehr häufige Aufgaben für mich erledigen und in meiner Anwendung aufgerufen werden ( ASP.Net MVC
Web App using C#
). Die einfache Frage ist, ob sie wirklich statisch sind oder nicht ?
Hier ist ein Beispiel von einem meiner Helfer.
public static class ActiveDirectoryHelper
{
public static PrincipalContext GetPrincipalContext(string ouName)
{
var fullOUName = string.Concat("OU=", ouName,",DC=");
return new PrincipalContext(ContextType.Domain, "", fullOUName, ConfigurationManager.AppSettings["ServiceAccountUser"], ConfigurationManager.AppSettings["ServiceAccountPassword"]);
}
public static PrincipalSearcher GetAllUsersInOU(string ouName)
{
var principalContext = GetPrincipalContext(ouName);
var userPrincipal = new UserPrincipal(principalContext);
return new PrincipalSearcher(userPrincipal);
}
public static UserPrincipal GetUserPrincipal(string userName, string ouName)
{
var principalContext = GetPrincipalContext(ouName);
return UserPrincipal.FindByIdentity(principalContext, userName);
}
}
c#
object-oriented-design
asp.net-mvc
Matthew Verstraete
quelle
quelle
PrincipalContext
Klasse sein und wie folgt aufgerufen werden :PrincipalContext.Get(ouName)
. Es ist im Wesentlichen eine Factory-Methode.Antworten:
Ich denke, statische Klassen sind in vielen Fällen nett. Ich könnte einfach sagen "benutze sie, wenn es nützlich ist", aber das ist nicht sehr hilfreich.
Meine Faustregel lautet (wie immer): Verstecke ich Abhängigkeiten? Wenn Sie der Meinung sind, dass eine "Helferklasse" nützlich ist (obwohl Sie auf einen geringen Zusammenhalt achten), fahren Sie auf jeden Fall fort. Stellen Sie nur sicher, dass Ihre Methoden nicht auf den globalen Status zugreifen. Reine statische Methoden sind sehr schön. Statische Methoden, die von einigen globalen Methoden abhängen oder DB-Verbindungen öffnen oder von der Festplatte / einer Konfigurationsdatei lesen, sind Zeitbomben.
Sie machen das Testen der Anwendung sehr schwierig (die einzige Möglichkeit, dies zu tun, besteht darin, das gesamte System manuell auszuführen, oder bei spröden automatischen Tests des gesamten Systems erhalten Sie keine Granularität). Sie machen es auch unmöglich, Implementierungen auszutauschen.
Denken Sie nur an das Abhängigkeitsinversionsprinzip und das Open / Closed-Prinzip! Stellen Sie sicher, dass Ihre Klassen steckbar sind. Stellen Sie sicher, dass sie nichts aus der Luft ziehen. Wenn Sie das tun, machen Sie so viele statische Methoden, wie Sie wollen!
quelle
Anscheinend verbergen Sie mit dieser statischen Klasse eine externe Abhängigkeit von Active Directory. Ein Problem hierbei ist, dass Sie keine statischen Aufrufe vortäuschen können, wenn Sie versuchen, die Klasse, die diese Methoden aufruft, einem Komponententest zu unterziehen. So verhindern Sie sofort die Testbarkeit Ihres Codes. Ich würde dies in eine Schnittstelle umgestalten, so etwas wie IProvideActiveDirectoryInformation und die konkrete Klasse ActiveDirectoryInformationProvider. Übergeben Sie dann die Schnittstelle im Konstruktor Ihres Controllers. Auf diese Weise können Sie die Betonklasse mit einem DI-Container verkabeln. Außerdem können Sie den ActiveDirectoryInformationProvider fälschen und für die Schnittstellenmethoden alles zurückgeben, was Sie möchten.
Ich würde auch versuchen, Dinge wie das PrincipalSearcher-Objekt in der Benutzeroberfläche nicht zurückzugeben. Wenn Ihre Methode GetAllUsersInOU () ist, würde ich eine Liste von Benutzern oder Benutzernamen erwarten.
quelle
Eine Klasse sollte statisch sein, wenn sie in Ihrer Anwendung nur als abstraktes Konzept vorhanden ist.
Angenommen, Sie erstellen einen Klon von Twitter. Sie können zwei Arten von Tweets, Benutzer-Tweets und Anzeigen haben. Beide haben ein gemeinsames Verhalten, sind aber unterschiedlich. Sie möchten also Polymorphismus und eine Fabrik verwenden, um das eine oder andere zu erstellen.
Diese 2 Tweets-Klassen sollten konkrete Klassen sein, da es sich um reale Einheiten handelt. Ihre Domain wird durch diese Klassen definiert.
Die Factory sollte statisch sein, da sie nur auf abstrakter Ebene vorhanden ist, um Ihre Anwendung besser zu gestalten und Ihnen zu helfen, Code wiederzuverwenden, der eine Art Tweet erstellt. Ihre Domain wird von dieser Factory auf keiner Ebene definiert.
Wenn Sie also nicht der Meinung sind, dass eine Klasse jemals instanziiert werden sollte, aber nicht erweitert werden muss, um verwendet zu werden, ist dies wahrscheinlich ein gutes Zeichen dafür, dass sie statisch sein sollte.
quelle
static A BuildA() { return new A(); }
sicher, das ist in Ordnung. Wenn Sie jedoch etwas Komplexeres benötigen, z. B. wenn A Abhängigkeiten hat, die injiziert werden müssen, oder wenn verschiedene Teile Ihres Systems unterschiedliche Factory-Instanzen benötigen (abstraktes Factory-Muster), wird dies durch eine statische Methode nicht abgeschnitten.Eines der Dinge, die in der objektorientierten Programmierung vorgeschlagen werden, ist schlecht (der Titel soll Ihre Aufmerksamkeit erregen, und der Inhalt ist umstritten, aber unterhaltsam)
*Handler
,*Manager
und*Doer
Klassen sind im Allgemeinen ein Codegeruch, der darauf hinweist, dass jemand versucht, die Objektorientierung auf eine zu erzwingen Problem, das für eine prozedurale Implementierung besser geeignet ist.In C # können Sie statische Klassen als Modul-Namespaces für Prozeduren verwenden und diese vorzugsweise als solche benennen. Ich denke, so geht das, aber nicht in Ihrem speziellen Fall.
Anwendungen Ihrer speziellen Implementierung weisen Verhaltensabhängigkeiten des globalen Status auf (z. B. die Berechtigungen eines bestimmten Benutzers) und sollten daher eine injizierte Abhängigkeit sein, damit der Code, der diese verwendet, isoliert einem Komponententest unterzogen werden kann.
quelle
Ich vermisse vielleicht etwas, aber meiner Meinung nach läuft die Antwort auf die Methoden und Mitgliedsvariablen hinaus.
Wenn diese alle statisch sind, kann (und sollte) die Klasse selbst statisch gemacht werden. Wenn nicht, ist es keine statische Klasse.
Hinweis: Es gibt nichts, was die Klasse dazu zwingt , statisch zu sein, selbst wenn die Methoden und Variablen alle statisch sind.
quelle
Betrachten Sie die Programmiersprache, die Sie verwenden (C #), als eine Reihe von Werkzeugen.
Es gibt kein Regelwerk, kein "sollte" oder "sollte nicht".
Schauen Sie sich den Job an und wählen Sie das beste Werkzeug für den Job.
Wenn Sie eine global verfügbare Sammlung von Methoden benötigen, die für alle Threads gleich ist, sind statische Klassen ein gutes Werkzeug. Wenn Sie Daten innerhalb der Klasse speichern möchten (für jeden Thread unterschiedlich), sind dies wahrscheinlich nicht der Fall.
quelle
In Ihrer Helferklasse ist nichts falsch. Ich muss zugeben, dass ich diese Art von Utils , Helfern oder Inhabern verwende , um bestimmte Ressourcen / Logik von verschiedenen Orten aus zugänglich zu machen.
Ein Architekt meiner Firma sagt mir jedoch immer wieder, dass diese Klassen häufig Code sammeln, bei dem ich nicht weiß, wo ich ihn platzieren soll. Er mag es auch nicht, weil Sie Komponenten aus Ebenen mitbringen könnten, auf die die oberen / unteren Ebenen keinen Zugriff haben sollten, und sie Aufgaben außerhalb ihrer Verantwortlichkeiten ausführen. Es bringt auch einige Probleme zur Testzeit.
Es macht mir nichts aus. Ich benutze sie und ich benutze sie so richtig, wie ich denke, dass es benutzt werden sollte. Und es funktioniert gut. Also mach dir keine Sorgen.
Es ist wahr, dass es Ihnen zum Zeitpunkt des Unit-Tests schwer fallen wird, sich darüber lustig zu machen. Aber es wird etwas länger dauern. Es gibt Bibliotheken, die dieses Problem behandeln.
Ein anderer Ansatz könnte Sie von solchen Mängeln (beim Testen) abhalten. Zum Beispiel Singleton-Muster. Injizieren der Instanz als Komponentenabhängigkeit und Umwandeln von Methoden in Instanzmethoden.
Soweit ich weiß, sehen Ihre Lösungen für mich jedenfalls gut aus.
quelle