Skip to content

Lambdas in Java

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:

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

No Trackbacks

Comments

Display comments as Linear | Threaded

netvance Softwareentwicklung on :

Bei der c# Lambda Expression gibt es ja ein "throw" statement. Verglichen mit dem console.writeLine() die ja eine "method invocation expression" mit dem void Type darstellt.

Add Comment

BBCode format allowed
Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA