Extreme Reusability, Part I

As promised, I’m posting of the presentation I’d been hoping to give at the OOW Unconference Methodology Symposium last week, expanded slightly for the more forgiving medium of a blog. As it turns out, it’s expanded substantially more than I thought, so I’m going to divide it into two parts. This week, I’ll talk about the basics of the methodology, its goals, and the two techniques it relies heavily upon. Next week, I’ll talk about the actual development process it specifies.

“Extreme Reusability” (the name is not mine, but rather Chris Muir’s; however, I decided I like it) is an idea for an ADF development methodology for mid-sized teams (generally around 4-20 developers) that I’ve been recently expanding on. I want to stress that that’s what it is–an idea. While I have used some of the practices involved in the methodology (and those have always worked out quite well) for parts of development work, many parts of the methodology require Oracle JDeveloper 11g, which is still not quite in production, so it’s not like I have a track record of 50 brilliantly successful applications developed using these methods. The usual legal stuff about holding me harmless if you try this and it doesn’t work out for you applies double here. Possibly even more important, I want your feedback. If you have reusability stories, or you’ve been trying to promote enterprise-wide reuse in your own applications (other than via true SOA; I want to keep this limited to web applications deployed in a traditional Java EE fashion for purposes of clean scope), drop me a line, post to the ADF Methodology group, or best of all, leave a comment.

Goals

The force behind Extreme Reusability is to get ADF applications making more use of the single biggest advantage of Java or any other object-oriented language: Reuse of code. ADF is, after all, a Java framework, and the fact that most ADF applications within most enterprises repeat code for the same tasks, over and over again, is a bit of a tragedy. No wonder so many of the ApEx people don’t get the point of JDeveloper and ADF–getting started with ADF is definitely harder than getting started with ApEx, and if you’re not going to use the power of an object-oriented framework (and you aren’t that freaked out about portability, which frankly most ADF users aren’t), there’s not much point.

There are, however, two goals of the project which, though subsidiary, are nonetheless quite important:

One of these goals is the facilitation of collaboration. Most ADF sample applications were written by one person, and their accompanying documentation/tutorials lays out a methodology that could reasonably be followed by a single person. This methodology is rarely ideal, however, for collaborating teams. Extreme Reusability is specifically a methodology for teams of programmers, intended to allow for productive and consistent collaboration.

The other goal is really a part of facilitating collaboration, but it deserves being called out. Ruby/Rails people are very fond of the idea of “Java by exception”–applications are supposed to be entirely declarative, exceptfor those few cases where declarative uses of the framework do not cover needed functionality. The idea is that you can harness the power of Java when you need it, and avoid the complexity at other times. At the ADF Methodology symposium, Steve Muench, very appropriately, pointed out that ADF, as well, is a “Java by exception” framework.

This is true, and this is one of the great powers of ADF. But the #1 rule of real enterprise applications–and this is true whether you’re using ADF Faces, Ruby/Rails, or any other Java by exception framework, is that there are always exceptions. Virtually any enterprise Java application, no matter how good its framework, is going to involve some Java coding at some point.

The thing is, the majority of shops that find these frameworks attractive don’t have huge numbers of Java programmers–heavy Java shops usually end up with a technology that involves much more direct contact with the code. Probably most developers on these teams will have their comfort zone in a 4GL development tool, such as forms. For these people, a JBE framework allows most development of a Java EE application to stay within that comfort zone, but there are always these exceptions, which, under a traditional methodology, require these 4GL developers to leave their comfort zone and learn Java, plus the 3GL elements of the framework (namely its API).

That’s really not a great situation, which is why the other subsidiary goal of Extreme Reusability is the isolation of Java coding. The idea here is that an organization is better off hiring 1-4 (depending on size) good Java programmers than training a team of 4-20 people who are experienced with 4GLs to be mediocre Java programmers. Those 1-4 Java programmers can be deployed to handle the exceptions, while everybody else takes care of the declarative cases.

Enabling Practices

Extreme Usability relies on two basic practices, both of which are a bit foreign to a beginning (or even intermediate) ADF developer:

Generalize, Push Up, and Customize

The essential idea of this practice is this: Rather than writing a piece of Java code tailored to a highly particular need, consider the possibility of generalizing the code and pushing it up the class hierarchy to a custom framework class, allowing declarative customization of specific cases.

I demonstrated an example of this practice in an earlier post:

  • The highly particular need was to replace an entity object’s DML operations with calls to a specific package API.
  • This was generalized to a need to write code that, based on an entity object’s custom properties (and the custom properties of its attributes), could optionally replace an entity object’s DML operations with calls to any package API.
  • The newly generalized code was pushed up into two custom framework classes: An entity definition class and an entity object class.
  • Then, specific entity objects could be declaratively customized by supplying the appropriate custom properties for the entity objects and their attributes.

Using this technique allows you to write (admittedly somewhat more complicated) code once, and ten apply 100%-declarative customization whenever a similar need comes up elsewhere in your enterprise, as opposed to writing similar code again and again. Like most attempts to architect for reusability, it’s a bit of extra up-front investment in exchange for a big payoff down the road.

Custom properties are the key to doing this with ADF BC. But don’t think you can’t use this technique in other layers of your application, because you can. For example, instead of solving a specific problem in a specific class for a specific managed bean, you can genericize the problem, solve it in a reusable class, and then customize it for specific managed beans using managed properties. People usually think of putting EL expressions in managed properties for customization scope-to-scope (that is, request-to-request, session-to-session, etc.), but you can just as easily put literals there for customization of a bean class bean-to-bean.

A closely related technique, which I don’t really want to give an entire section to, is “Generalize, Push Out, and Customize.” Rather than refactoring code up the hierarchy, you can often refactor it to a totally separate hierarchy (in object orientantionese, this is called the “Bridge” pattern) or even a utility (that is, a class with all static methods). For example, rather than implement a tricky bit of validation in an attribute setter or the validateEntity() method for an entity object class, you can abstract away from the particulars of the case and create a custom validator that performs attribute- or entity-level validations based on any number of declaratively customized properties. A bean class that provides common functionality across the framework can be added to each project as a bean and referred to at a variety of scopes. It’s not actually a Java class, but a single ADF Faces declarative component, template, or skin is very similar in spirit.

Think Globally, Deploy Locally

As I argued in SOA Without the S, mid-sized and larger enterprises, even those that aren’t going the full-SOA route (with web services, the SOA Suite, and all that involves) should be getting out of the habit of thinking primarily in terms of applications and should start thinking primarily in terms of developing a portfolio of services, reusable mini-applications that accomplish low-level tasks for what would traditionally be called an application. It’s not really SOA, since the services are deployed as libraries local to each application, rather than being single instances acting as global services to the enterprise, but the multiple instances share a single source, massively increasing reusability.

In the earlier blog post, I talked primarily about services that themselves had a view, controller, and model layer, but you can also create services with only a model to provide data without providing a UI (this, after all, is what many web services do). A business components project can be deployed as a business components library by itself, allowing other applications to nest the application module in their own (or create a shared instance of it) and access its data collections and services. You can even deploy a library of entity objects and associations alone, and think of these as providing “DML and business logic services” for a single schema to the view objects of multiple applications, or multiple reusable business component projects.

 

All of this talk of “goals” and “practices” is very well and good, but, some of you may be thinking, we haven’t gotten to an actual methodology yet. I know that, but this is all groundwork that needs to be laid before I actually outline a procedure for developing applications. Now that we’ve laid it, I’ll go through the procedure next week.