On 22/09/2009, at 4:07 PM, Anjo Krank wrote:

I'm not sure you understand... the String thing is only the bottleneck. I have caller code like:

ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, model.name ());
        ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, dbc);
ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, channel);

Surely you don't suggest I need to create a "module" in every top- level caller?

My argument being, I have a lot of code that depends on various "services" and their instantiation. But 90% of the time, this code depends on user input, program state and external stuff. It's very rare that I actually know at compile time what implementation I have. We normally use Class.forName().newInstance() in some way or other to handle that. So can DI help me there? If yes, how?

Yeah, this is what I assumed Anjo was getting at - after some thought, of course (as Anjo's usually the king of succinctness :)

It seems to me that factory instantiations (as above) and/or making use of delegates provides all the opportunities for environment/ context-based switching that DI promises. i.e., both delegate style and DI style require the declaration of injection points and interfaces to implement, factories providing all the opportunities for custom implementations etc... so Andrus would you like to elaborate on why you think DI would be particularly advantageous over these given that it would require hacks?

And Kieran: properties are there to make things *easier* I wouldn't want to avoid if's at the cost of putting every constructor in there... I dread the guy who has to deal with that after you...

Cheers, Anjo

Am 22.09.2009 um 00:11 schrieb Henrique Prange:

Hi Anjo,

You would not need a static method to create new ERXSQLHelper objects if you were using a DI container. For example, using Guice you could declare a helper property that must be injected.

@Inject
ERXSQLHelper helper;

If you were too lazy you could let the user define which implementation to use. For example, using Guice this is achieved with a Module with the following binding:

bind(ERXSQLHelper.class).to(OracleSQLHelper.class);

If I had to implement this using Guice, I would create an ERXSQLHelper provider that would return the right ERXSQLHelper based on the chosen database. Of course, to avoid the same code (nested ifs) inside the provider, I would refactor the way the database type is defined too.

IMHO, one advantage of this approach is I could create my own extension of ERXSQLHelper class and bind to all ERXSQLHelper declarations easily. I just need to create my own Module with the following code:

bind(ERXSQLHelper.class).to(MyOwnSQLHelper.class);

I could do the same thing with the current implementation, but I need to set a property that is not type safe and you had to write a lot of boilerplate code to support this.

Guice fail fast mechanism also helps to find problems earlier. If something is wrong with the bindings, an exception is thrown as soon as you create the Injector. In your example, I would get a NoClassDefFound in runtime, during a very important presentation, of course. :p

And last, but not least, you could bind a MockERXSQLHelper class when unit testing classes that depend upon ERXSQLHelper.

Cheers,

Henrique

Anjo Krank wrote:
U-huh. So how about a real world example and not these cooked up things. Take a look at the ERXSQLHelper. Depending on various types of input it creates a concrete subclass. Can DI change this to sth more "clean"?
Cheers, Anjo
public static ERXSQLHelper newSQLHelper(String databaseProductName) {
  synchronized (_sqlHelperMap) {
    ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
    if (sqlHelper == null) {
      try {
String sqlHelperClassName = ERXProperties.stringForKey (databaseProductName + ".SQLHelper");
        if (sqlHelperClassName == null) {
          if (databaseProductName.equalsIgnoreCase("frontbase")) {
            sqlHelper = new FrontBaseSQLHelper();
          }
          else if (databaseProductName.equalsIgnoreCase("mysql")) {
            sqlHelper = new MySQLSQLHelper();
          }
          else if (databaseProductName.equalsIgnoreCase("oracle")) {
            sqlHelper = new OracleSQLHelper();
          }
else if (databaseProductName.equalsIgnoreCase ("postgresql")) {
            sqlHelper = new PostgresqlSQLHelper();
          }
else if (databaseProductName.equalsIgnoreCase ("openbase")) {
            sqlHelper = new OpenBaseSQLHelper();
          }
          else if (databaseProductName.equalsIgnoreCase("derby")) {
            sqlHelper = new DerbySQLHelper();
          }
else if (databaseProductName.equalsIgnoreCase ("microsoft")) {
            sqlHelper = new MicrosoftSQLHelper();
          }
          else {
            try {
sqlHelper = (ERXSQLHelper) Class.forName (ERXSQLHelper.class.getName() + "$" + databaseProductName + "SQLHelper").newInstance();
            }
            catch (ClassNotFoundException e) {
              sqlHelper = new ERXSQLHelper();
            }
          }
        }
        else {
sqlHelper = (ERXSQLHelper) Class.forName (sqlHelperClassName).newInstance();
        }
        _sqlHelperMap.put(databaseProductName, sqlHelper);
      }
      catch (Exception e) {
throw new NSForwardException(e, "Failed to create sql helper for the database with the product name '" + databaseProductName + "'.");
      }
    }
    return sqlHelper;
  }
}
Am 21.09.2009 um 23:24 schrieb Andrew Lindesay:
Hi Anjo;

I guess this could be helpful in _some_ situations; I take for example, the Jetty server. Jetty can have a number of "handlers" added to it. Each handler does something like re-writes, feeds disk-based content, runs servlets etc.. etc.. The Jetty authors could not have envisaged all of the possible handlers that might have been written for Jetty, but because of the configuration style which follows the same line of thinking as Andrus is describing, it is possible to configure additional handlers. So that's a good example of where this seems quite helpful and Andrus' other examples also feel like good examples, but I agree that it seems like over-kill for many situations.

cheers.

Thanks for the write-up, but yeah, this can all be achieved w/o it. I really don't see why I shouldn't configure my app with if (Configration.isStaging())... and instead use DI. At least my way I easily find all the occurrences and have full logic support if(!Configuration.isStaging()). How is DI "cleaner" in any way when:

- I have any number of DI containers and their various syntax to chose from - I can't *find* the dependencies when I really want or need them. Have you ever tried to debug such an app that wasn't written by yourself? Take a look at the Red5 Media server for some fun...

___
Andrew Lindesay
www.lindesay.co.nz

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/hprange%40gmail.com
This email sent to hpra...@gmail.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/anjo %40krank.net

This email sent to a...@krank.net

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/lachlan.deck%40gmail.com

This email sent to lachlan.d...@gmail.com

with regards,
--

Lachlan Deck



_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to