Laden...

Wo genau Extension Methods einsetzen, wo besser eigene Klassen?

Erstellt von sth_Weird vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.310 Views
S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 13 Jahren
Wo genau Extension Methods einsetzen, wo besser eigene Klassen?

hallo,

Ich habe endlich mal die Zeit mich etwas ausführlicher mit Extension Methods zu beschäftigen. Was man alles schönes damit machen kann fällt einem gleich auf, die Frage ist aber, was ist designtechnisch (noch) schön und sauber, und was eher quick&dirty?
Beispiel: Ich habe eine Datenklasse, die prinzipiell nichts weiter tut als Daten aus einer Datenbank, XML-Datei oder sonstiges zu kapseln.
Nun möchte ich in der Lage sein, zwei Objekte zu vergleichen, oder eine Liste der Objekte nach bestimmten Kriteren zu filtern (d.h. ich müsste in der Lage sein zu prüfen, ob ein Objekt bzw. bestimmte Properties davon bestimmten Kriterien genügt). Oder, um mal von der reinen Datenebene wegzugehen, ich möchte gerne einige der Daten in ein Bitmap oder so zeichnen oder auf der Konsole ausgeben.
Dass hier Extension Methods ganz einfach zum Ziel führen würden, liegt auf der Hand. Aber ist das auch noch sauberer Stil? Oder sollte man da lieber eine eigene Klasse dafür erstellen?
Sprich: Wofür genau sollte man Extension Methods einsetzen und wofür besser nicht/wo wären sie schlechtes Design (Beispiele?)?

gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo sth_Weird,

Wofür genau sollte man Extension Methods einsetzen und wofür besser nicht/wo wären sie schlechtes Design (Beispiele?)?

wenn du die Klasse(n) selber schreibst, brauchst du (normalerweise) keine Extensionsmethods. Pack einfach die Methoden direkt in die jeweilige Klasse. Extensionmethods braucht man, wenn man Klassen erweitern will, die man nicht selbst geschrieben hat. Außerdem kann man Extensionmethods verwenden, um Interfaces mit (Standard-)Implementierungen auszustatten.

... ich möchte gerne einige der Daten in ein Bitmap oder so zeichnen oder auf der Konsole ausgeben.

Im Sinne von SoC würde das nicht in die Datenklasse gehören.

Davon abgesehen bin ich kein Fan von (reinen) Datenklassen. Siehe 3-Schichten-Design?? [harte vs. weiche (Daten-)Objekte / OOP vs. ActiveRecods].

herbivore

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 13 Jahren

Das Beispiel mit dem Zeichnen war bewusst und provokativ gewählt, da man ja bei Filtern und Vergleichen spontan auf die Idee kommt, dass das doch in die Datenklasse direkt passt, man aber beim Zeichnen gleich an die Daten/GUI Trennung denkt.

Hmm, nach dem SRP (Single Responsibility Principle) hätte ich, wenn die Datenklassen wirklich nur Daten kapseln, dort keine weitere Intelligenz reingepackt...auch wegen der Gefahr, dass die Klasse immer mehr Funktionalität bekommt, die nur an bestimmten Stellen von außerhalb relevant ist. Da gefällt mir die Idee mit den Extension Methods, die ich z.b. in eine FilterUtils.dll packen kann, die ich nur dann in ein Projekt dazubinde, wenn ich in diesem Projekt das Filtern der Daten überhaupt unterstützen will (analog dazu dlls mit anderen Extension Methods).
Zeichnen oder GUI-Geschichten gehören so oder so nicht in die Datenklasse insofern ist das ein schlechtes Beispiel...
Aber vielleicht nehme man mal ein "Auto", das kann ein normaler User "fahren", "putzen", etc. und hat diverse Eigenschaften wie Farben, PS,...
Nun wird die Klasse aber in ner Anwendung "Werkstatt" verwendet, diese muss das Auto auch "reparieren" können (irgendwelche Fehlerzustände zurücksetzen und so), was ein "normaler" Nutzer nicht können sollte. Da könnte ich dann doch eine Extension Method dazu machen. Oder eine Lackiererei, die das Auto "lackieren" kann (d.h. die Extension Method würde alle Farb-Properties der Auto-Klasse ändern).
Ich fände hier Extension Methods super praktisch. Alternativ müsste ich ja alle Funktionen in die Datenklasse packen, was ich für das Auto-Beispiel nicht passend fände. Oder wäre das schlechtes Design?
Nuja, alternativ hätte ich im Beispiel der "Lackierei" den "klassischen" Weg, dass ich in einer Klasse eine Funktion "Lackiere (Auto a, Farbe c)" habe, die dann einfach alle Farb-Properties des Autos ändert.

Um noch weiter zu gehen, ich könnte damit z.B. eine DAL Klasse weitergeben, die nur Lesezugriffe enthält, und in einer anderen dll die Schreibzugriffe in Form von Extension Methods packen. Diese Dll würde ich nur mit weitergeben, wenn ich explizit erlauben wollte, dass ein Anwender auch schreiben kann, sonst nicht.
Klar, ich könnte hier auch zwei Klassen erstellen, oder ableiten (falls erlaubt)...nuja das will ich ja gerade wissen, ob das ein berechtigter, denkbarer Anwendungsfall wäre oder man die Extension Methods da missbrauchen würde...

Externe Klassen, die man nicht selbst schreibt, lasse ich mal außen vor, da gibt es ja quasi oft keine Alternativen (außer Vererbung, sofern nicht gesperrt)...

gruß
sth_Weird

EDIT: Rechtschreibung/Grammatik

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo sth_Weird,

ich kann mich mit deinen Überlegungen nicht recht anfreunden. Wenn SRP, dann richtig. Also extra und eigene und eigenständige Klassen für extra Concerns schaffen. Dass eine Klasse, je nachdem welche Extensions man gerade "geladen" hat, immer wieder andere Methoden hat, gefällt mir nicht.

herbivore

5.742 Beiträge seit 2007
vor 13 Jahren

Hallo sth_Weird,

ich würde auf jeden Fall mal als Faustregel vorschlagen: Extensionmethods nie länger als 3-4 Anweisungen.

Nun wird die Klasse aber in ner Anwendung "Werkstatt" verwendet, diese muss das Auto auch "reparieren" können

Das ist IMHO wirklich kein guter Anwendungsfall für Extensionmethods.
Da schafft die Extensionmethod wirklich eine neue Tätigkeit.

Wo ich sie gerne einsetze, sind so "kleine" Aufgaben, die Klassen eigentlich selber implementieren sollten. Dabei erweitern diese die Klasse nicht wirklich um "neue" Funktionalität, sondern bieten nur eine Art "Kurzschreibweise" für etwas Vorhandenes.
Beispiele, die ich selber schon verwendet habe:*MostSignifcant Byte eines short *HasAttribute<TAttribute> für Type *IsDefined für Enum

5.941 Beiträge seit 2005
vor 13 Jahren

Hallo zusammen

Ich stimme hier zu, das Extensionmethods primär als sinnvolle, projektinterne Erweiterung für Typen sind, die sonst nicht zugreifbar sind.
So eine Art Short-Cut / Syntactic Sugar.

Die Extensionmethods sollten auf jeden Fall in einem Projektbezogenen Namespace sein (Ausser es handelt sich um ein Framework).

Da muss man aufpassen, das beim Zusammenführen von Bibliotheken, oder nur schon der gemeisamen Nutzung keine Konflikte auftreten, die dann mühsam sind und teilweise auch verwirren können.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

5.742 Beiträge seit 2007
vor 13 Jahren

Da muss man aufpassen, das beim Zusammenführen von Bibliotheken, oder nur schon der gemeisamen Nutzung keine Konflikte auftreten.

Aus diesem Grund lege ich alle Extensionmethodklassen in je einen eigenen Namespace, d.h. Erweiterungen für Byte landen in z.B. "Extensions.Bytes.ByteExtensions"

1.373 Beiträge seit 2004
vor 13 Jahren

Hallo,

Ich verwende Extension Methods z.B. manchmal, um triviale Überladungen von interface-Methoden an einen zentralen Ort zu implementieren.

Beispiel:


interface IWidgetRenderContext {
  void RenderWidgetZone(string name);
}

// extension:
static class WidgetRenderContextExtensions{
  public static void RenderWidgetZone(this IWidgetRenderContext context, CommonZone zone){
    context.RenderWidgetZone(zone.ToString());
  }
}

So muss nicht jede Implementierung von IWidgetRenderContext die Überladung implementieren (DRY lässt grüssen), eine Basisklasse ist auch nicht nötig. Natürlich mache ich das nicht pauschal und nur wie gesagt bei trivialen Fällen, in denen jede Implementierung gleich aussähe. Glücklicherweise lässt sich diese Extension-Method später bei Bedarf relativ leicht refaktorisieren zu einer "echten" Methode des Interface, falls das mal nötig und/oder sinnvoll werden sollte.

Grüße,
Andre

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 13 Jahren

Joa, hab ich schon vermutet, dass man Extension Methods im "Werkstatt"-Beispiel missbrauchen würde.
So verwendet würde es eine Klasse aber quasi "plugin"-fähig machen, ohne extra Klassen zu brauchen oder ableiten etc. zu müssen. Da hätte man sich Informationen und Funktionalitäten, die man in bestimmten Projekten braucht, so richtig schön "zusammenbasteln" können.
Ist zwar unheimlich verlockend, aber dass das designtechnisch unschön ist, habe ich schon erahnt. Nuja, was schönes und was unschönes Design ist ändert sich ja hin und wieder, vielleicht wird diese Verwendungsart ja irgendwann mal noch "modern" 😉

So richtig "berechtigte Anwendungsfälle" für Extension Methods finde ich damit in meinen Projekten leider nicht (schade, dass man von dem, was die Technologie theoretisch könnte, nur einen winzigen Teil wirklich einsetzen darf, wenn man guten Stil wahren will). Das einzige was ich damit bisher habe ist eine Funktion, die mir zu einem Enum-Wert einen Text liefert (also das DescriptionAttribut, das man drüber schreiben kann, ausliest).

gruß & thx
sth_Weird

EDIT: Rechtschreibung/Grammatik (warum findet man diese Fehler immer erst wenn man schon gepostet hat und nicht schon in der Vorschau?)

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo sth_Weird,

So richtig "berechtigte Anwendungsfälle" für Extension Methods finde ich damit in meinen Projekten leider nicht

siehe Snippetsuche nach ExtensionMethods.

herbivore

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 13 Jahren

Über einige der Beispiele bin ich schon gestolpert, dass es aber schon so viele hier gibt, ist mir entgangen.

Aber um nochmal mein erstes Beispiel aufzugreifen mit dem Filtern...
Wenn ich nun eine Liste List<T> habe, wären es dann ein berechtigter Anwendungsfall für Extension Methods, dieser eine Extension Method "Filter (this IList<T> data, ...)" hinzufügen, die als Parameter eine Filter-Matrix (Eigenkreation, Kombination von Filter-Kriterien) enthält?
Oder noch allgemeiner, dass ich eine Extension Method für object schreibe, die untersuchen kann, ob ein Objekt einer Filter-Matrix entspricht?
Oder würdest du eher eine Klasse "FilterProcessor<T>" oder so schreiben mit einer Funktion IList<T> Filter (IList<T> listeZumFiltern, FilterMatrix filterKriterien) bzw. bool IsMatch(T testObject, FilterMatrix filterKriteria)???

gruß & thx
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo sth_Weird,

also eine Filter-Extension-Methode würde ich eher nicht schreiben, denn es gibt ja schon die Where<T>-Methode zum filtern von Aufzählungen. Was man noch braucht, wäre die Func<T>-Methode, die für ein einzelnes Element prüft, ob durch den Filter gelassen werden soll oder nicht. Und die käme sicher ebenfalls nicht in die List<T>-Klasse, sondern in eine eigene.

herbivore

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 13 Jahren

Wo wir dann bei diesem Thema wären (sei der Vollständigkeit halber erwähnt, falls jemand mal auf ein ähnliches Problem stößt):
Wie am besten zu verschachtelter Property anhand des "Pfades" durchhangeln

das mit der Liste über Extension Methods erweitern hatte ich in einem anderen Forum gefunden, wo es prinzipiell um ein ähnliches Thema ging:
http://www.daniweb.com/forums/thread139722.html

Wenn jemand sonst noch Kommentare oder Anregungen hat darf er gerne noch was schreiben, ansonsten würd ich mal sagen Thema soweit erledigt und danke an euch alle für eure Beiträge.

gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+