Re: WebObjects and dependency injection (DI)
Re: WebObjects and dependency injection (DI)
- Subject: Re: WebObjects and dependency injection (DI)
- From: Henrique Prange <email@hidden>
- Date: Mon, 21 Sep 2009 19:11:51 -0300
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 (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden