I quite like the instance initializers, too. The only drawback is that they create anonymous inner classes every time you use one, but considering the advantages of better encapsulation and nice scoping of the construction block I think the extra $n classes are a small price to pay.
Peter Viktor Klang wrote: > > > On Sun, Feb 22, 2009 at 11:23 PM, Christian Catchpole > <[email protected] <mailto:[email protected]>> wrote: > > > I guess there is no right or wrong to most patterns, it's just a > matter of taste. My person opinion is that ThreadLocals are a bit of > a hack. I'm an advocate for optimizing interfaces, reducing boiler > plate and minimizing code. But I drew the line when it breaks some > fundamental paradigms. > > Readers will have heard me complain about the "returning self" builder > pattern. > > new Thing().setOne().setTwo() > > > Ah, this reminds me... > > > I've grown more and more fond of using instance-initializers. > > It produces more declarative looking code: > > someArea = new JTextArea(10, 20){ > { > setLineWrap(true); > > setBorder(BorderFactory.createLineBorder(Color.BLACK)); > setMaximumSize(new > Dimension(100,100)); > > setBackground(Color.RED); > }}; > > Pros with this approach is that you don't loiter the code, it's > apparent that the code belongs to the created instance, > you can make all "construction-time only" methods into "protected" so > they're not accessible from outside object creation (thus encouraging > information hiding etc) > > This allows you to write stuff like: > > > public abstract class Foo > { > private Bar bar; > private Baz baz; > protected void setBar(Bar bar) { this bar = bar; } > protected void setBaz(Baz baz) { this baz = baz; } > public Bar getBar() { return this.bar; } > public Baz getBaz() { return this.baz; } > } > > then in other package: > > { > Foo myFoo = new Foo(){{ > setBar(someBar); > setBaz(someBaz); > }}; > > myFoo.setBar(null); //Not visible > myFoo.getBar(); //Visible > } > > > > > Why should the API change so my code can be a little more compact? > > There is talk of adding 'returning self' as a language feature. I > can't understand why we don't implement a globally applicable language > feature that doesn't change APIs and works on existing code. Having a > method return (this) at the end is somewhat broken.. If not just plain > strange. > > using (new Thing()) { setOne(); setTwo() } // override the default > 'this.' within the block. > > But that's another thread. :) > > I guess ThreadLocal is more of an accepted pattern, even if I don't > like it. > > ThreadLocal assumes you code is running on that and only that thread. > It also can cause problem with garbage collection (entities don't get > collected when they should). > > On Feb 23, 7:20 am, Christian Hvid <[email protected] > <mailto:[email protected]>> wrote: > > There is a built-in connection pool and you are right; there is no > > overhead in closing and opening a pooled connection. > > > > But you still have to say what database is used. And here it is the > > database the caller is using unless explicitly stated otherwise. > > > > Wrt. ThreadLocal - the way it is used here is a bit like context > > passing in AspectJ. > > > > I don't think it is evil. It is just not commonly used in Java. > But it > > has its merits and here it serves the purpose of reducing boiler > plate > > code. > > > > On Feb 22, 9:51 pm, Christian Catchpole <[email protected] > <mailto:[email protected]>> > > wrote: > > > > > I think stageful statics are evil. I think ThreadLocal should > be cast > > > into a large pit and burried. :) > > > > > Isn't connection management a non-issue in web containers and even > > > stand along apps with a good connection pool. When you open > and close > > > a connection, you are just borrowing a slot in a pool. There > is no > > > expense to it. In fact the pool will do clever things such as > match > > > prepared statements to connections which it has already been > prepared > > > on. > > > > > I'm simply suggesting that you might be able to get away with > hiding > > > the connection management. > > > > > I'm not trying to discourage your work. I have written a > persistence > > > layer which takes a completely different approach again. > > > > > Nice name by the way. :) > > > > > On Feb 23, 5:58 am, Christian Hvid <[email protected] > <mailto:[email protected]>> wrote: > > > > > > :-D > > > > > > Great, exactly. > > > > > > This is the point - it removes a lot of code - it is magic - > and thus > > > > smells of ... air - unless you are used to it. > > > > > > You avoid carrying around a JDBC connection object or a > reference to > > > > something like jdbcTemplate. > > > > > > Suppose you write a web application and in your servlet code > or page > > > > code you have a single try finally block that opens and > closes the > > > > database connection. > > > > > > Within that block you call into your business code and your > business > > > > code uses various database queries - all against the > connection that > > > > you manage with the try catch block. > > > > > > The reason it is a stack of connections and just one > connection - is > > > > that a stack allows you to use multiple databases / > connections - so > > > > this would work: > > > > > > public long accountBalance(int accountId) { > > > > openConnection("accounting"); > > > > try { > > > > return queryScalar(Integer.class, "select balance from > account > > > > where id=?", accountId); > > > > } finally { > > > > closeConnection(); > > > > } > > > > > > } > > > > > > int accountId = 27; > > > > > > try { > > > > openConnection("logging"); > > > > update("insert into log(account_id, balance) values(?, ?)", > > > > accountId, accountBalance(accountId));} finally { > > > > > > closeConnection(); > > > > > > } > > > > > > On Feb 22, 7:59 pm, Robert Fischer > <[email protected] > <mailto:[email protected]>> > > > > wrote: > > > > > > > Now you've shifted the problem from a plumbing issue to a > magical state issue. This is a major code > > > > > smell and complicates the API in nonobvious (to the user) > ways. > > > > > > > (Of course, I'm the guy who also finalizes his method > arguments. So I've got some wacky opinions > > > > > relative to Java norms.) > > > > > > > ~~ Robert. > > > > > > > Christian Hvid wrote: > > > > > > But you can leave it up to the caller to open the > connection - meaning > > > > > > you just don't open or close any connections. > > > > > > > > public int getUserCount() { > > > > > > return queryScalar(Integer.class, "select count(*) > from people"); > > > > > > } > > > > > > > > And then have the calling code open and close the > connection: > > > > > > > > openConnection(); > > > > > > try { > > > > > > ... > > > > > > getUserCount(); > > > > > > ... > > > > > > } finally { > > > > > > closeConnection(); > > > > > > } > > > > > > > > (The idea is that there is a stack of connections and > when you do > > > > > > something you always use the connection at the top of > the stack.) > > > > > > > > On Feb 22, 7:24 pm, Robert Fischer > <[email protected] > <mailto:[email protected]>> > > > > > > wrote: > > > > > >> The problem is this code: > > > > > > > >> public int getUserCount() { > > > > > >> openConnection(); > > > > > >> try { > > > > > >> return queryScalar(Integer.class, > "select count(*) from people"); > > > > > >> } finally { > > > > > >> closeConnection(); > > > > > >> } > > > > > > > >> } > > > > > > > >> That's 1 semantically meaningful line surrounded by 5 > lines of boilerplate plumbing. Which means > > > > > >> that it's really 1/6th actual code, and 5/6th noise. > That's a pretty poor signal to noise ratio. > > > > > > > >> It's even worse when you're dealing with raw JDBC > calls, since you have to think about preparing > > > > > >> statements and managing connections and data sets and > the like. > > > > > > > >> ~~ Robert. > > > > > > > >> Christian Hvid wrote: > > > > > >>> I don't understand - why would that be a problem? > (That you have > > > > > >>> explictly open and close your database connection). > > > > > >>> On Feb 22, 7:09 pm, Robert Fischer > <[email protected] > <mailto:[email protected]>> > > > > > >>> wrote: > > > > > >>>> +1 for Spring JDBC: it manages all that > openConnection/closeConnection noise for you, which means > > > > > >>>> that your JDBC code can *also* start to be expressive. > > > > > >>>> ~~ Robert. > > > > > >>>> Rakesh wrote: > > > > > >>>>> have you looked at Spring JDBC? It has a similar > interface and manages > > > > > >>>>> the connections for you. > > > > > >>>>> I think if you go down a non-orm route and want to > have lots of sql, > > > > > >>>>> Ibatis is quite common - not used it so can't say > for sure. > > > > > >>>>> Spring JDBC though is very nice and have used it > extensively. > > > > > >>>>> Rakesh > > > > > >>>>> On Sun, Feb 22, 2009 at 2:21 PM, Christian Hvid > > > > > >>>>> <[email protected] > <mailto:[email protected]>> wrote: > > > > > >>>>>> Hi Java people. > > > > > >>>>>> I have been toying with simplier ways of doing > embedded SQL in Java. > > > > > >>>>>> And would like your comments on this one? > > > > > >>>>>>http://code.google.com/p/chalkmine/ > > > > > >>>>>> It allows you to write code like this: > > > > > >>>>>> openConnection(); > > > > > >>>>>> try { > > > > > >>>>>> int count = queryScalar(Integer.class, "select > count(*) from > > > > > >>>>>> people"); > > > > > >>>>>> System.out.println("There are "+count+" people > in the bin."); > > > > > >>>>>> } finally { > > > > > >>>>>> closeConnection(); > > > > > >>>>>> } > > > > > >>>>>> or > > > > > >>>>>> openConnection(); > > > > > >>>>>> try { > > > > > >>>>>> List<Person> people = queryList(Person.class, > "select name, > > > > > >>>>>> time_in_the_bin from people"); > > > > > >>>>>> for (Person p : people) > > > > > >>>>>> System.out.println(p.getName()+" has been > "+p.getTimeInTheBin() > > > > > >>>>>> +" hours in the bin."); > > > > > >>>>>> } finally { > > > > > >>>>>> closeConnection(); > > > > > >>>>>> } > > > > > >>>>>> (Provided that Person has a constructor matching > the types of name, > > > > > >>>>>> time_in_the_bin. Probably Person(String, int).) > > > > > >>>>>> Where the methods openConnection, queryScalar, > queryList, > > > > > >>>>>> closeConnection are statically imported. > > > > > >>>>>> openConnection() figures out the name of the > calling class, looks up a > > > > > >>>>>> configuration, opens a connection and puts in a > ThreadLocal container. > > > > > >>>>>> queryScalar(Class, String, ...) performs a query > with a single row > > > > > >>>>>> result that is "cast" to the given class. > > > > > >>>>>> queryList(Class, String, ...) performs a query and > returns the result > > > > > >>>>>> as a list of the given class. > > > > > >>>>>> I would like to turn it into a full-fledged open > source project. > > > > > >>>>>> But since it is incredibly hard for a new open > source project to gain > > > > > >>>>>> traction I would like to figure out whether it is > interesting enough > > > > > >>>>>> first. > > > > > >>>>>> -- Christian > > > > > >>>> -- > > > > > >>>> ~~ Robert Fischer. > > > > > >>>> Grails Training http://GroovyMag.com/training > > > > > >>>> Smokejumper Consultinghttp://SmokejumperIT.com > > > > > >>>> Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog > > > > > >>>> Check out my book, "Grails Persistence with GORM and > GSQL"!http://www.smokejumperit.com/redirect.html > > > > > >> -- > > > > > >> ~~ Robert Fischer. > > > > > >> Grails Training http://GroovyMag.com/training > > > > > >> Smokejumper Consultinghttp://SmokejumperIT.com > > > > > >> Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog > > > > > > > >> Check out my book, "Grails Persistence with GORM and > GSQL"!http://www.smokejumperit.com/redirect.html > > > > > > > -- > > > > > ~~ Robert Fischer. > > > > > Grails Training http://GroovyMag.com/training > > > > > Smokejumper Consultinghttp://SmokejumperIT.com > > > > > Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog > > > > > > > Check out my book, "Grails Persistence with GORM and > GSQL"!http://www.smokejumperit.com/redirect.html > > > > > -- > Viktor Klang > Senior Systems Analyst > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/javaposse?hl=en -~----------~----~----~----~------~----~------~--~---
