This session's goals are to:
- To detail the "ROO" DDD architecture
- To show you how productive ROO can be
- To profile an Australian project using ROO
ROO is more of an implementation than an architecture. So what is ROO? It's not an Australian marsupial or an Australian airline. It's a Domain-Driven Design (DDD) implementation.
Real Object Oriented (ROO) is both an architectural approach and a framework with code generation. ROO uses 4 (UI, middle-tier, domain model and persistence) layers instead of 3. Most of of the code is in the domain model. In the persistence layer, most DAOs only differ in finder methods. Rather than DAOs, "Repositories" (from DDD) are used.
Since most of the code is in the middle-tier DO layer (including business), the middle-tier is primarily used to "export" interfaces for remoting, the middle-tier facade and DTOs. Almost all of the interfaces in the ROO architecture are generated or require trivial coding.
Compare ROO to Traditional Approach (normal way people develop with Spring).
- Transparent persistence usually not used , it is in ROO
- Persistence layer name: DAO, Repository in ROO
- Finder method location: DAO, Finders in ROO
- State integrity: None, DO layer in ROO
- Business logic: Service Layer, DO Layer in ROO
- Form backing objects: "DO" layer, DTO layer in ROO
- DO and SL pattern names: Misused, Correct in ROO
ROO uses more layers and types than traditional Java. Traditional Java isn’t a fair comparison (patterns are not very OO, and can be less efficient). Ben believes the ROO approach is justifiable for 3 reasons:
- Layers have well-defined purpose (OO justification)
- Types mostly auto-generated (efficiency justification)
- Architecture uses patterns (precedence justification)
Patterns used in ROO:
- Domain Object (“DO”)
- Data Transfer Object (“DTO”)
- DTO Assembler
There are many problem with code generation, but quality code generation is attainable.
How is ROO different from other things?
It was designed to scratch an itch. Ben wrote it because he was tired of writing code using the same old architecture patterns. He didn't write it because he wanted to start another open source project. It was also designed to scratch other people's itch (do we really need the service layer?). ROO is founded on a few philosophies: domain first, infrastructure 2nd, convention over configuration, embrace OO and modern capabilities.
Ben is now doing a video demo of ROO. In the video, he's created a project using a Maven 2 archetype (I've seen this used a lot at this conference) and imported it into Eclipse. From there, he creates Entity classes and shows how Eclipse generates Hibernate mapping files and DTOs (as well as tests) for the entities. The one pain (currently) is you do have to copy the generated mapping files back into your classpath. Most of the POJOs that Ben is creating for his domain model extend some ROO parent classes (i.e. AbstractDomainObjectLong). While he does write getters in these classes, he only provides setters for those fields that can change. Then he creates a public constructor that contains the required fields.
It looks like Ben has wired up some sort of external tool (or maybe a Maven plugin) to do the code generation. Later I found out it's Java class that's merely run from Eclipse or Maven. ROO is Java 1.3 compatible.
For the tests that ROO generates, it creates abstract methods for any business logic methods that need testing. It's then up to you to subclass this test and implement the abstract test method. ROO also seems to generate population classes that populate your database for tests. I don't know how it figures out sample address information, but I'm assuming this data somehow existed in the Maven archetype.
To create Finders with ROO, you implement a FinderSpecification class and implement a public FinderDetails getFinderDetails() method. The code in this method is more like EasyMock's API than Hibernate's Criteria API.
For the code generation, the life of a type is very important. Not only are types created initially, they're updated when you touch them. Some class are generated as Abstract classes when they need you to provide additional information.
ROO generates custom finders, classes, and the Spring XML. It does not generate Hibernate User Type interfaces, but it does generate classes for user types. It generates DTOs, middle-tier facades, classes and Spring XML. It also generates test data and tests for all the generated code.
Ben just did a survey of the room asking who's using Ant vs. Maven. Surprisingly, Ant only slightly beats Maven.
Persistence in ROO
- Think of them as DAOs with transparent persistence
- Transparent persistence engine is essential
- Domain objects always attached to unit of work (UoW)
- Persistence layer may be injected into domain objects (although mostly finder types will be injected, not repositories)
- Persistence layer is unaware of DTOs
- Global, shared repository
- Transparent persistence, API agnostic interface
- Method naming convention (read*, find* and make*)
- Some methods exported to middle tier facade
Typically fine grained and domain object specific
- public User findUserBySurname(String surname) )
- Easy to dynamically mock and DI
- Returns domain objects attached to UoW
- ROO generates finder via criteria-like API
Middle Tier Exporting
- Repository contributes its read* methods to facade
- Finders contribute all methods
- Facades returns DTOs
- Not domain objects
- Conversion via DTO Assembler
- DTOs are normal JavaBeans
- DTOs lack lazy loading semantics
- Most of your work and code occurs in domain objects
- Domain objects are your only 1st class citizens
- Code generation is mostly driven by domain objects
- DI is certainly possible
- Fully encapsulated
- Distinguish state managed fields
- Persistence layer uses field-level access
- Public constructors reflect mandatory fields
For the DTO Assembler in ROO, they use Dozer. Initially, they had a fair amount of issues with it, but the latest releases have solved all of those.
In addition to the code generation for DTOs, Facades, etc., ROO generates middle-tier metadata that's all available via JMX. There is enough information provided by this metadata to build a Naked Objects implementation (or possibly even a web UI).
Interestingly enough - it looks like the Maven archetype for this project is able to manipulate the launchers and external tools that are configured in Eclipse. I confirmed with Ben afterwards that Maven's archetypes (or maybe it's the Eclipse plugin) are capable of configuring Eclipse's launcher configurations.
Woolworths in Australia (not the same as Woolworths in the US) is using this system. They've used ROO on 3 different projects, from simple to very complex projects. For the complex project, ROO had to add support for composite primary keys. Many of the issues ROO had with Dozer were fixed and contributed back to the project by Woolworth's developers.
ROO looks like a pretty cool system. It reminds me a lot of Grails' GORM except that it requires more tooling. Ben said most of the code generation is driven by a Java class. I wonder if it has templates (i.e. FreeMarker) that can be modified? If ROO ever becomes an open source project, I'm guessing it will be very polished and well-received. I'm sure we could use ROO in AppFuse and make a lot of Java developers very happy.