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

  • (question) info.magnolia.cms.* or info.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 use info.magnolia.x instead. The former "clashes" with core's info.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 and com.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.
(warning) 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 vs FooConfiguration vs Foo

 

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:

GOOD
@Test
registerForChangesTriggersCallbackForGivenPattern()

@Test
newResourcePathThrowsExceptionWhenGivenPathIsNotBelowRoot()
BAD
@Test
testRegisterForChanges()

@Test
newResourcePathWithWrongRootPath()

 

 

 


  • No labels