Monday, January 31, 2005
Saturday, January 22, 2005
In the Year 2000
I was bringing up some discussion on where our development group would like to go with web page development. A lot of stuff started popping into my head as we talked.
The cause for the discussion in the first place is that things have become unbelievably hard to manage in our web pages-- a hodge-podge of HTML, Javascript, Custom tags, Scriplets, and JSTL. I brought up a few solutions and reworked a bit of my previous post on Development with CSS, mainly from the standpoint of the programmer (I might write another blog on this).
But to go off on a tangent-- here we have JSP technology. An unbelieveably flexible medium to create your applications with (Scriplets/Javascript/HTML/Tags). But to use our stuff as an example, maybe too flexible. I'm not saying that there is anything at all wrong with JSP, but in the future I'm going to use the JSP medium as a strong reflection of what we choose for frameworks and tools. I don't want to end up with Java code that reads like some of our old JSP pages, a little Java, a dash of proxies, a pinch of Aspects, with a little bit of specialized scripting languages.
Although, I do remember reading an article only a short while back on how future applications will just be specialized vendor tools thrown together. Not that it isn't that way now.
Maybe it isn't so much what we use for frameworks and tools, but how we use them. My example of the JSP page, everything is boiled together at the top. This is where component-based development would come in handy-- programmer develops a component that encapsulates client/server behavior in a standardized way, then the JSP page is just a compilation of custom tags only that hide all of the other concerns.
The cause for the discussion in the first place is that things have become unbelievably hard to manage in our web pages-- a hodge-podge of HTML, Javascript, Custom tags, Scriplets, and JSTL. I brought up a few solutions and reworked a bit of my previous post on Development with CSS, mainly from the standpoint of the programmer (I might write another blog on this).
But to go off on a tangent-- here we have JSP technology. An unbelieveably flexible medium to create your applications with (Scriplets/Javascript/HTML/Tags). But to use our stuff as an example, maybe too flexible. I'm not saying that there is anything at all wrong with JSP, but in the future I'm going to use the JSP medium as a strong reflection of what we choose for frameworks and tools. I don't want to end up with Java code that reads like some of our old JSP pages, a little Java, a dash of proxies, a pinch of Aspects, with a little bit of specialized scripting languages.
Although, I do remember reading an article only a short while back on how future applications will just be specialized vendor tools thrown together. Not that it isn't that way now.
Maybe it isn't so much what we use for frameworks and tools, but how we use them. My example of the JSP page, everything is boiled together at the top. This is where component-based development would come in handy-- programmer develops a component that encapsulates client/server behavior in a standardized way, then the JSP page is just a compilation of custom tags only that hide all of the other concerns.
Thursday, January 20, 2005
New Articles
I was lucky enough to get an article at OnJava.com.
Alex Winston (who I thought fell of the face of the planet), just posted an awesome article on functional objects (similar to commons-collections, but with generics).
Alex Winston (who I thought fell of the face of the planet), just posted an awesome article on functional objects (similar to commons-collections, but with generics).
Monday, January 17, 2005
When Will We Come Full Circle?
Kirill Grouchnikov recently blogged about his distaste for AOP, and I have to completely agree with the guy. Not to my surprise, a few disagreed with him, retorting that, "you don't understand AOP." What aren't we understanding, and more importantly, when will the Java developer community come full circle?
I look at things like Groovy and AOP, what are we gaining? What purpose does it serve that can't already be accomplished in Java? Is it appealing to some developers because it's simply something new and more interesting to try? Or, is it appealing because developers are trying to solve problems they've created for themselves?
Really, we can't blame developers for thinking AOP is the greatest thing next to sliced bread, or blame those developers who have developed their entire application in Groovy. I say we blame the specification groups and framework developers. Ask yourself, "Why is AOP so appealing here?" Is it because the API is so horridly complex that developers seek to jump completely out of the "box" into byte code manipulation, just to better understand what they are doing?
Simon Brown also blogged about a new Web Services Tag library. What's the goal? To simplify the use of web services. I find this funny since we can generate a JSR for an easy to use tag library, yet we must still jump through hoops on the Java side to deploy and use web services. I realize that open source projects have made web services easier, but for pete's sake, why isn't this standardized in an easy to use API?
Some may argue that most specifications generated are for vendors, giving them grace for being so complex and yet so flexible. An example is JavaServerFaces, a framework geared at working directly with your plain old Java Objects-- beautiful, but I wouldn't use it without a development tool.
But then I look at some other specifications that have come out and for the every day developer, it's like choosing a contractor to build your house, and then they just dump all the materials on site and leave you with a few instructions. Maybe this is why .Net is so appealing? There, I said it. Developer friendly APIs, not vendor friendly APIs.
At the ServerSide.com, they just posted an interview with the EJB 3.0 spec where a question was asked, "POJO programing is definitely one of the hottest things going. How is the POJO programing model on EJB3 going to affect developers?" To which he replied, "I think it is going to have a big impact on developers, in particular, because it simplifies what developers are required to do to write an EJB. So the bean class much more like regular java beans class now. It's not required to implement a particular call back interface or extend EJB classes like it was in the past. So it has made EJB development a lot more like regular java development."
What's wrong with this--? POJO programming is definitely one of the hottest things going... the POJO programming model? You mean developers are actually using plain old java objects again-- or as he put it, "regular java beans"?! Taboo I tell you. Basically, this is a perfect example of why Java went wrong.
In any case, I'm still waiting for the day when developers will feel comfortable actually new'ing an instance of something in their code again-- instead of using some factory with byte code weaving under a proxy layer which is an object with twenty 'setters' and no concept of encapsulation, referenced by some key name *cough*.
I look at things like Groovy and AOP, what are we gaining? What purpose does it serve that can't already be accomplished in Java? Is it appealing to some developers because it's simply something new and more interesting to try? Or, is it appealing because developers are trying to solve problems they've created for themselves?
Really, we can't blame developers for thinking AOP is the greatest thing next to sliced bread, or blame those developers who have developed their entire application in Groovy. I say we blame the specification groups and framework developers. Ask yourself, "Why is AOP so appealing here?" Is it because the API is so horridly complex that developers seek to jump completely out of the "box" into byte code manipulation, just to better understand what they are doing?
Simon Brown also blogged about a new Web Services Tag library. What's the goal? To simplify the use of web services. I find this funny since we can generate a JSR for an easy to use tag library, yet we must still jump through hoops on the Java side to deploy and use web services. I realize that open source projects have made web services easier, but for pete's sake, why isn't this standardized in an easy to use API?
Some may argue that most specifications generated are for vendors, giving them grace for being so complex and yet so flexible. An example is JavaServerFaces, a framework geared at working directly with your plain old Java Objects-- beautiful, but I wouldn't use it without a development tool.
But then I look at some other specifications that have come out and for the every day developer, it's like choosing a contractor to build your house, and then they just dump all the materials on site and leave you with a few instructions. Maybe this is why .Net is so appealing? There, I said it. Developer friendly APIs, not vendor friendly APIs.
At the ServerSide.com, they just posted an interview with the EJB 3.0 spec where a question was asked, "POJO programing is definitely one of the hottest things going. How is the POJO programing model on EJB3 going to affect developers?" To which he replied, "I think it is going to have a big impact on developers, in particular, because it simplifies what developers are required to do to write an EJB. So the bean class much more like regular java beans class now. It's not required to implement a particular call back interface or extend EJB classes like it was in the past. So it has made EJB development a lot more like regular java development."
What's wrong with this--? POJO programming is definitely one of the hottest things going... the POJO programming model? You mean developers are actually using plain old java objects again-- or as he put it, "regular java beans"?! Taboo I tell you. Basically, this is a perfect example of why Java went wrong.
In any case, I'm still waiting for the day when developers will feel comfortable actually new'ing an instance of something in their code again-- instead of using some factory with byte code weaving under a proxy layer which is an object with twenty 'setters' and no concept of encapsulation, referenced by some key name *cough*.
Thursday, January 06, 2005
Dual Persistence Strategies
I was once asked if it's appropriate to use EJBs when fetching large datasets. The answer is of course no. To highlight this point, Sun has recently posted comparisons on persistence frameworks.
After writing my blog entry on Corporate Development, I realized that I wasn't covering all my bases with persistence. In the blog, I wrote about using open frameworks like JDO or Hibernate and throwing DAO's completely out the window. This isn't necessarily the impression I wanted to leave casual readers with.
For example, say you are writing an ordering application and you have various requirements having to do with line items, listing products, validating orders, etc. Idealy this sample of requirements would require two persistence strategies, one for supporting the view (large fetch/search operations) and one for supporting transactions (more robust data objects) (notice I'm beating this mule about objects never being able to serve all contexts).
Let's walk through the process of searching for a product and adding it to an order. Often times now the solution developers write is a DAO with a bunch of fetch operations for "light products" which contain data that only serves the view, then having a single fetch method by ID that returns a "full product". This dual object model returned from the DAO is done in order to optimize the frequent read operations required by the view. To implement our example above with DAO's:
Now lets say we've written our DAO and encapsulated all read or view operations, later we want to be able to do sorting for all fetch operations. Now you have to go back and modify your DAO (which you've realized isn't very 'closed' for change). We also want to be able to search for products based on both category ID and price range, are you now going to add another method to the DAO? Hopefully you can see where I'm going here.
The solution that I should have clarified in my previous blog entry was to directly and openly use Hibernate or JDO for fetch operations that serve the view; a framework that allows us to freely modify or add behavior to an application without changing a DAO layer for every requirement or view feature.
You might enquire about testability since we are using direct DB calls for read operations, but in reality you want to be testing transactions (the competancies of your application) instead of validating that Hibernate or JDO actually sorted your products by name. Our DAO should be indifferent towards view requirements.
When it comes to serving the transactional persistence model, then yes, implement a DAO service that can be mocked and tested without a database. Your service DAO's now become much simpler because most all of their operations will only need to fetch DataObjects by id.
To conclude, I would go as far as creating view specific JSF components or JSP tags that allow you to query and sort object sets directly in the view using HQL. This doesn't seem too outlandish since databases aren't likely to change and you've already provided a layer of abstraction just by using Hibernate or JDO to produce an object model with mapped properties. Quite a few years ago, I created such a taglib for Apache OJB and I still got emails a few years later with people interested in using it for application development. Even in doing this, you are still preserving your transactional behavior and testability with DAO's in the application's domain model.
After writing my blog entry on Corporate Development, I realized that I wasn't covering all my bases with persistence. In the blog, I wrote about using open frameworks like JDO or Hibernate and throwing DAO's completely out the window. This isn't necessarily the impression I wanted to leave casual readers with.
For example, say you are writing an ordering application and you have various requirements having to do with line items, listing products, validating orders, etc. Idealy this sample of requirements would require two persistence strategies, one for supporting the view (large fetch/search operations) and one for supporting transactions (more robust data objects) (notice I'm beating this mule about objects never being able to serve all contexts).
Let's walk through the process of searching for a product and adding it to an order. Often times now the solution developers write is a DAO with a bunch of fetch operations for "light products" which contain data that only serves the view, then having a single fetch method by ID that returns a "full product". This dual object model returned from the DAO is done in order to optimize the frequent read operations required by the view. To implement our example above with DAO's:
Collection<ProductView> products;
products = productDao.findAllForCategoryId(catId);
// display view let them pick a product
String prodId = request.getParameter("prodId");
ProductData product = productDao.findById(prodId);
Now lets say we've written our DAO and encapsulated all read or view operations, later we want to be able to do sorting for all fetch operations. Now you have to go back and modify your DAO (which you've realized isn't very 'closed' for change). We also want to be able to search for products based on both category ID and price range, are you now going to add another method to the DAO? Hopefully you can see where I'm going here.
The solution that I should have clarified in my previous blog entry was to directly and openly use Hibernate or JDO for fetch operations that serve the view; a framework that allows us to freely modify or add behavior to an application without changing a DAO layer for every requirement or view feature.
You might enquire about testability since we are using direct DB calls for read operations, but in reality you want to be testing transactions (the competancies of your application) instead of validating that Hibernate or JDO actually sorted your products by name. Our DAO should be indifferent towards view requirements.
When it comes to serving the transactional persistence model, then yes, implement a DAO service that can be mocked and tested without a database. Your service DAO's now become much simpler because most all of their operations will only need to fetch DataObjects by id.
To conclude, I would go as far as creating view specific JSF components or JSP tags that allow you to query and sort object sets directly in the view using HQL. This doesn't seem too outlandish since databases aren't likely to change and you've already provided a layer of abstraction just by using Hibernate or JDO to produce an object model with mapped properties. Quite a few years ago, I created such a taglib for Apache OJB and I still got emails a few years later with people interested in using it for application development. Even in doing this, you are still preserving your transactional behavior and testability with DAO's in the application's domain model.
Wednesday, January 05, 2005
Taking the Bullet
James Gosling wrote a blog entitled "Sharpen the Axe: the Dark Side". You can read the blog for yourself, but the quick and dirty is that we all can get too caught up in the path taken instead of the destination. Although James was generally describing tool development, I believe the same can be applied to application development and pattern usage.
James references a quote from Abraham Lincoln, "If I had eight hours to chop down a tree, I'd spend six sharpening my axe." While improving your situation through preparation, it's very easy to over prepare yourself without fully understanding the problem at hand. Let me rephrase that, while improving your situation through patterns, it's very easy to over engineer your application without fully understanding the problem at hand.
To continue the axe example, lets say you did spend all that time on sharpening the axe. Is that axe going to now cut everything for you? The same can be applied to object oriented development as you will soon realize the scary truth that no object model is best suited for all tasks.
Even though you spent four weeks of meetings on defining your Account object, in the end it probably won't be the best object for handling both large fetches for a view and coordinating long transactional processes. How do we find the best solution? We don't. We "cut down that f*cking tree" and then spend that extra time adapting to the next task-- if it's cutting down more trees, then by all means sharpen your axe. If there are no more trees to cut, then we have six hours to watch most of the extended edition of "Return of the King".
Robert Martin uses the quote "Fool me once, shame on you, fool me twice shame on me" --or use some other variation from President Bush. In order to save time and protect ourselves from needless complexity, we allow ourselves to be fooled only once. By letting ourselves get fooled only once (or taking the bullet), we can more rapidly move on to the other tasks. The longer we wait to fully realize what kind of changes are likely, the harder it will be to create the appropriate solution.
This methodology can go south on you but change can be harmless when you have very short development cycles. Get solutions created quickly and move on to the next, dependencies and change will present themselves as if you are reading between the lines of all your requirements. Other ways you can protect yourself is to use simple OO programming tactics such as the open/closed principle, the single responsibility principle, and the Liskov substitution principle. If you didn't put the world in the hands of that framework or object, it's not such a big deal if something in the world changes.
In summary, the basic idea is to take the bullet and develop some solution that best fits the task at hand, while not wasting time rolling out a bloated mess. This is not an excuse for poor programming style. Being able to resist premature pattern usage and abstraction is just as important as using patterns and abstraction.
James references a quote from Abraham Lincoln, "If I had eight hours to chop down a tree, I'd spend six sharpening my axe." While improving your situation through preparation, it's very easy to over prepare yourself without fully understanding the problem at hand. Let me rephrase that, while improving your situation through patterns, it's very easy to over engineer your application without fully understanding the problem at hand.
To continue the axe example, lets say you did spend all that time on sharpening the axe. Is that axe going to now cut everything for you? The same can be applied to object oriented development as you will soon realize the scary truth that no object model is best suited for all tasks.
Even though you spent four weeks of meetings on defining your Account object, in the end it probably won't be the best object for handling both large fetches for a view and coordinating long transactional processes. How do we find the best solution? We don't. We "cut down that f*cking tree" and then spend that extra time adapting to the next task-- if it's cutting down more trees, then by all means sharpen your axe. If there are no more trees to cut, then we have six hours to watch most of the extended edition of "Return of the King".
Robert Martin uses the quote "Fool me once, shame on you, fool me twice shame on me" --or use some other variation from President Bush. In order to save time and protect ourselves from needless complexity, we allow ourselves to be fooled only once. By letting ourselves get fooled only once (or taking the bullet), we can more rapidly move on to the other tasks. The longer we wait to fully realize what kind of changes are likely, the harder it will be to create the appropriate solution.
This methodology can go south on you but change can be harmless when you have very short development cycles. Get solutions created quickly and move on to the next, dependencies and change will present themselves as if you are reading between the lines of all your requirements. Other ways you can protect yourself is to use simple OO programming tactics such as the open/closed principle, the single responsibility principle, and the Liskov substitution principle. If you didn't put the world in the hands of that framework or object, it's not such a big deal if something in the world changes.
In summary, the basic idea is to take the bullet and develop some solution that best fits the task at hand, while not wasting time rolling out a bloated mess. This is not an excuse for poor programming style. Being able to resist premature pattern usage and abstraction is just as important as using patterns and abstraction.