Design Markers: Explicit Programming for the Rest of Us

by Bruce Wallace
03/20/03

There are many choices made at software design time which cannot be directly expressed in today's implementation languages like C# and Java. These design choices (which are known by names like Design Patterns, Design Contracts, Refactorings, Effective Programming Idioms, Blueprints, etc.) must be implemented via programming & naming conventions because they go beyond the built-in functionality of production programming languages. The consequences of this limitation conspire over time to erode your wise investment in design as well as promoting a false segregation between a designer mindset and an implementer mindset.

The recognition of these problems and the same basic strategies for tackling them have been described by two recent independent proposals: Design Markers and the budding Explicit Programming movement. Until now, Explicit Programming has been linked to the use of an experimental Java research tool called ELIDE, but the proposed Design Markers technique requires only standard Java and JavaDoc. For those who must restrict themselves to production-ready tools, this article describes how you can use Design Markers, today, to provide many of the benefits of Explicit Programming.

Explicit Programming vs. Design Markers

Frankly, when I coined the terms Design Markers and Design Choices in the original Design Markers proposal, I had not yet heard of Explicit Programming and only later chanced upon its manifesto on the web. But, it was immediately obvious that both shared a strategy of coining a name for each design choice and explicitly referencing those names in program source code. The second leg of the strategy was to also embed in program source the description of how to implement each design choice.  Each "how-to" description is factored out to a well known place in the code. The coined name is the link between the many places in the code that reflect a particular design choice and its single implementation description. ELIDE calls these coined names modifiers and Design Markers calls them, well... design markers.

The significant difference between the two proposals is in the mechanism used to implement these modular "how-to" descriptions.  Design Markers have "plain language" descriptions intended to inform human programmers how to manually implement each choice (i.e. documentation). The ELIDE tool automates the generation of code to implement design choices because it defines Java language extensions that one uses to describe design choice implementations (think a cross between macro preprocessing and Aspect Oriented Programming). The tradeoff is implementation automation versus the use of (1) a still-evolving research tool (ELIDE), (2) its still-evolving language syntax, and (3) meta-programming (which is a different skill than normal programming).

There are also some finer grained differences between ELIDE and Design Markers with regard to what kinds of design contracts can be defined. Design Markers (being Java interfaces) are only attached to classes and interfaces, unlike ELIDE's ability to also attach modifiers to methods and even variables. On the other hand, ELIDE's contracts are not inherited by subclasses and thus it is more work to enforce a consistent "is-a" relationship between classes and their subclasses. Design markers are inherited.

However, the important benefits the two proposals still share are (1) preventing code from drifting away from adherence to its required design contracts, and (2) providing a trigger for design refactoring as code changes over time. These benefits are possible because the following items are in defined in the source code where developers are more likely to see them and more likely to keep them synchronized than is the case with traditional separate design documents. Items placed explicitly in implementation source code include:

What are Design Markers?

Design Markers are Marker Interfaces that are used primarily for documentation purposes and specifically to document Design Choices. The description of each design choice is placed in the JavaDoc comments of its associated marker interface in as much detail as desired. Design Markers (like all Java Interfaces) cause JavaDoc to generate hyperlinks back and forth between each marker definition and the definitions of each of its heirs, thus, navigation is trivial between the uses of a design concept and its definition.

I've coined the term Design Choices to encompass all flavors of design contracts because it emphasizes an oft forgotten fact that design is not a checklist of "best practices", but rather an interacting set of choices. These choices balance tradeoffs between competing design patterns that are made for the benefit of an entire system rather than isolated classes. These global tradeoffs are just the sort of knowledge that is lost or forgotten when developers are in the heat of refactoring particular classes.

Marker Interfaces are defined as those that have no details, only a name. This idea has long been used in Java via standard interfaces like Serializable, Clonable, RandomAccess, etc. However, their use has typically been limited to those interfaces intended to be explicitly verified at runtime (normally via "instanceof").

Design Markers, even though focused on documentation, share the root purpose of marker interfaces; namely, to declare adherence to a design contract whose implementation cannot be policed by the language compiler and runtime system. For example, just because a class declares "implements Serializable" doesn’t mean that it has correctly implemented the Serializable contract, but since Java can’t really tell if the contract has been met, using the marker interface is more of an explicit pledge by the programmer that it has. The overlooked benefit of marker interfaces is that they also document the intention that a contract should be met. Generalizing this notion to any design choice, Design Markers document the required obligations of a class and the reasons why.

For example, consider Data Transfer Objects (DTOs) that are passed as EJB remote method parameters. Since copies of these parameters are passed, rather than Java’s normal pass-by-reference, it is common to make them "immutable". Since one can’t simply declare classFoo to be immutable in Java, a series of conventions must be manually programmed. However, with a design marker, the requirement that a class should be immutable is a simple declaration (e.g. "class Foo implements Immutable").

Since interfaces in Java can inherit multiple parent interfaces, Design Markers benefit from being able to define higher level contracts in terms of lower level ones. So, to extend the above example, suppose for EJB method return values, an extra restriction is desired to prevent counterfeits. One could coin the term "consume-only" to mean "classes whose instances can be read-by but not created-by the user". A ConsumeOnly design marker interface is created to document that concept. Further, to codify the entire collection of contracts associated with return values, one could declare, "interface ReturnValue extends ConsumeOnly, Immutable" thus documenting both a new contract and its relation to other contracts. The JavaDoc for each design marker interface can document its definition, how it needs to be implemented, why it is done, etc. And instead of redundantly copying this info into the comments of each return value class (or leaving it undocumented altogether), each need only declare, "implements ReturnValue".

Finally, as a "best practice", I recommend making all design marker interfaces an extension of a single root level design marker (e.g. "interface Immutable extends Contract"). This has two benefits: (1) making a place to document the project’s practice of using Design Markers overall, and, (2) making it trivial, via JavaDoc, to get a hyperlinked catalog of all your defined contracts. New project members will love you.

Are Design Markers alone worth the effort?

Because programmers must use manually enforced programming conventions to implement design choices, they naturally need to be always cognizant of those design choices. However, without expensive round-trip design tools, or experimental research tools, "the blueprints" are not typically at hand.

So, as programmers refactor, they can make changes that are locally appropriate but globally inappropriate. Worse, the consequences of breaking a design contract may be not be a functionality failure, but instead a performance failure. Since unit tests focus on testing functionality much more than performance, these defects may not be discovered. In addition, even changes that improve the performance of an individual unit may, in fact, hurt the performance of the entire system. And this regression is even less likely to be caught because system level tests are done much less than unit tests. Preventing breaks is much better than trying to catch them later via testing. Having design markers, not only makes developers aware of pre-existing contracts, but provides a good trigger for design and/or code reviews. After all, changing a class's design markers is literally the same thing as changing its published interface.

So, why haven’t design choices traditionally been recorded in source code? Mostly, because there has been no clear place to put them. Even if each "typesafe enumeration" class had a comment noting that it followed that pattern, any elaboration (much less tutorial information) would not have been added because one either had to copy it repeatedly, or worse, place it sporadically in arbitrary spots. When creating the JavaDoc comments attached to each Design Marker interface, one can put more detail than typical because the comments do not need to be repeated anywhere else. Design Markers define a well-known place to factor out all those details and encourage including design documentation. JavaDoc automatically publishes all this in a form that makes it trivial to navigate from each use of a design pattern to that pattern’s central documentation and vice versa. This is especially useful for project-specific,  lesser known, or newly hatched patterns, idioms, conventions, etc.

Instead of creating actual marker interfaces, one might be tempted to invent and use custom JavaDoc tags (e.g. @Immutable, or @TypeSafeEnum). This approach is seemingly given encouragement with the new JDK 1.4 version of JavaDoc that allows simple command line parameters to make JavaDoc aware of invented tags. However, Design Markers have these advantages over custom JavaDoc tags:

Conclusion

According to its charter, Explicit Programming intends for its tools to be "widely accessible to programmers" and not "require a developer to understand language parsing to be able to define grammar extensions". It also states that "ELIDE tries to provide less power [relative to other techniques] with the intent of remaining more accessible to programmers". These tradeoffs are the same ones that Design Markers make relative to ELIDE itself. Design Markers represent a technique which occupies the optimal decision point between embracing the Explicit Programming style but only requiring tools and techniques available to all Java programmers today.

Finally, over time, as tools like ELIDE solidify and become production-ready, the design choices documented today by Design Markers will be ready and waiting to be converted to their use.

Examples

As a simple example of using Design Markers and illustrating the JavaDoc produced for them, Java source files, and all the JavaDoc generated for them, are available for viewing. Whether with JDK 1.3 or 1.4, the JavaDoc command used was simply "javadoc *.java".

References

Bruce Wallace as principal consultant of PolyGlot, Inc. since 1980, has provided consulting and custom computer software development services around the world. Projects have been completed in Sydney Australia, Perth West Australia, "Silicon Valley" California, "Route 128" Massachusetts, Austin Texas, and currently in Atlanta Georgia covering the full spectrum of roles from manual QA tester through CTO.