This is a draft AND a proposal. This, in no way, constitutes a document of how we're currently naming things. Rather, it's a proposal of where we'd like to go.
There are a bunch of places where our naming (classes, packages, ...) is rather inconsistent. This document proposes a convention, to be taken with a grain of salt, to attempt to consolidate our code base.
Whenever you feel unsatisfied with an existing name, or are writing new code, have a look here.
Project names
Modules & apps
...
Maven GroupIDs
...
ArtifactID
...
Source code repository name and location
...
Tags and branches
...
Packages
info.magnolia.cms.*
orinfo.magnolia.*
? : the discussion here is about whether the ".cms" subpackage is relevant. We started adding packages outside of it a while back, without much thinking about it. Now, we see how relevant it might have been - stuff under.cms
relates to the CMS product. Unfortunately, this thought is not consistent with reality. There are "generic" packages under.cms
, and there are product-specific packages outside..setup
subpackages are used for ModuleVersionHandler classes, tasks, etc.- Modules should not use
info.magnolia.module.x
, but useinfo.magnolia.x
instead. The former "clashes" with core'sinfo.magnolia.module
packages which contains ModuleManager and other base component of the module and version handling base systems.
How to choose a new package name
Now that the location of your new package is clarified, how should you name your package(s) ?
- Group by functionality (
.ui
) (.upload
), not by type (.dialogs)
, . Objects that "use" each other are packaged together. This allows for less public APIs, which in turns eases testability, maintenance and stability. - ? interfaces outside implementation packages (i.e
com.Foo
andcom.foos.SimpleFoo
,com.foos.ComplexFoo
)
Class names
There are usually good reasons to give a certain name to a class. Here we're attempting to clarify those reasons and provide some guidelines for consistency.
to be completed: in many cases, we're going to be referring to a known pattern. It would help to provide links to GoF pattern definitions (or other, more modern references, for example Martin Fowler's wiki).
Abstract, base, impl, default, ...
AbstractFoo
FooBase
FooSupport
FooImpl
: when you have an interface, implemented by this component, and there is no evidence that a different implementation will be needed.DefaultFoo
: when you have an interface, implemented by this component, and it is likely that different implementation could be needed for certain projects or tasks.
Also see http://blog.joda.org/2011/08/implementations-of-interfaces-prefixes.html
Factories, providers, ...
FooFactory
FooProvider
FooManager
FooAdapter
(this is perhaps PicoContainer-specific)
Strategies and policies
FooStrategy
FooPolicy
Other patterns
FooHandler
Modules
- Module configuration classes:
FooModule
vsFooConfiguration
vsFoo
Tests
Naming of the test classes
Unit Tests: Tests for a class should be placed in a class with the same name and the postfix Test. Like for FileSystemOrigin
there should be a FileSystemOriginTest
.
Naming of test cases
Try to use DAMP in tests, especially for test method names. Avoid tests like testFoo()
where foo()
is a method of the object under test. Try rather a pattern like fooDoesThisWhenThat()
(see the verb in there?). It highlights the expected behavior and the conditions of the test.
Note that we've been using JUnit 4 long enough, not to bother with the test prefix anymore (dear @Test
annotation). Do feel free to align this when touching an older test class; however avoid having a mix of both.
Here are some good and bad examples:
@Test registerForChangesTriggersCallbackForGivenPattern() @Test newResourcePathThrowsExceptionWhenGivenPathIsNotBelowRoot()
@Test testRegisterForChanges() @Test newResourcePathWithWrongRootPath()