views:

1346

answers:

8

I just stumbled upon this article by Bruce Wallace:

Design Markers - Explicit Programming for the rest of us

Bruce describes a way to use interfaces to explicitly document things about your classes that can't otherwise be enforced in code.

Bruce's example: Immutable classes

Suppose you have a class that should be immutable. There is no immutable keyword in Java, so you can't document this fact directly in your code (or, for that matter, make the compiler enforce this requirement). In order to inform other developers working on your code that they shouldn't add setter methods to your class (in order to maintain the immutability requirement), you could define an empty interface named Immutable that relays this requirement to others working on the project:

public interface Immutable {}

Any classes that should be immutable then simply implement this interface:

public class UserRole implements Immutable {
...
}

This way, any other developers know right away that they shouldn't add setters to your class. The interface serves solely as a way to explicitly document this aspect of your class.

Another example: Internal framework code

Most frameworks contain at least a few classes that exist to support the internal operation of the framework and which normally should not be used directly by users of the framework. An Internal marker interface could explicitly identify such classes to end-users.

This also provides a good example for how design marker interfaces can help to organize JavaDoc documentation. The JavaDoc comments for Internal would explain that it is an interface implemented by classes meant for internal use only, and would provide a single point of reference for describing internal classes. This helps maintain the DRY principle: instead of repeating the same comment for every internal class, you can write the documentation once (in the Internal interface JavaDoc). Anything about internal classes that needs to documented at a later date can then be updated in a single place.

You also have the added benefit that all your Internal classes are listed in one place in your documentation - they will appear in the "All Known Implementing Classes" list in the JavaDoc for Internal.

Taking advantage of JavaDoc

This approach is meant to be used in combination with JavaDoc. For example, the JavaDoc for the Immutable marker interface can explain to developers that Immutable is a marker interface, and that it should be implemented by classes that are intended to remain immutable. As a side effect of adhering to this pattern, you can also browse the JavaDocs for your project and instantly see which classes are currently immutable, by seeing which classes implement the 'Immutable' marker interface.

What about design marker annotations?

The original article was written in 2003. Now that Java has annotation support, I could also see this same concept being implemented with annotations instead of interfaces: in fact, the @Deprecated annotation is a good example of Wallace's original idea. The @Deprecated annotation aids in the documentation of your code, rather than actually changing the behavior of your code. Annotations also give you the power to extend the "design marker" concept to individual methods in your classes.

I can see many interesting uses for this idea, especially the annotation-based variation of it: for example, an @Experimental annotation could be a very useful way to document features that are "in-progress" and more subject to change that other areas of the code base.

And now...my question

So, my question is this: Has anyone here applied Wallace's "design marker" concept to real-world projects? If so, did you find it useful? If not, why not?

I'd be very interested in what others think of this approach to documenting code, especially the annotations-based variation that I presented here.


EDIT: But what's the point???

David raises a valid concern: why bother with all this design marker interface stuff? As he says, "code should be code." After all, you could express the same requirements in a code comment. The design marker pattern seems to couple two different (although argubly related) concerns: it tightly binds documentation concerns to the code.

I've been playing devil's advocate in the comments, as I'm ambivalent about the usefulness/non-usefulness of the design marker pattern. However, to expand a bit on what I've been saying in the comments, I'm currently wondering if it's really such a bad thing to couple code to documentation a bit more tightly. After all, aren't most of us striving to write self-documenting code? In my mind, the design marker pattern seems like one way to achieve that goal, and even go beyond it. At the same time, I can see potential for abuse, and it would be less than helpful to try to work on a project that defined a design marker interface for every tiny little business rule or domain-specific concept.

I'm hoping the discussion picks up and we can get input from people on both sides of the issue. I'm interested to see what people have to say on this topic.

+10  A: 
David
Point taken. However, one proposed advantage of using an interface instead of a comment is that the JavaDoc generated for the Immutable class consolidates that comment in one location. You don't have to repeat the comment everywhere it's needed. Also, developers don't always read comments ;-)
Mike Spross
In addition, it's also immediately obvious which classes are immutable. When you view the JavaDoc page for Immutable, you can instantly see a list of all the classes that implement the Immutable interface. You get this documentation "for free" and don't have to manually fix it when the code changes.
Mike Spross
@Mike Spross And what is the value of such a list, I wonder ?
krosenvold
@krosenvold - It aids documentation. Instead of writing /* This class is immutable */ in each immutable class, your documentation is automatically updated when you add a new Immutable class, so you can't forget to add the note to your docs.
Mike Spross
@krosevnvold - Also, I suppose it could help with code reviews. If you have a list of all Immutable classes, you can easily check each one and make sure they are still immutable. If you didn't implement an interface, it would be harder to find/remember which classes are immutable.
Mike Spross
I'm not advocating this approach necessarily. It sees like it could be useful, but I also agree with Dave's point that it adds more code solely to aid the documentation process. But what about @Deprecated then? That's also a form of code documentation written directly into the code.
Mike Spross
I guess I don't really see too much of a difference between the "design marker" concept and the @Deprecated annotation. To me, @Deprecated could be seen as a specific instance of the more general "design marker" concept. You are documenting your code explicitly with more code (i.e. annotations).
Mike Spross
For that matter, an @Immutable annotation would really solve the problem!
David
+2  A: 

I believe that type declarations should accomplish something and be crafted in such a way to serve that end.

Your question is very well worded. I agree with your assertions that a) marker interfaces are mostly outmoded and b) annotations are a useful replacement for them.

I think part of what you want to use marker interfaces for is left unsaid.

Reading between the lines, it sounds like you are interested in providing an extra layer of documentation that is explicit and self-maintained. Looking more closely, it sounds like you want to provide some means of warning/protecting programmers from using/doing unsafe things.

If that is indeed what you are pursuing then I think AspectJ specifically - and aspect oriented programming (AOP) in general - will be quit intriguing to you.

Using aspects, you can declare a rule, basically, for when the compiler should produce a warning, where/what extra code to insert before/after/around things in your Java program, and so forth.

Aspects are annotation aware. So, an annotation can lend a guiding hand to your aspects.

One tradition of AOP in Java is to declare things consistently that you want to have handled consistently by aspect(s). In other words, use a common ending or start in the class name, implement common interface, use a common method name/signature, or these days even have a common annotation.

That you specify in your "pointcut". Then you write an "advice" to the compiler to put a common piece of code before, after, or around the code in question. The code weaves the code you specify to those places by changing the bytecode.

Generally, this is done by bytecode instrumenting the .class file(s). However, it can also be done strictly in memory using some Java implementations of AOP.

AspectJ was the original AOP tool and originally only supported the former method. I think Aspectwerkz and Spring framework support the latter technique.

It is usually best to wait to declare something until you need to do so. It is also best to name/organize things consistently from the get go.

If you are yearning for a little more control and order in your application (or system) then perhaps delving into AOP should be the next avenue of your investigation. Just keep in mind as you plan out what aspects you will write yourself, how to establish consistant naming conventions that will make it easy to specify a pointcut for the places in the program that need some extra code.

Also, be aware that AspectJ supports outputting warnings too if there are calls that violate some architectural rule of your application or whatnot. Swing calls from outside EDT is one popular thing for detecting - and then warning programmer about them.

JohnnySoftware
A: 

Immutability in general

Whenever I make an immutable object, it doesn't have any setters or getters, only one parametrized constructor and all fields are public like this:

public class ImmutablePerson {

    public final String firstName;
    public final String lastName;

    public ImmutablePerson(String firstName, String lastName) {
     this.firstName = firstName;
     this.lastName = lastName;
    }
}

The reasoning of course is that since firstName and lastName are immutable in this class, I can actually break the rule about not exposing inner members of class since they're immutable. Oh and this is something I only do in my personal projects since I don't think this is that much of a standard way to do immutable objects.

(overuse of this can lead up to code looking like person.home.address.city.getZipcode() which of course isn't necessarily desired)

Internal member methods/classes of a framework

I've seen both internalSomeMethod() and InternalClassName being used but none of these have been in interfaces/classes I'm supposed to interact with directly. I think it's enough of a warning that if you hit the magic word internal in any part of the external code you're using, you're most likely doing whatever you're trying to do wrong.

Your actual question

No, I don't. And neither does anyone else at my work, we've agreed that if we find it important to mention that something's immutable, we write it to the documentation of that class. We generally like to do things very coherently/OOP anyway and part of that is that marker interface pattern which this question really is about is that it doesn't really serve any actual purpose in traditional sense.

I wouldn't mind seeing an annotation for it but at the same time I don't feel the need for one either.

Esko
+2  A: 

You can use annotations to check immutability or other properties during compilation, see this article.

starblue
A: 

Let's put things in some order. Suppose that your class implements Immutable interface, which provides semantic to compiler or some tool invoked prior to compiler that the instance will be never changed, since it's creation. In order to ensure that, following preconditions should hold:

  1. All methods of a class, after the object is instantiated, will not assign value to its attributes, It is not necessarily means that we should not have setters, because any call to the method may have as side effect the modification of Immutable object state.

  2. All non-primitive attributes of a class should also be Immutable, either extending the Immutable interface or being immutable without such declaration (see Boolean, String, Long and other java.lang.* wrappers).

Then let's try to examine how the Immutability can be ensured. The first and mostly naive approach is to check for presence setters in our code, it can be done by finding the existence of set* pattern in our source code; and if pattern is found raise an exception. This partially ensures the first precondition.

Another more advance approach is to perform some kind of static analysis of the code, the data flow analysis. This approach may ensure that both of above preconditions are true, but still it is really difficult to implement robust version of such analiser.

My personal oppinion that the notion of interface should be preserved in it's context, in Java the interface is a set of method signatures and nothing more. If we wan't to use Interface for other purpose than original we break the language semantics, for example the Serializable marker interface is one of such cases - it is used for marking objects that can be serialized by JVM.

On the other hand it is useful to use marker interface as a type definition for some object that may combine various interfaces. Suppose a pipe-line where we process data each node of line accepts one value, modifies it and outputs it. Each node is simultaneously reader and writer, so the node can extend reader AND writer interfaces. Personally, I believe that this approach makes code more readable, and interface helps to explain some combined behaviors; and always without violating it's concept.

andreasmk2
A: 

I would guess that it is the case that any documentation provided in this way will be redundant.

At first I thought this would be a great idea, particularly because you could get consistent documentation on what exactly an immutable class is. So you could have one for a bean class, another for a delegate, one for each design pattern.

But part of design patterns is that they are supposed to be commonly recognized and agreed upon things. As a programmer, you should know what an immutable object is, so documenting it in an external interface defeats one of the points of design patterns.

Additionally, if you do a common task that is specific to your application, then you are probably better off packaging into a single place and then using delegation/inheritance. So if you follow "don't repeat yourself" then I don't think there is a need for this, as intriguing an idea as it is.

A: 

To me it comes down to three things: clearness, consistency, and tool support.

Relying only on documentation clearly does not meet any of these. A word such as immutable could appear in other contexts, the same concept can be expressed in different words, and it is very hard to support with tools (e.g., checkers that ensure you are not violating a property).

In that sense, markers are a decent solution - they are clear - if something implements the interface, you know what they mean. They are also generally consistent, at least if you get everyone on board to using them. Tool support is possible, but also becomes iffy, you've introduced noise into the type hierarchy.

Annotations are a better solution as you indicated - they are also clear and consistent, but they are easier to build tools around without getting the actual program to be as noisy.

Uri
A: 

Unless your code forces the behavior it represents then I'm not for it. Why? Someone else has to come after you to maintain it and they can break that "guarantee."

Case in point, this is what came after I had been put on a different project:

class GroundType 
{
public:
    GroundType(string _name, double _depthMeter, double _cost) :
        m_Name( _name ), m_DepthInMeter( _depthMeter ), m_Cost( _cost ) {}

    double    GetDepthMeter() const {return m_DepthMeter;}
    double    GetCost() const {return m_Cost;}
    double    GetUnitCost() const;
    string    GetName() const {return m_Name;}

    double dft;
    double air;
    int unitsDug;
    float value;

    void Calc();
private:

    double m_Cost;
    double m_DepthMeter;
    string m_Name;
};

Now, what would Immutable have done for that? They totally butchered my "immutable" data structure.

wheaties