Stagean annotations
Stagean is a Java library of annotation types that let you document development stage of your project on class or method level. Hand-edited Stagean annotations complement automated coverage and analysis tools to create overall picture of project's state and progress.
Example
In the example below, @NoDocs
, @DraftTests
,
and @StubCode
are development stage annotations.
They inform developers and users about development stages reached by this particular class and method.
@NoDocs
@DraftTests("async scenarios are untested")
public class MyClass {
@StubCode
public void doSomething() {
throw new UnsupportedOperationException();
}
// ...
}
Download
Get Stagean from Maven Central:
<dependency>
<groupId>com.machinezoo.stagean</groupId>
<artifactId>stagean</artifactId>
<version>1.0.2</version>
</dependency>
Or clone sources from GitHub or Bitbucket. Don't forget to configure your build for Java 8+. Sources and binaries are distributed under Apache License 2.0.
Available annotations
All annotations currently defined by Stagean are arranged in the table below. Stagean recognizes four different development stages that can be assigned to four different content types.
No* |
Stub* |
Draft* |
Complete* |
|
---|---|---|---|---|
*Api |
@StubApi |
@DraftApi |
@CompleteApi |
|
*Code |
@StubCode |
@DraftCode |
@CompleteCode |
|
*Tests |
@NoTests |
@StubTests |
@DraftTests |
@CompleteTests |
*Docs |
@NoDocs |
@StubDocs |
@DraftDocs |
@CompleteDocs |
Annotations NoApi
and NoCode
do not exist, because they don't have any meaning.
Use @StubApi
and @StubCode
instead.
Applications and libraries are free to define their own annotations,
but the annotations defined by Stagean are expected to have the best support in scanning and reporting tools.
How to track project progress
Common approaches that existed before Stagean:
- Mark whole project with overall development stage.
This is the well-known alpha/beta/... classification. This approach fails in projects that have stable core surrounded by experimental extensions, a very common scenario in opensource libraries. - Have separate experimental packages.
This causes breaking changes when classes mature and it doesn't work for experimental methods and nested classes. - Flag experimental code in Javadoc.
This often takes the form of a very visible "(EXPERIMENTAL)" banner in class summary. This is a very flexible solution, but it's informal, which hinders development of reporting tools. - Use coverage tools.
This works well for missing tests and docs, less so for ineffective tests and quick-n-dirty docs, and not at all for unstable APIs and incomplete implementations.
All of the above solutions still apply. Stagean just adds another tool to your toolbox:
- Add Stagean annotations.
Annotations capture developer's understanding of code quality. They are visible in code and in javadoc. Regex search will reliably find them. Tools can be developed to scan for them and create reports.
Development stages
Stagean recognizes four development stages:
@No*
Used when given type of content does not exist at all, e.g.@NoDocs
if there's no javadoc yet. This is perfectly unambiguous and the bare annotation without further comments is usually enough.@Stub*
Stub is a dummy placeholder. For example,@StubCode
indicates the implementation just throwsUnsupportedOperationException
or does something similarly trivial. The work is still 0% done, but@No*
annotation is not applicable, because something technically already exists. Stubs may contain some minimal content. For example,@StubDocs
javadoc would include the required summary sentence.@Draft*
Draft content needs more work. The annotation doesn't say how much. It could mean the work is 5% done or 95% done. Annotation's parameter or nearby comments should summarize what is unfinished.@Complete*
Indicates that this type of content is perfect, i.e. no changes are needed. The work is 100% done. There is a bit of ambiguity in what you consider "done", but generally it means you have no TODOs left.
@Draft*
stage is deliberately broad to minimize ambiguity and to avoid wasteful tinkering with annotations.
Some ambiguity might arise at its extremes with @Stub*
near 0% and with @Complete*
near 100%.
Criteria for @Stub*
and @Complete*
are somewhat project-specific.
If in doubt, use @Draft*
annotation.
// BAD: Abusing stub for working code.
@StubCode("switch to front crawl, improve speed") // DON'T DO THIS
void swim() {
// ...
}
// GOOD: Any non-placeholder implementation, even simple one, is a draft.
@DraftCode("switch to front crawl, improve speed")
void swim() {
// ...
}
// GOOD: Appropriate use of stub annotation for do-nothing implementation.
@StubCode
void swim() {
logger.warn("Swimming is not implemented yet.");
}
@Complete*
stage is the default when no annotation is present.
You can use it anyway for clarity, but the advantage of omitting it is that
Stagean annotations will add overhead only in unfinished code.
// BAD: If there are TODOs, it is not done yet.
@CompleteCode("just improve performance")
class MyClass {
// ...
}
// OKAY: Redundant but technically correct.
@CompleteCode
class MyClass {
// ...
}
// BEST: No need to annotate finished code.
class MyClass {
// ...
}
Target content
Stagean currently supports flagging of these kinds of content:
@*Api
Applies to API, which usually means signature and behavior of public types and members.@*Code
Applies to implementation, i.e. everything behind the API.@*Tests
Applies to tests, usually unit tests. This annotation should be applied to code under test. It can be also informatively applied to test code itself, but scanning tools will likely ignore annotations on test code.@*Docs
Applies to javadoc and perhaps related external docs.
Comments
Annotations other than @Draft*
are unambiguous. They don't need further comment.
@Draft*
stage, on the other hand, is very broad.
The annotation needs a summary of what needs to be done in order to reach @Complete*
stage.
Short comment will fit in annotation's parameter. Longer comment can be left above the annotation.
// BAD: No information about what needs to be improved.
@DraftCode
class MyClass {
// ...
}
// GOOD: Annotation's parameter lists remaining issues.
@DraftCode("no exception handling, O(N*N) complexity")
class MyClass {
// ...
}
// GOOD: Parameter summarizes issues and surrounding comments add details.
/*
* Required performance improvements:
* - set operations: O(NlogN)
* - search methods: O(logN)
* - editing methods: O(logN)
*/
@DraftCode("suboptimal performance")
class MyClass {
// ...
}
Cascading
Annotations cascade to nested language constructs. For example, package annotations also apply to all types in the package and type annotations also apply to all members of the type.
@DraftCode("no logging or metrics")
class MyClass {
@StubCode
void doSomething() {
throw new UnsupportedOperationException();
}
void orOther() {
// ...
}
// ...
}
In the above example, all methods inherit @DraftCode
annotation from MyClass
except method doSomething()
that has overriding local annotation @StubCode
.
Cascading of @StubDocs
and @StubTests
is an exception.
If there are any nested constructs, @Stub*
cascades to them as
@NoDocs
and @NoTests
respectively.
Contribute
Stagean was developed by Robert Važan. If you have any suggestions, including requests for documentation, report an issue (GitHub, Bitbucket) or submit a pull request (GitHub, Bitbucket). You can reach the author via email .