Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

 

I highly encourage you to write down here all our coding conventions. From now on nobody will be able to say "how could I know?".

Most of them are highly debatable so feel free to discuss them or even prove them wrong.

Also, the thing is that you have to know the rules to be able to break them. Proper order of coding something should look like this:

  1. You consider doing it according to this conventions, assuming you fully understand them.
  2. If your common sense tells you it's not right, it probably isn't - do it your way.
  3. But don't leave it like that, talk about it, or even better update this page.

Mes specific conventions

Fields constants

Every time we add a new model field we should add it to the constants/PluginNameFields.java like this:

Code Block
public class PluginNameFields {
 
  public final static String ORDER = "order";
}  

So we won't repeat those string literals over and over when accessing entities fields. We're gonna use:

Code Block
entity.getBelongsToField(PluginNameFields.ORDER);

or even better:

Code Block
import static com.qcadoo.mes.pluginName.constants.PluginNameFields;
 
entity.getBelongstoField(ORDER);

I know it's something new, and refactoring the whole system will be a horror. Let's just use it from now on, ok?

 

Java enums

For every enum field of a model we create, we should create corresponding Java enum in constants package.

For ex.

Code Block
titleBatchNumberUniquness.java
public enum BatchNumberUniqueness {
 
  GLOBALLY("01globally"), MANUFACTURER("02manufacturer");

  private String stringValue;
 
  private BatchNumberUniqueness(final String stringValue) {
    this.stringValue = stringValue;
  }
  
  public String getStringValue() {
    return stringValue;
  }

  public static final BatchNumberUniqueness parseString(final String string) {
    if ("01globally".equals(string)) {
      return GLOBALLY;
    } else if ("02manufacturer".equals(string)) {
      return MANUFACTURER;
    } else {
      throw new IllegalStateException("Couldn't parse BatchNumberUniqueness from string");
    }
  }
}

 

Naming conventions

Naming literals:

EDIT: look at the mes specific convention about model field literals.

If the same string literal occurs more than once we extract it to a field like this:

Code Block
private static final String L_STRING_LITERAL = "stringLiteral"

I know it was STRING_LITERAL_L before, but that convention didn't work for magic numbers, also if you think about it, that L_ upfront tells you clearly what you deal with. That it's not a plugin specific constant nor enum.

Same thing holds for magic numbers:

Code Block
private static final int L_15 = 15;

 

Naming classes/packages:

If plugin name is "mes-plugins-awesome-plugin" the basic package is: com.qcadoo.mes.awesomePlugin, we can create some additional packages (and it's very rare when we should create anything else):

  • constants - we hold here classes like AwesomePluginConstants.java and maybe some model enums that are plugin specific.
  • hooks - model and view hooks like: ViewNameViewHooks.java, ModelNameHooks.java
  • validators - model validators like: ModelNameValidators.java, SomeOtherModelNameValidators.java
  • listeners - view listeners like: ViewNameListeners.java
  • states - if there is some logic regarding model states (I consider enum state model field as something that common to write it here), for ex. ModelNameStatesService.java
  • workPlansColumnExtensionhttp://wiki.qcadoo.org/display/QCDMESDOC/WorkPlans+column+extension

We add PluginName prefix only to classes that are meant to be used outside this plugin - things like: AwesomePluginConstants.java, AwesomePluginService.java.

Coding style conventions

Single line for or if statements:

Even if they are single commands, that you are sure won't grow bigger, we enclose it in { } brackets - always.

BAD

Code Block
if (condition)
  doSomething(); 

GOOD

Code Block
if (condition) {
  doSomething();
}  

 

We initiate objects, especially Lists (local - non field) upon creation:

Because if we won't we are in risk to letting them remain null.

BAD

Code Block
String name;

if (condition) {
  name = "Michael";
}  
Code Block
List<Entity> customers;

if (condition) {
   customers = loadCustomers();
}    

 

GOOD

Code Block
String name = "Name not available";

if (condition) {
  name = "Michael";
}    
Code Block
List<Entity> customers = new LinkedList<Entity>();

if (condition) {
  customers = loadCustomers();
}    

 

If we are dealing with 2 state enum kind of option we don't make the other option fall into simple else block.

Because number of states can change over time. The code where all different states fall into else block won't tell you anything, will just remain broken, silently.

This also applies to any options, not just model enums.

BAD

Code Block
// state is either 01draft or 02accepted
 
if ("01draft".equals(state)) {
  doSomething();
} else {
  doSomethingDifferent();
}   

 

GOOD

Code Block
// state is either 01draft or 02accepted

if ("01draft".equals(state)) {
  doSomething();
} else if ("02accepted".equals(state)) {
  doSomethingDifferent();
} else {
  throw new IllegalStateException("state is neither 01draft nor 02accepted");
}