Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
OOPzwei gleiche Methoden mit kleinen Unterschieden
was macht ihr, wenn ihr methoden habt die vom Ablauf her gleich sind, rufen jedoch auf einem Objekt andere Methoden auf? gibt es da einen eleganten workaround?
Template method ist es nicht, da aufzurufende Methoden verschiedene Parameter haben.
wenn die Parameter unabhängig vom umgebenden Code sind, was schwer vorzustellen ist, dann kannst du doch durchaus etwas von außen reingeben,
anderenfalls ist es komisch dass es derselbe Code ist,
na schwer zu beschreiben ohne Beispiel, wie sieht es denn bei dir aus?
neben Vorgabe von außen geht wohl nur noch ein if/else-Block in der Mitte
ins Blau geraten wuerde ich eine Art Callback interface mitgeben.
Die beiden Methoden rufen dann eine dritte methode auf, die die gemeinsame Codebasis enthaelt und eben einer Implementierung des Interfaces, welches dann die entsprechende Methode aufruft.
kann natuerlich sein dass auch eine simple fall unterscheidung reicht
es sind zwei jobs, die emails verschicken, der eine braucht parameter und der andere nicht. vom ablauf sind sie fast gleich, der unterschied besteht eben in dem (nicht-)vorhandensein von parametern. die zwei jobs müssen die sich etwas von einander unterscheidenden SQL-Anfragen auf der DB ausführen. Dies erledigt eine DAO-Klasse. Es unterscheiden sich also die Aufrufe auf der DAO-Klasse.
d.h. eine Methode hat n Parameter, die andere keine ?
mhm wie auch immer, ich bin kein freund davon eine gemeinsame methode aufzurufen und dann ueber Parameter verhalten zu steuern (in dem sinne von "wenn der erste parameter null ist dann machen wir das und wenn der zweite null ist dann das" etc). Da wuerde ich das Callback interface vorziehen, da dies bei weitem flexibler ist fuer den Fall dass spaeter noch ein dritter Fall hinzukommt
ich verstehe nicht wie das Callback Interface mein problem lösen soll. oder vielleicht verstehe ich es nicht wie Du es meinst.
es gibt einfach stellen im code die sich eben duch die parameter (in einem fall gibt es die und es muss damit was gemacht werden und im anderen fall gibt es die nicht)
du kannst ja an das Callback alle Parameter übergeben und dieses leitet sie intern weiter oder ruft eine Methode ohne/ mit anderen Parametern auf,
dass manche Parameter im Callback nicht genutzt werden, wäre kein Beinbruch
public void foo() {
final String aStringParam = "parameter";
inner(new CallbackInterface() {
public void callback(Dao theDao) {
theDao.doSomething(aStringParam);
}
});
}
public void bar() {
final int counter = 2;
inner(new CallbackInterface() {
public void callback(Dao theDao) {
theDao.doSomethingElse(2);
}
});
}
private void inner(CallbackInterface callback) {
Dao theDao = ....
// do whatever needs to be done
callback.callback(theDao);
// do if something needs to be done
}
in inner befinden sich alle gemeinsamkeiten, der eigentliche unterschiedliche Aufruf zum DAO (so weit ich verstanden habe) ist in das callback ausgelagert.
Falls die eigentlichen Methoden (hier [c]doSomething[/c] und [c]doSomethingElse[/c] andere Paramter brauchen, die sich erst in [c]inner[/c] ergeben, die nicht gleich sind, so muss der Bruch der Logik in [c]inner[/c] komplexer stattfinden - oder es gibt eine Art parameterobjekt und die callbacks lesen sich dann die benoetigen aus.... spaetestens hier gehts wahr. ohne code nicht wirklich
nun, ich habe wie empfohlen das CallbackInterface verwendet, es wird sich zeigen ob das funktioniert, bin noch nicht ganz fertig. An der von mir gemeinten Stelle ist es denke ich auf jeden Fall eine gute Möglichkeit.
Ich hasse es den Code zu duplizieren, ich habe nie ein gutes Gefühl dabei undversuche es zu vermeiden. In der Prouktiventwicklung wird es trotzdem gemacht (???). Manchmal denke ich, ob es sich lohnt sich so viele Gedanken zu machen wegen 20 Zeilen Code? Was meint Ihr?
Wie ich schon erwähnt habe, habe ich zwei Jobs zum verschiecken von Emails. Die Jobs greifen auf die DB zu, um festzustellen an wen sollten Emails verschickt werden und was soll darin stehen. Der eine Job ist bereits implementiert, den anderen muss ich implementieren. Beim Zugriff auf die DB (in der oben erwähnten DAO-Klasse) wird zunächst einmal die Informationen für den Header abgefragt. Bei dem ersten Job werden 2 Parameter für den vordefinierten SQL-Statement verwendet, bei meinem Job gibt es keine Parameter, sondern einen vordefinierten SQL-Statement der sich nur in der WHERE-Klausel von dem 1. unterscheidet. Dementsprechned wenn man die Ergebnisse zurückbekommt, füllt man eine Liste von Data Container mit informationen (durch aufruf von setter Methoden). Der Unterschied zu meinem Job besteht darin, dass ich die Parameter im Statement nicht setze und dass ich 3 setter nicht aufrufe in dem jeweiligen Data Container. Leider weiß ich nicht die Möglichkeit was ich tun könnte um den Code nicht zu duplizieren. if-Abfrage fände ich überhaupt nicht schön an der Stelle.
Was würdet Ihr machen? Code duplizieren oder gäbe es hier doch eine Möglcihkeit dies zu vermeiden?
> Manchmal denke ich, ob es sich lohnt sich so viele Gedanken zu machen wegen 20 Zeilen Code? Was meint Ihr?
wenn du allgemein nachdenkst, z.B. über das generelle Mini-DB-Framework des Programms
bzw. die Möglichkeiten das Callbacks an sich auslotest, dann ist das gut investerte Zeit,
so denke ich das jedenfalls auch für mich,
wenn du das zum x-tem Mal tust, dann vielleicht wirklich fraglich
zu deiner Anwendung/ zum speziellen Einzelfall ist schwer zu sagen was dort möglich ist und wofür sich Zeit lohnt,
zwei wenig ähnliche Aktionen zusammenzumischen mit drei speziellen Codestellen die man beachten muss klingt gefährlich, selber wenn 19 weitere Zeilen nicht kopiert werden..
im Zweifel durchaus auch mal doppelt,
noch eine kleine Strohhalm-Zwischenlösung:
vielleicht kann man einzelne Bestandteile der beiden ähnlichen Aktionen zusammenfassen uns auslagern,
try/catches sollten bei sowas gar nicht zu sehen sein, ansonsten kann ich jetzt ohne Code nix vorschlagen,
ganz allgemein:
nicht
Java:
methode12
{
langer Code A
if Unterscheidung
langer Code B
if ..
langer Code C
if ..
langer Code D
}
eher, aber auch nicht unbedingt:
Java:
methode1
{
langer Code A
Fall 1
langer Code B
Fall 1
langer Code C
Fall 1
langer Code D
}
methode2
{
langer Code A
Fall 2
langer Code B
Fall 2
langer Code C
Fall 2
langer Code D
}
sondern vielleicht:
Java:
methode1
{
Aufruf methodeA
Fall 1
Aufruf methodeB
Fall 1
Aufruf methodeC
Fall 1
Aufruf methodeD
}
methode2
{
Aufruf methodeA
Fall 2
Aufruf methodeB
Fall 2
Aufruf methodeC
Fall 2
Aufruf methodeD
}
methodeA
methodeB
methodeC
methodeD
so ideal wird es nie klappen, aber das ist das anvisierte Ziel,
durchaus unterschiedliche Methoden, aber nur mit dem wesentlichen gefüllt,
was immer doppelt ist kann vielleicht ausgelagert werden
ja die Möglichkeiten sind mir auch durch den Kopf gegangen und ja es steht im try catch Block. Die Methode lässt sich nicht so einfach und schön außeinander zu trennen, deshalb habe ich gerade beschloßen sie zu duplizieren. Die guten Lösungen sollten einfach nachvollziehbar und logisch sein. Wenn ich die zwei Parameter nicht hätte, die ich sonst überall mitschleppen muss (oder in einem anderen fall nicht muss), würde ich vielleicht darüber nachdenken in einzelne Methoden zu trennen.
Hm...
das geht nun tief in deinen code rein, so dass denk ich, so wie Slater schon sagt, nicht einfach ist allgemein zu sagen wie man es macht - die Moeglichkeit der beruehmten Ausnahme ist immer gegeben.
Ansonsten vertrete ich den Standpunkt, dass man zu keiner Zeit versuchen sollte duplizierten Code zu haben. Sobald man anfaengt code zu kopieren muss man sich schon Gedanken machen ueber eine sinnvollere Loesung.
Inwieweit das natuerlich zum Teil mit legacy code moeglich ist bzw welchen Aufwand es kostet ist hier ausgenommen, daher kann die Frage erstmal ohne Code nur theoretisch beantwortet werden.
Von deiner Beschreibung klingt es fuer mich als ob der Unterschied in der Behandlung des SQL statements liegt, dann wuerde eine logische Folge sein, dass die generelle Methode ein fertiges SQL statement bekommt und die spezielle Methoden eben dieses vorbereiten.
Aber das ist natuerlich auch nur ins Blaue geraten
Du kannst auch mal nachsehen, was die beiden Jobklassen gemein haben. Das extrahierst Du dann in einen abstrakten Job, der eine oder mehrere Methode als abstrakt erklärt und benutzt, die die erbenden Jobs überschreiben müssen. In diesen Methoden sind dann die kleinen aber feinen Unterschiede enthalten.
Von deiner Beschreibung klingt es fuer mich als ob der Unterschied in der Behandlung des SQL statements liegt, dann wuerde eine logische Folge sein, dass die generelle Methode ein fertiges SQL statement bekommt und die spezielle Methoden eben dieses vorbereiten.
Aber das ist natuerlich auch nur ins Blaue geraten
Mit Deinem "ins Blaue geraten" lagst Du gar nicht mal so daneben.
Schließlich habe ich nun keine Duplizierungen im Code, was meinem Gewissen dann natürlich gut tut. Bei der Implementierung gab es drei Anfragen, die sich teilweise nur in der WHERE-Klausel unterschieden haben. Eine von diesen Anfragen unterschied sich dann auch in den selektierten bzw. gruppierten Feldern. Von den Kollegen habe ich erfahren, dass wir hier ein Filtering-Mechanismus haben mit dem ich eine WHERE-Klausel bauen kann. Somit übergab ich dann der DAO klasse ein Filter-Objekt, der sich um die WHERE-Klausel gekümmert hat. Ansonsten hatte ich dann eine abstrakte Helper-Klasse, die mir die Anfragen gebaut hat und wenn sie sich bei den beiden Jobs unterschieden haben (also nicht nur in der WHERE-Klausel) dann war dafür(und für das Befüllen vom Modell wenn ich die Ergebnisse der Anfragen zurückbekomme) die jeweilige Helper-Implementierung zuständig.
Ich denke das ist das beste was ich bei dem Job rausholen konnte, ansonsten gibt es immer etwas zu verbessern
Ich danke Euch auf jeden Fall für Eure Anregungen, es hat mir sehr geholfen!