Groups Images Directory Web
Recently Visited Groups | Help | Sign in
Google Groups Home
Group info
Members: 292
Language: English
Group categories:
Computers > Programming
More group info »
ADF Extreme Reusability    

Extreme Reusability

Extreme Reusability is an ADF development methodology for mid-sized teams (generally around 4-20 developers) originally laid out by Avrom Roy-Faderman in a two-part series of blog posts. More...

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. For example, consider the need to make a particular entity object use a package API, instead of standard DML opetations, to perform data. The Generalize, Push Up, and Customize technique can be used to address this problem:

  • The highly particular need is to replace an entity object's DML operations with calls to a specific package API.
  • This can be generalized to a need to write code that, based on an entity object's custom properties (and the custom properties of its attributes), can optionally replace an entity object's DML operations with calls to any package API.
  • The newly generalized code is pushed up into two custom framework classes: An entity definition class and an entity object class.
  • Then, specific entity objects can 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 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

This technique requires that an enterprise, even one that is not going the full-SOA route (with web services, the SOA Suite, and all that involves), gets out of the habit of thinking primarily in terms of applications and starts 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.

These services can be implemented as entire MVC "reusable applications", 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.

The Three Tracks

Development under Extreme Reusability involves developing along three separate but interacting (and communicating–communication is absolutely vital under this system) tracks: framework development, service development, and application development. These tracks are assigned to different individuals on the team, in somewhere around a 20-60-20 division for a typical organization’s needs.

The Framework Development Track

This is the track on which to put your Java developers, because this is the track which (among other things) is responsible for the vast majority–in the theoretical ideal, all–of your Java development. The framework track creates the stuff that is truly enterprise-wide: the stuff that *every* other developer is going to import into their applications. In particular, here’s what people on the framework track do:
  • Create ADF BC custom framework classes.
  • Create custom ADF BC validators (if you do model-level validation) and, if you have developers who are basically competent with Swing, customizers for those validators.
  • Create custom conroller classes (e.g., lifecycle changes, classes for managed beans, and so on).
  • Create custom Faces components (declarative or otherwise)
  • Implement an enterprise-wide LAF using skins.
  • Deploy as a library.
  • Receive and implement enhancement requests from the other tracks.
This is the track that needs to implement the “Generalize, Push Up” part of Generalize, Push Up, and Customize. When track developers receive an enhancement request (”I need to be able to use this package API instead of DML”), it is their responsibility to figure out how it might be generalized (”I need to be able to use any package API instead of DML”) in such a way that it can be declaratively customized (by setting properties on an entity object definition and its attributes).

The Service Development Track

This is probably where most developers will be working in a typical organization. These people develop “services,” not in the sense of true web services, but in the sense described in the principle "Think Globally, Deploy Locally." Not every application will use the services these developers create, but the idea is that the individual services may be combined and recombined to create a variety of applications. In particular, here’s what people on the service development track do:
  • Import the framework into all of their applications
  • Create libraries of entity object definitions (generally 1 library/schema)
  • Import these libraries into all of their applications that use the relevant schemas
  • Receive requests for particular services from the application development track
  • Create “data-only” services (i.e., services that require only service methods, not a UI) as libraries containing an application module and required view objects
  • Create “full” services (i.e., particular subtasks that involve a UI) as reusable task flows, including page fragments and business components
  • Request framework enhancements (anything requiring Java coding or a new LAF style) from the framework development track
When developers in this track receive a request for a custom service, they should first see if it can be composed from other existing services, and do so if possible. Otherwise, they need to consider if the service request can be generalized–made more reusable, allowing declarative customization by passing in parameters. The idea here, just as in SOA, is to develop a collection of services that have good potential for reuse across the enterprise.

The Application Development Track

Note that I’m suggesting that only about 20% of the developers actually need to be developing applications. That’s because applications, on this model, are largely just strings of composed services. The developers on this track need to do the following:
  • Import the framework into every application
  • Identify existing and new required services for the application
  • Request new services from the services track
  • Create an application module to manage the application’s transaction
  • Nest data-only service application modules in the main application module, or create shared instances of them, as appropriate
  • Create a “frame” ADF Faces page in which UI services can run
  • Create an unbounded task flow to string together services
  • Request framework enhancements (any new required Java code) from the framework track
  • Deploy the application as an EAR to a web server.
Note that, in a “pure” case (which may be an unreachable ideal, but the goal is to strive for it), application track developers won’t be developing entity objects, view objects, a real data model (as opposed to just a bunch of nested AM instances), pages (besides the “frame” page, which has few or no databound components), etc. Most of their work, actually, is just in identifying the services their application requires and working with the service development team to make sure the services work to spec.

Source Control

In most ways, this divided methodology actually makes source control easier. The relative granularity of the modules, and the assignment of particular developers to each module, makes merge conflicts far less likely.
On the other hand, precisely because of this granularity, some care needs to be taken to ensure that all developers are using the same versions of the libraries they share, and that changes to a set of libraries do not simply break working applications. This takes some care, but it really isn’t that difficult. Here are some tips:
  • Libraries should be deployed for incorporation to a central, networked location. Where practicable, developers should actually use the networked library in their applications. In some cases (e.g., remote developers over a slower connection with VPN encryption), this may not be practicable, so these developers should make a point to download the libraries each day. (This can, if desired, be done fairly easily with a single ANT script.)
  • Specifications are extremely important. In particular, framework developers need to create interfaces for all of their custom code, and these interfaces should lose methods, or change the function or signature of methods, only with appropriate deprecation time and careful communication with the other tracks (adding methods is rather lower-impact, so if you want to make, e.g., a signature change, just add it and deprecate the other one). Service developers need to maintain documentation to describe exactly what the inputs, outputs, and behavior of their services are, and break these contracts only after careful communication amongst themselves and with application developers.
  • Extreme Reuse makes unit testing relatively easy, because units of code are divided up quite well. You need to take advantage of this; continuous testing against established specs is critical.
Version: 
Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google