Ich bin gerade dabei, eine ziemlich große Portion Spaghetti-Code zu refaktorieren. Kurz gesagt ist es eine große "Gott-ähnliche" Klasse, die sich in zwei verschiedene Prozesse verzweigt, abhängig von einer bestimmten Bedingung. Beide Prozesse sind langwierig und haben viel doppelten Code.Ist es eine gute Design-Option, eine Initialisierungsmethode einer Klasse innerhalb einer Fabrik zu nennen, bevor sie injiziert wird?
Meine erste Bemühung bestand also darin, diese beiden Prozesse in ihre eigenen Klassen zu extrahieren und den gemeinsamen Code in ein Elternteil zu setzen, von dem beide erben.
Es sieht ungefähr so aus:
public class ExportProcess
{
public ExportClass(IExportDataProvider dataProvider, IExporterFactory exporterFactory)
{
_dataProvider = dataProvider;
_exporterFactory = exporterFactory;
}
public void DoExport(SomeDataStructure someDataStructure)
{
_dataProvider.Load(someDataStructure.Id);
var exporter = _exporterFactory.Create(_dataProvider, someDataStructure);
exporter.Export();
}
}
Ich bin ein begeisterter Leser von Mark Seemann Blog und in this entry erklärt er, dass dieser Code eine zeitliche Kopplung Geruch hat, da es notwendig ist, um die Load-Methode auf das anrufen Datenanbieter, bevor es in einem verwendbaren Zustand ist.
auf dieser Grundlage, und da das Objekt auf die ohnehin durch die Fabrik zurück diejenigen injiziert wird, ich denke, die Fabrik zu ändern, dies zu tun:
public IExporter Create(IExportDataProvider dataProvider, SomeDataStructure someDataStructure)
{
dataProvider.Load(someDataStructure.Id);
if(dataProvider.IsNewExport)
{
return new NewExportExporter(dataProvider, someDataStructure);
}
return new UpdateExportExporter(dataProvider, someDataStructure);
}
Wegen des Namens „Data Provider“ Sie wahrscheinlich vermutet, dass die Load-Methode tatsächlich einen Datenbankzugriff durchführt.
Etwas sagt mir, dass ein Objekt, das einen Datenbankzugriff innerhalb der create Methode einer abstrakten Fabrik macht, kein gutes Design ist.
Gibt es irgendwelche Richtlinien, Best Practices oder etwas, das besagt, dass dies effektiv eine schlechte Idee ist?
Danke für Ihre Hilfe.
Offensichtlich dataProvider.Load eine Art Nebeneffekt hat, entlang der Linien von einer Instanz von etwas in eine Eigenschaft zu holen? Verwendet der Rest der Factory-Methode tatsächlich 'dataProvider' und' someDataStructure'? Wenn dies nicht der Fall ist, sollten Ihre Argumente für die Factory-Methode so umgestaltet werden, dass sie die Argumente akzeptieren, die sie wirklich benötigt. – PatrikAkerstrand
@PatrikAkerstrand: Guter Punkt Patrik. Die Objekte, die von der Factory erstellt werden, verwenden den Datenprovider in der Tat stark, da die Load-Methode einige erforderliche Eigenschaften auffüllt. Dies ist eine allererste Refactoring-Maßnahme, aber leider ist dies eine technische Schuld, die auf kurze Sicht möglicherweise nicht bezahlt wird. –
ok, beachte das dann: Wenn dataProvider.Load mehrfach aufgerufen würde, würde das irgendwelche Probleme verursachen? ** Wenn nein **: Cool, würde ich den 'Load'-Aufruf in die Factory-Methode verschieben, da dies die Clients vereinfacht (alle Aufrufe von .Load würden sich innerhalb der Factory-Methode befinden). ** Wenn ja **: Sie haben keine andere Wahl, als es außerhalb der Fabrik zu belassen, da Sie nicht wissen können, ob es initialisiert ist oder nicht – PatrikAkerstrand