Clone wiki

pmd-rules / PmdRulesConstraints

Constraints

Special (likely controversial) rules for constraints in code katas, Coding Dojos and Code Retreats. See http://coderetreat.org/facilitating/activity-catalog Some less extreme rules like PrimitiveObsession or FirstClassCollections are located in the regular codecop.xml ruleset.


OnlyVoidMethods

As an exercise only void methods are allowed. This enforces Tell, Don't Ask design. Only inherited Object methods can be non-void.

This rule is defined by the following XPath expression:

//MethodDeclaration[ @Void='false' and
        not(@MethodName='hashCode' or @MethodName='equals' or
            @MethodName='toString' or @MethodName='clone' or
            @MethodName='compare')
    ]

Example:

public class Foo {
    public int nonVoidMethod(byte b){
        return 1;
    }
}

NoVoidMethods

As an exercise no void methods are allowed. This is the functional style. Only JUnit tests and custom asserts can have void methods.

This rule is defined by the following XPath expression:

//MethodDeclaration[ @Void='true' and
        not(../Annotation/MarkerAnnotation/Name[@Image='Test' or @Image='Before' or @Image='After']) and
        not(MethodDeclarator[@Image='run' or substring(@Image,1,6)='assert'])
    ]

Example:

public class BadClass {
    public void voidMethod(){
    }
}
public class OkClass {
    public int getIt(){
    }
}

NoLoops

As an exercise no loop constructs are allowed. You cannot use for, do or while.

This rule is defined by the following XPath expression:

//ForStatement | //WhileStatement | //DoStatement

Example:

public void main() {
    for (int i = 0; i < 3; i++) { }

    int i = 0;
    while (i < 3) { i++; }

    do { } while (false);
}

NoElseKeyword

As an exercise no else statement is allowed. This is rule 2 of Object Calisthenics.

This rule is defined by the following XPath expression:

//IfStatement[@Else='true']

Example:

public class Foo {
    public void main() {
        // ok, no else
        if (true) { }

        // bad, hase else
        if (false) { } else { }
    }
}

NoConditionals

As an exercise no conditional statements are allowed. You cannot use if, while, switch or ?:.

This rule is defined by the following XPath expression:

//IfStatement | //WhileStatement | //ConditionalExpression | //SwitchStatement

Example:

public class Foo {
    public void main() {
        if (true) {  }
        int i = true ? 1 : 2;
        switch(i) { case 0: break; }
        while(true) {  }
    }
}

NoGetterAndSetter

Do not use getter or setter to enforces encapsulation. This is rule 9 of Object Calisthenics.

This rule is defined by the following XPath expression:

//MethodDeclaration [
  @Synchronized='false' and
  count(Block/BlockStatement)=1 and
  (
     (
        MethodDeclarator/FormalParameters[count(FormalParameter)=1] and
        ResultType[count(Type)=0] and
        Block/BlockStatement/Statement/StatementExpression/Expression/PrimaryExpression[
           (count(PrimarySuffix/Arguments)=0) and
           (count(descendant::Expression)=0)
        ] and
        //AssignmentOperator[@Image='=']
     ) or (
        MethodDeclarator/FormalParameters[count(FormalParameter)=0] and
        ResultType/Type[count(ReferenceType)=1] and
        Block/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression[
           (count(PrimarySuffix/descendant::*)=0) and
           (count(descendant::Expression)=0) and
           (count(descendant::AllocationExpression)=0)
        ] and
        count(Block/BlockStatement/Statement/ReturnStatement)=1
     )
  )
]

Example:

class AvoidGetterAndSetterExample {
   String myVariable;
   void setMyVariable(String pMyVariable) {    // don't use
      myVarialbe = pMyVariable;
   }
   ...
   myVariable = "asdfasdf";
}

OnlyStaticMethods

As an exercise only static methods are allowed. This exaggerates the common mistake to have too many static methods. Only inherited Object methods can be non-static.

This rule is defined by the following XPath expression:

//MethodDeclaration[ @Static='false' and
        not(@MethodName='hashCode' or @MethodName='equals' or
            @MethodName='toString' or @MethodName='clone' or
            @MethodName='compare')
    ]

Example:

public class Foo {
    public int nonStaticMethod(byte b){
        return 1;
    }
}

ImmutablesOnly

Immutable data structures are easier to reason about and have no concurrency issues. Only final fields are allowed. (Mutable field references should be copied when passed in or out, but that is not checked.)

This rule is defined by the following XPath expression:

//FieldDeclaration[@Final='false']

Example:

public class SomeClass {
   private final String channel; // ok
   private boolean showIfSearchedInRegion; // not ok
}

OnlyStaticFields

As an exercise only static fields are allowed. This exaggerates the common mistake to have too many static fields.

This rule is defined by the following XPath expression:

//FieldDeclaration[@Static='false']

Example:

public class SomeClass {
   private String channel; // not ok
   private static boolean showIfSearchedInRegion; // ok
}

LooongIdentifiers

To enforce giving names meaningful names, every identifier shall be at least x characters. With x in the range of possibly 40. This forces people to let go of things like "num" or "i1" and "i2". This is part 1 of 20/80, see http://manynames.sevensuns.at/technojoy/2014/12/2080-a-coding-dojo-constraint-just-for-fun.html

This rule is defined by the following Java class: org.codecop.pmd.constraints.LooongIdentifiers

Example:

package possiblenextmovesreversi;

public class ReversiBoardPosition {
    private final int xCoordOfReversiBoard;
    private final int yCoordOfReversiBoard;

    public ReversiBoardPosition(int xCoordOfReversiBoard, int yCoordOfReversiBoard) {
        this.xCoordOfReversiBoard = xCoordOfReversiBoard;
        this.yCoordOfReversiBoard = yCoordOfReversiBoard;
    }
}

This rule has the following properties:

Heading NameHeading Default valueHeading Description
identifierMinLen'20'Minimal length of identifier names

ShortStatements

Keep statements (lines) short, so not many long identifiers can fit in. This is part 2 of 20/80, see http://manynames.sevensuns.at/technojoy/2014/12/2080-a-coding-dojo-constraint-just-for-fun.html

This rule is defined by the following XPath expression:

//BlockStatement[ (@SingleLine='false') or (number(@EndColumn)-number(@BeginColumn) > $lineMaxLen) ] |
//FieldDeclaration[ (@SingleLine='false') or (number(@EndColumn)-number(@BeginColumn) > $lineMaxLen) ] |
//MethodDeclarator[ (@SingleLine='false') or (number(@EndColumn)-number(@BeginColumn) > $lineMaxLen) ]

This rule has the following properties:

Heading NameHeading Default valueHeading Description
lineMaxLen'80'Maximal length of lines

Updated