Fundamental Failing of JSF, Some Ideas for Overcoming
If you look at the history of technology, there are certain rules that exist in a kind of stratosphere, above specific technologies, that apply to lots of areas. One of those tablet rules has a vernacular version that is sh*t in/sh*t out. The basic idea being that if you let bad stuff into your program, your program will produce bad stuff. Of course, in the old days, the ‘bad‘ would be data. Today, in the age of object orientation, just calling it data is probably wrong, instead, it goes to the whole generative problem that my last couple posts have discussed: how do we create objects, where, and how are we sure that they are valid?
In a lot of ways, OO brings the issue into much clearer focus because the old days of SI/SO, we would just say ‘well you have to make sure the data is good‘ v. in OO we can say ‘our abstraction must be whole.‘ So in other words, whereas in SQL we would say ‘we must block the door by implementing some set of constraints on the various effected tables,‘ in OO, we can say ‘an Address (example) is not valid unless it has a postal code, city, state, and a number and street.‘
While I love the idea of binding, and see it as the correct way to do ui framework‘s, JSF‘s approach to binding leaves some things to be desired, but none is as dire as the fact that any domain object that is bound in JSF must implement sets and gets for all of the properties that the user wants to make writeable. Now, the reason this is a problem is because it basically says: ‘go ahead, pin the entity layer to the ui, and if you want to constraint what gets constructed, you must do it through the validation/conversion facilities in the framework.‘ This translates as: ‘make all columns take nulls and empties and just cross your fingers that THE most untestable part of your application will be sufficiently secured through the diligence of all those who would expose a property through an interface component.‘ This is not the contract model of Meyer (DbC), but it‘s also not even the defensive model of McConnell, it‘s a strange hinterland in between where the most important phase of the development process (the generative problem: the making of things/entities), is not even left to chance, it‘s granted almost no importance, and leaves us in a world where the transmission of DNA is so willy nilly that we quite literally spawn mutants, saying to ourselves that we will fill in the chains after birth.
My first instinct on overcoming this was to cast it as a PAC v. MVC problem. The main advantages of PAC over MVC are the fact that it sees the ‘model‘ as hierarchical, and it makes provisions for the various components to have their own model needs that are independent of the domain model that is being transformed through the use of the ui. But PAC also opens the door to the idea that those intermediary abstractions (the A in PAC) could be used to create complete domain objects AFTER the edit session. In JSF, when the form is instantiated, for instance, to take a User‘s Address, a bean is made of Address, with all the fields empty (e.g. Street, City, State, etc.) and editing is commenced. Of course, you can create a validator, but again, what you are saying is that you can make the entity as a mutant and just not let the user out of the post-create infusion phase until certain constraints are satisfied. Using the PAC approach, we would make a bean called AddressInputAbstraction and then we would take all the components, and that component would be a builder of sorts, because it would have a getAddress method on it. The trick being that the get method would use the static builder in Address and so if the address was invalid, it would never get created in the first place.
Then the question becomes do we just make these Abstraction classes for each entity and we write out the mappings in the get method (a single line of code, given the syntax of the static builders), or is there some way that we could provide automatic mapping? Of course, the problem with the automatic approach is that many of the properties are going to be primitives, so you would have to rely on names, which would be sketchy at best. Of course, if JSF were able to have different ways of doing binding (other than just interpreting the expression as a property name that has a corresponding set), this would not be a problem: we could just map the builder properties directly. Another option would be to use annotations to provide the wiring, with the idea that only builder methods that were not simple mappings of name/method name would require additional metadata.
Ultimately, you just have to ask yourself the question: were all the AT&T folks like Andrew Koening, and now Josh Bloch in the Java realm onto something when they became increasingly obsessed with immutability, or are you happy to just live in the wild west where anything can be born, cars without wheels, human beings without brains (ok, bad example), etc. The other advantage of the PAC approach is that you can lock the domain classes so there really is no way for people working on the ui to take shortcuts or remove the protections against birth defects.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)