Gerade bastle ich an einem Wrapper für DataSources der im Umgang mit Datenbanken helfen soll (zusätzliche Statistiken, blocking bei DB Fehlern und pausieren von DB Anfragen). Dabei wrappe ich zwei Methoden getConnection() und getConnection(String, String). Nur der Aufruf der realen Methode unterscheidet sich, der restliche Code ist in beiden Methoden gleich:
Im Sinne von DRY (don't repeat yourself) ist dies aber unschön, weil der (in Realität noch komplexere) Retry code doppelt vorkommt, und ich immer beide Methoden anpassen muss. Dieses Problem kommt oft bei Frameworks vor, und nennt sich "the whole in the middle" Muster. Eine Lösung wäre:
Das funktioniert aber nur im einfachsten Fall und es verkompliziert leider den Framework code, was auch wieder der Verständlichkeit schadet.
In C# 3.0 kann man das (wie ich grade gesehen habe) mit einer Lambda Action lösen (man kann also im Prinzip anonyme Funktionsblöcke übergeben). In Java müßte man dazu ein Objekt übergeben:
Der smartConnect() code wird damit lesbarer, und man kann auch komplexere Aktivitäten injizieren (eventuell mit Argumenten zur provide() methode), aber man muss jetzt noch eine extra Klasse definieren und alles in allem wird es auch mehr Code. Bei jedem Aufruf wird ein zusätzliches Objekt erzeugt. Ich denke ich werde also eher bei dem "if" Ansatz bleiben.
Ich vermute mal der Syntaktische Zucker "Lambda Expression" erzeugt bei C# auch ein extra Call Objekt, aber es fällt wesentlich weniger zusätzlichen Code beim Aufruf an.
CODE:
public Connection getConnection(String user, String pass) ...
{
verifyState();
while(true) {
try {
Connection c = ds.getConnection(user, pass);
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
public Connection getConnection() ...
{
verifyState();
while(true) {
try {
Connection c = ds.getConnection();
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
Im Sinne von DRY (don't repeat yourself) ist dies aber unschön, weil der (in Realität noch komplexere) Retry code doppelt vorkommt, und ich immer beide Methoden anpassen muss. Dieses Problem kommt oft bei Frameworks vor, und nennt sich "the whole in the middle" Muster. Eine Lösung wäre:
CODE:
public Connection getConnection(String user, String pass)
{
return smartConnect(true, user, pass);
}
public Connection getConnection()
{
return smartConnect(false, null, null);
}
Connection smartConnect(boolean hasArgs, String user, String pass)
{
verifyState();
while(true) {
try {
Connection c;
// --- the whole in the middle
if (hasArgs)
c = ds.getConnection(user, pass);
else
c = ds.getConnection();
// ---
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e);
}
}
}
Das funktioniert aber nur im einfachsten Fall und es verkompliziert leider den Framework code, was auch wieder der Verständlichkeit schadet.
In C# 3.0 kann man das (wie ich grade gesehen habe) mit einer Lambda Action lösen (man kann also im Prinzip anonyme Funktionsblöcke übergeben). In Java müßte man dazu ein Objekt übergeben:
CODE:
public Connection getConnection(String user, String pass)
{
return smartConnect(
new ConnectionProvider() {
Connection provide() { return ds.getConnection(user, pass); }});
}
public Connection getConnection()
{
return smartConnect(
new ConnectionProvider() {
Connection provide() { return ds.getConnection(); }});
}
Connection smartConnect(ConectionProvider cp)
{
verifyState();
while(true) {
try {
Connection c = cp.provide();
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
abstract class ConnectionProvider {
Connection provide();
}
Der smartConnect() code wird damit lesbarer, und man kann auch komplexere Aktivitäten injizieren (eventuell mit Argumenten zur provide() methode), aber man muss jetzt noch eine extra Klasse definieren und alles in allem wird es auch mehr Code. Bei jedem Aufruf wird ein zusätzliches Objekt erzeugt. Ich denke ich werde also eher bei dem "if" Ansatz bleiben.
Ich vermute mal der Syntaktische Zucker "Lambda Expression" erzeugt bei C# auch ein extra Call Objekt, aber es fällt wesentlich weniger zusätzlichen Code beim Aufruf an.
Trackbacks
Trackback-URL für diesen Eintrag
Keine Trackbacks
Kommentare
Ansicht der Kommentare:
(Linear | Verschachtelt)
Layout by Ricky Wilson | Serendipity Template by Carl Galloway | Login
Impressum
Bernd Eckenfels
Mörscher Str. 8
76185 Karlsruhe
bernd-2012@eckenfels.net
Read More
Suche
Kategorien
Verlinkung
- gesehen [597]
- the whole in the middle [823]
- www.bing.com [6]
- ak-zensur.de [4]
- www.google.at [3]
- blogsearch.google.de [1]
Kommentare
bl123 zu Passwortsicherheit
2012-02-04 14:25
Edith - die Zauberkünstlerin zu Passwortsicherheit
2012-02-04 13:00
Bernd zu Passwortsicherheit
2012-02-04 10:59
Oliver// zu Passwortsicherheit
2012-02-04 10:34
Christian zu Passwortsicherheit
2012-02-03 14:53
Michael zu Java Stream mit Puffer einlesen
2011-12-13 08:06
2011-08-17 05:22
2011-08-10 18:39
2011-08-10 17:57
Blog abonnieren
Blogsphere
Letzten Monat...
Di, 03.01.2012"Eckpunktepapier der BNetzA zu Smart Grids und Markets"
So, 01.01.2012"SQL Server JDBC Probleme"
Fr, 30.12.2011"Facebook Events im Google Kalender"
Mo, 19.12.2011"E-Mail versenden von Amazon EC2"
Fr, 09.12.2011"Java Stream mit Puffer einlesen"
