Skip to content

PmdRulesConstraints

Peter Kofler edited this page Feb 10, 2020 · 12 revisions

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 rule set.


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'  or @MethodName='compareTo' )
    ]

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. Allows implementing Runnable.

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, Comparable and Comparator.

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'  or @MethodName='compareTo' or
            @MethodName='run')
    ]

Example:

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

ImmutablesOnly

Deprecated

This rule has been renamed or moved. Use instead: ImmutablesOnly


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:

Name Default value 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:

Name Default value Description
lineMaxLen '80' Maximal length of lines

NoStaticFields

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

This rule is defined by the following XPath expression:

//FieldDeclaration[@Static='true']

Example:

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

NoStaticMethods

As an exercise no static methods are allowed. This fights the common mistake to have too many static methods.

This rule is defined by the following XPath expression:

//MethodDeclaration[@Static='true']

Example:

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

OnlyMapsAsParameters

According to POODR, use Maps as single argument in public API to make your code the most extensible without breaking callers because the API never changes. Also use default values in the Maps as much as possible.

This rule is defined by the following XPath expression:

//ConstructorDeclaration[
    @Public='true' and
    (
        FormalParameters[@ParameterCount > 1]  |
        FormalParameters/FormalParameter/Type/PrimitiveType  |
        FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[ not (@Image=$paramType) ]
    )
]
|
//MethodDeclaration[
    @Public='true' and
    not(@MethodName='equals' or @MethodName='compare' or @MethodName='compareTo' ) and
    (
        MethodDeclarator/FormalParameters[@ParameterCount > 1]  |
        MethodDeclarator/FormalParameters/FormalParameter/Type/PrimitiveType  |
        MethodDeclarator/FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[ not (@Image=$paramType) ]
    )
]

Example:

import java.util.Map;

public class Sandbox {
  public Sandbox(Map<?, ?> a) { } // public can only have Map
  public void run(Map<?, ?> a) { } // public can only have Map
  private void later(int i) { } // private can do anything
  public boolean equals(Object obj) { return false; } // equals is allowed
}

This rule has the following properties:

Name Default value Description
paramType 'Map' Simple name of the Map type allowed for public arguments