11 January 2018

Compliance with Object Calisthenics

During my work as Code Cop I run many workshops. Sometimes I use constraints to make exercises more focused or more intense. Some constraints, like the Brutal Coding Constraints, are composite or aggregate constraints, which means that they are a combination of several simpler or low level constraints. (Here simple does not mean that they are easy to follow, rather that they focus on a single thing.) Today I want to discuss Object Calisthenics.

some warmup calisthenicsObject Calisthenics
Jeff Bay's Object Calisthenics is an aggregate constraint combined of the following nine rules:
  1. Use only one level of indentation per method.
  2. Don't use the else keyword.
  3. Wrap all primitives and strings (in public API).
  4. Use only one dot per line.
  5. Don't abbreviate (long names).
  6. Keep all entities small.
  7. Don't use any classes with more than two instance variables.
  8. Use first-class collections.
  9. Don't use any getters/setters/properties.
If you are not familiar with these rules, I recommend you read Jeff Bay's original essay published in the The ThoughtWorks Anthology in 2008. William Durand's post is an exact copy of that essay, so no need to buy the book for that. Several people have followed up and discussed their interpretation and experience with Object Calisthenics, e.g. Mark Needham, Jeff Pace, Vasiliki Vockin and Juan Antonio.

Object Calisthenics is an exercise in object orientation. How is that? One of the core concepts of OOP is Abstraction: A class should capture one and only one key abstraction. Obviously primitive and built-in types lack abstraction. Wrapping primitives (rule #3) and wrapping collections (rule #8) drive the code towards more abstractions. Small entities (rule #6) help to keep our abstractions focused.

Further objects are defined by what they do, not what they contain. All data must be hidden within its class. This is Encapsulation. Rule #9, No Properties, forces you to stay away from accessing the fields from outside of the class.

Next to Abstraction and Encapsulation, these nine rules help Loose Coupling and High Cohesion. Loose Coupling is achieved by minimizing the number of messages sent between a class and its collaborator. Rule #4, One Dot Per Line, reduces the coupling introduced by a single line. This rule is misleading, because what Jeff really meant was the Law Of Demeter. The law is not about counting dots per line, it is about dependencies: "Only talk to your immediate friends." Sometimes even a single dot in a line will violate the law.

High Cohesion means that related data and behaviour should be in one place. This means that most of the methods defined on a class should use most of the data members most of the time. Rule #5, Don't Abbreviate, addresses this: When a name of a field or method gets long and we wish to shorten it, obviously the enclosing scope does not provide enough context for the name, which means that the element is not cohesive with the other elements of the class. We need another class to provide the missing context. Next to naming, small entities (rule #6) have a higher probability of being cohesive because there are less fields and methods. Limiting the number of instance variables (rule #7) also keeps cohesion high.

The remaining rules #1 and #2, One Level Of Indentation and No else aim to make the code simpler by avoiding nested code constructs. After all who wants to be a PHP Street Fighter. ;-)

Checking Code for Compliance with Object Calisthenics
When facilitating coding exercises with composite constraints, I noticed how easy it is to overlook certain violations. We are used to conditionals or dereferencing pointers that we might not notice them when reading code. Some rules like the Law Of Demeter or a maximum size of classes need a detailed inspection of the code to verify. To check Java code for compliance with Object Calisthenics I use PMD. PMD contains several rules we can use:
  • Rule java/coupling.xml/LawOfDemeter for rule #4.
  • Rule #6 can be checked with NcssTypeCount. A NCSS count of 30 is usually around 50 lines of code.
    <rule ref="rulesets/java/codesize.xml/NcssTypeCount">
        <properties>
            <property name="minimum" value="30" />
        </properties>
    </rule>
  • And there is TooManyFields for rule #7.
    <rule ref="rulesets/java/codesize.xml/TooManyFields">
        <properties>
            <property name="maxfields" value="2" />
        </properties>
    </rule>
I work a lot with PMD and have created custom rules in the past. I added rules for Object Calisthenics. At the moment, my Custom PMD Rules contain a rule set file object-calisthenics.xml with these rules:
  • java/constraints.xml/NoElseKeyword is very simple. All else keywords are flagged by the XPath expression //IfStatement[@Else='true'].
  • java/codecop.xml/FirstClassCollections looks for fields of known collection types and then checks the number of fields.
  • java/codecop.xml/OneLevelOfIntention
  • java/constraints.xml/NoGetterAndSetter needs a more elaborate XPath expression. It is checking MethodDeclarator and its inner Block/ BlockStatement/ Statement/ StatementExpression/ Expression/ PrimaryExpressions.
  • java/codecop.xml/PrimitiveObsession is implemented in code. It checks PMD's ASTConstructorDeclaration and ASTMethodDeclaration for primitive parameters and return types.
For the nitty-gritty details of all the rules have a look at codecop.xml and constraints.xml.

AutomaticInterpretation of Rules: Indentation
When I read Jeff Bay's original essay, the rules were clear. At least I thought so. Verifying them automatically showed some areas where different interpretations are possible. Different people see Object Calisthenics in different ways. In comparison, the Object Calisthenics rules for PHP_CodeSniffer implement One Level Of Indentation by allowing a nesting of one. For example there can be conditionals and there can be loops, but no conditional inside of a loop. So the code is either formatted at method level or indented one level deep. My PMD rule is more strict: Either there is no indentation - no conditional, no loop - or everything is indented once: for example, if there is a loop, than the whole method body must be inside this loop. This does not allow more than one conditional or loop per method. My rule follows Jeff's idea that each method does exactly one thing. Of course, I like my strict version, while my friend Aki Salmi said that I went to far as it is more like Zero Level Of Indentation. Probably he is right and I will recreate this rule and keep the Zero Level Of Indentation for the (upcoming) Brutal version of Object Calisthenics. ;-)

Wrap All Primitives
There is no PHP_CodeSniffer rule for that, as Tomas Votruba considers it "too strict, vague or annoying". Indeed, this rule is very annoying if you use primitives all the way and your only data structure is an associative array or hash map. All containers like java.util.List, Set or Map are considered primitive as well. Samir Talwar said that every type that was not written by yourself is primitive because it is not from your domain. This prohibits the direct usage of Files and URLs to name a few, but let's not go there. (Read more about the issue of primitives in one of my older posts.)

My rule allows primitive values in constructors as well as getters to implement the classic Value Object pattern. (The rule's implementation is simplistic and it is possible to cheat by passing primitives to constructors. And the getters will be flagged by rule #9, so no use for them in Object Calisthenics anyway.)

I agree with Tomas that this rule is too strict, because there is no point in wrapping primitive payloads, e.g. strings that are only displayed to the user and not acted on by the system. These will be false positives. There are certain methods with primitives in their signatures like equals and hashCode that are required by Java. Further we might have plain numbers in our domain or we use indexing of some sort, both will be false positives, too.

One Dot Per Line
As I said before, I use PMD's LawOfDemeter to verify rule #4. The law allows sending messages to objects that are
  • the immediate parts of this or
  • the arguments of the current method or
  • objects created inside the current method or
  • objects in global variables.
I did not look at PMD's source code to check the implementation of this rule - but it complains a lot. For me this is the most difficult rule of all nine rules. (I code according to #1, #3, #5 and #6 and can easily adapt to strictly follow #2, #7, #8 and #9.) Although it complains a lot, I found every violation correct. I learned much about Law Of Demeter by checking my code for violations. For example, calling methods on an element of an array is a violation. The indexed array access is similar to a pointer access. (In Ruby this is obvious because Array defines a method def [](index).) Another interesting fact is that (at least in PMD) the law flags calling methods on enums. The enum instances are not created locally, so we cannot send them messages. On the other hand, an enum is a global variable, so maybe it should be allowed to call methods on it.

The PHP_CodeSniffer rule follows the rule's name and checks that there is only one dot per line. This creates better code, because train wrecks will be split into explaining variables which make debugging easier. Also Tomas is checking for known fluent interfaces. Fluent interfaces - by definition - look like they are violating the Law Of Demeter. As long as the fluent interface returns the same instance, as for example basic builders do, there is no violation. When following a more relaxed version of the law, the Class Version of Law Of Demeter, than different implementations of the same type are still possible. The Java Stream API, where many calls return a new Stream instance of a different class - or the same class with a different generic type - is likely to violate the law. It does not matter. Fluent interfaces are designed to improve readability of code. Law Of Demeter violations in fluent interfaces are false positives.

Don't Abbreviate
I found it difficult to check for abbreviations, so rule #5 is not enforced. I thought of implementing this rule using a dictionary, but that is prone to false positives as the dictionary cannot contain all terms from all domains we create software for. The PHP_CodeSniffer rules check for names shorter than three characters and allow certain exceptions like id. This is a good start but is not catching all abbreviations, especially as the need to abbreviate arises from long names. Another option would be to analyse the name for its camel case patterns, requiring all names to contain lowercase characters between the uppercase ones. This would flag acronyms like ID or URL but no real abbreviations like usr or loc.

Small Entities
Small is relative. Different people use different limits depending on programming language. Jeff Bay's 50 lines work well for Java. Rafael Dohms proposes to use 200 lines for PHP. PHP_CodeSniffer checks function length and number of methods per class, too. Fabian Schwarz-Fritz limits packages to ten classes. All these additional rules follow Jeff Bay's original idea and I will add them to the rule set in the future.

Two Instance Variables
Allowing only two instance variables seems arbitrary - why not have three or five. Some people have changed the rules to allow five fields. I do not see how the choice of language makes a difference. Two is the smallest number that allows composition of object trees.

In PHP_CodeSniffer there is no rule for this because the number depends on the "individual domain of each project". When an entity or value object consists of three or more equal parts, the rule will flag the code but there is no problem. For example, a class BoundingBox might contain four fields top, left, bottom, right. Depending on the values, introducing a new wrapper class Coordinate to reduce these fields to topLeft and bottomRight might make sense.

No Properties
My PMD rule finds methods that return an instance field (a getter) or update it (a setter). PHP_CodeSniffer checks for methods using the typical naming conventions. It further forbids the usage of public fields, which is a great idea. As we wrapped all primitives (rule #3) and we have no getters, we can never check their values. So how do we create state based tests? Mark Needham has discussed "whether we should implement equals and hashCode methods on objects just so that we can test their equality. My general feeling is that this is fine although it has been pointed out to me that doing this is actually adding production code just for a test and should be avoided unless we need to put the object into a HashMap or HashSet."

From what I have seen, most object oriented developers struggle with that constraint. Getters and setters are very ingrained. In fact some people have dropped that constraint from Object Calisthenics. There are several ways to live without accessors. Samir Talwar has written why avoiding Getters, Setters and Properties is such a powerful mind shift.

Java Project Setup
I created two repositories containing starting points for the LCD Numbers and Minesweeper Kata:Both are Apache Maven projects. The projects are set up to check the code using the Maven PMD Plugin on each test execution. Here is the relevant snippet from the pom.xml:
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-pmd-plugin</artifactId>
      <version>3.7</version>
      <configuration>
        <printFailingErrors>true</printFailingErrors>
        <linkXRef>false</linkXRef>
        <typeResolution>true</typeResolution>
        <targetJdk>1.8</targetJdk>
        <sourceEncoding>${encoding}</sourceEncoding>
        <includeTests>true</includeTests>
        <rulesets>
          <ruleset>/rulesets/java/object-calisthenics.xml</ruleset>
        </rulesets>
      </configuration>
      <executions>
        <execution>
          <phase>test</phase>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
      <dependencies>
        <dependency>
          <groupId>org.codecop</groupId>
          <artifactId>pmd-rules</artifactId>
          <version>1.2.3</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>
You can add this snippet to any Maven project and enjoy Object Calisthenics. The Jar file of pmd-rules is available in my personal Maven repository.

To test your setup there is sample code in both projects and mvnw test will show two violations:
[INFO] PMD Failure: SampleClass.java:2 Rule:TooManyFields Priority:3 Too many fields.
[INFO] PMD Failure: SampleClass:9 Rule:NoElseKeyword Priority:3 No else keyword.
It is possible to check the rules alone with mvnw pmd:check. (Using the Maven Shell the time to run the checks is reduced by 50%.) There are two run_pmd scripts, one for Windows (.bat) and one for Linux (.sh).

Object Calisthenics RetrospectiveLimitations of Checking Code
Obviously code analysis cannot find everything. On the other hand - as discussed earlier - some violations will be false positives, e.g. when using the Stream API. You can use // NOPMD comments and @SuppressWarnings("PMD") annotations to suppress false positives. I recommend using exact suppressions, e.g. @SuppressWarnings("PMD.TooManyFields") to skip violations because other violations at the same line will still be found. Use your good judgement. The goal of Object Calisthenics is to follow all nine rules, not to suppress them.

Learnings
Object Calisthenics is a great exercise. I used it all of my workshops on Object Oriented Programming and in several exercises I did myself. The verification of the rules helped me and the participants to follow the constraints and made the exercise more strict. (If people were stuck I sometimes recommended to ignore one or another PMD violations, at least for some time.) People liked it and had insights into object orientation: It is definitely a "different" and "challenging way to code". "It is good to have small classes. Now that I have many classes, I see more structure." You should give it a try, too. Jeff Bay even recommends to run an exercise or prototype of at least 1000 lines for at least 20 hours.

The question if Object Calisthenics is applicable to real working systems remains. While it is excellent for exercise, it might be too strict to be used in production. On the other hand, in his final note, Jeff Bay talks about a system of 100,000 lines of code written in this style, where the "people working on it feel that its development is so much less tiresome when embracing these rules".

28 December 2017

Interview Gabriel Grill

I have known Gabriel since a long time. We met at an early meetings of the Java User Group Vienna many years ago. I noticed him sharing content concerning diversity. It was just a matter of time until I would make him share his views ;-)

Gabriel, please introduce yourself. Why did you choose to become a software developer?
My name is Gabriel Grill. Currently I am writing my Master's Thesis at the University of Technology, Vienna, and work at the Austrian Centre for Digital Humanities at the Austrian Academy of Sciences. I started programming in high school (HTL). My main reasons for choosing the field at that time were the possibilities for earning money afterwards and the high probability of having a secured job in the future. After I got to know programming more, I liked how seamless one could use this skill to create things, the puzzle solving aspects of it and the creativity one needs to find solutions. I always tried not to focus too much on computing only. Consequently - at university - I took lectures in the social sciences, was politically involved, played the drums, did theatre and so on.

brosI know that you are concerned with sexism. For example I noticed you sharing content about women in technology. Why does that matter to you?
I believe it is important to be socially engaged in groups, organisations, etc. one is a part of and try to improve conditions for marginalised people there. Inclusion helps everybody. I very much recommend to watch this video on gender-inclusive software design by Distinguished Professor Margaret Burnett, which explains this point much better then I could.

My engagement in tech is not limited to barriers women have to face, I think structural discrimination against this group is still a very big issue in the community. Structural means that the discrimination is ingrained into the culture, normalised, and thereby one has to actively learn, reflect and work against exclusionary mechanisms to change the status quo. In male majority communities, such as the developer community, often so called "bro" cultures emerge. They have certain unwritten rules of how one should act and look like, to be a part of them. An example to me is the beer with "the guys" after work. Bonds are often formed there which in turn may help the people participating to advance in their careers. But there are people who are not into that or do not have the time. Similarly smoke breaks allow those who participate to connect more. Another example, which I have noticed several times in conversations or talks at conferences, are various forms of sexualisation or objectification through jokes or comments, which have exclusionary effects. These seemingly small things together make up a culture in which some have it easier to be a part of. Many of these mechanisms are not unique to developer communities but prevalent in society. The "Pop Culture Detective" is a great YouTube-Channel with many videos on reflections of portrayals of culture in media. I recommend its videos on the "Big Bang Theory" and nerdom especially to male developers (Part 1 - The Adorkable Misogyny of The Big Bang Theory, Part 2 - The Complicity of Geek Masculinity on the Big Bang Theory). I think we all would benefit a lot from a more inclusive and reflective community where for instance I, as a man, would not have to act and dress in certain ways to feel "normal". I would love if our community was much more about supporting one another and thinking about how to improve society.

What other topics are you concerned about?
I usually do political work in the contexts I am directly involved in. Consequently I have been doing a lot of student politics working against different types discrimination based on income, gender, race, accessibility at university. I believe in Austria we have a special responsibility to reflect and remember our past and work against right wing tendencies that want to divide society. In this manner, I want to point to Karl Popper's "Paradox of tolerance" which states: "Unlimited tolerance must lead to the disappearance of tolerance. We should therefore claim, in the name of tolerance, the right not to tolerate the intolerant." I try to take part in protests or actions that I am fond of and generally work on awareness through campaigns.

I am also interested in net politics, privacy and ethics of programming or more generally algorithmic systems. I have created a seminar lecture at TU Wien together with professor Tompits and my colleague Matthias Fassl to enable students to read scientific papers on ethical and social aspects of such systems and have interesting discussions. I try to talk at events or conferences sometimes to raise points I find important. I think generally as developers we need to spend more time on reflecting and learning how to build systems for people. This entails taking diversity into account and creating software which is not only tailored for a small subset of people who are well-off anyway but also useful to people with little money or single parents. I educate myself through lectures mostly in the social sciences, blogs and papers. I recommend to look through YouTube and Twitter, and consume content of people who belong to marginalised groups, such as Feminist Frequency, Kat Blaque and Annie Elainey. There is a lot to learn about other experiences.

I think global warming is a big issue and my actions here are more on a personal level like eating only little meat.

Outside your personal topics discussed till now, what do you consider the biggest challenges (for humanity)?
That is a very tough question to answer. I think it would be arrogant of me to answer this question bluntly. Depending on your circumstances the answers would be very different. For instance to me climate change is a big issue, but there are many people out there who see this differently. I think it is very important to explain to them that doing nothing makes things worse, but there may be no universal human challenges on which everybody completely agrees on. As a middle European, white, male, able-bodied, computer science student to me climate change may be a big issue at the moment, but for people who are starving or live in poverty other priorities apply.

Many developers would probably answer this question somehow similar because it is still a very homogeneous group. That is why I believe questions like this should be asked to people with different backgrounds to get a better answer. This would necessarily include most people that are part of the global South. I think as developers we should look more outside our own bubbles to grow our perspectives. I consider dealing with remnants of colonialism as a very important issue and in turn exploitation of the global South as well as weapon trading and war. Most of the other issues I have mentioned in the previous question.

Speak up, make your voice heardWhat do you do to engage in the topics? For example, did you take part in public protests, donate money to NGOs or sign petitions?
I do things like trying to eat less meat and use public transport as much as possible, but ultimately I think most important are policies. The issues mentioned in the previous questions should be tackled collectively through democratic processes by engaging in a political party or other organisation, raising awareness through events or activism and learning on what issues are there and what they really are about. I do many of these things and the ones you mentioned in the question as well, but still time and money is limited and you have to prioritise.

I would like to see more impact of my regular work on these important topics. Do you think that is possible in general?
I do not know if it is possible in general, but I think as developers we are in the position to be able to choose were we want to work. We can ask critical questions, have a positive influence on the projects we work on, raise awareness on issues in the organisation we are a part of and so on. If many developers, consumers and other stakeholders are keen on social and ecological values, businesses will adapt. On the positive side, it seems that social responsibility is becoming a more important topic to many companies at the moment. I believe often more policy is necessary, e.g. to foster fairer working conditions and payment for people in the global south. I think little things like supporting people, talking to colleagues about political issues, learning about ethics or working on improving diversity, are contributions that should be highly valued. Unfortunately a lot of this kind of work, especially care labour, is not paid.

Which guidance do we have to navigate professional decisions? Did you take specific decisions because of your values and social responsibility?
I think it is important as a developer to be aware of your responsibilities and educate yourself on how to deal with them. The social sciences, political science and philosophy or more specific the fields of social informatics and human computer interaction have a lot of knowledge on how to navigate when being faced with political decisions. I strongly suggest to read more literature from these fields.

I want my development to be human-centred. I think about for whom I create something, am I really inclusive, is it ethical or bad for others and how can I best include stakeholders in the decision processes. These question usually do not have a trivial answer and that is why it is important to give them attention.

I have not encountered a situation where I was asked to write a piece of code which I considered to be very unethical, but I am aware that I have made ethical decision myself when coding. In my Master's Thesis I use text mining methods to extract information from news articles. There are many parameters to tune and models to choose and depending on my choices the results will be different. It is my obligation to document this process very well. How I get results and how I present these results is very political. I suggest reading this article which critiques a study that claims to be able to identify sexual orientation through images given to a trained machine learning system.

How do you think about selecting industry, customer and project based on your values and social responsibility?
I think one definitely should take their values and the social responsibility of the company into account. I would not be willing to work for a arms manufacturing company. Thorough research is required here because some companies do not state directly that their work or research may have a secondary use in armed conflicts. I would not like to work at companies in the gambling business or with a focus on surveillance.

DiversityDo you have problems with any industries?
It depends on the context very much. I would not want to work for an animal factory but if there is not another option or the factory is somehow vital I would probably reconsider. I think I am not able to give a general answer here, but animal factory and weapon manufacturing are as close as it gets to a no for me. This includes companies like Thales or Glock.

Did you ever reject a customer based on your values?
I did not need to reject a project offer so far, but I have chosen consciously not to apply to certain companies. During my studies I have chosen my projects in a way I felt they could benefit society.

On the other hand, what would be projects that you would love to work on?
At the moment I consider to go into research and work on ethical and social implications of algorithmic systems. I think research in this area could be useful to society. The current trend is towards putting more decision making algorithms in our lives but when these are mostly developed by a homogeneous group with almost no education on ethical and political issues, this becomes a democratic problem on who gets to decide what the algorithms do or what their optimisation goals are. Big companies are looking into these topics, due to critique from the public. I like developing very much. Working on projects that support marginalised people in some way would be interesting, like working on accessibility, support for campaigns or apps against hate. Projects that are very interesting from a technological point of view would also be options for me.

Thank you Gabriel.

3 December 2017

PMD Check and Report in same build

lane one, lane twoI am working together with senior developer and (coding) architect Elisabeth Bl├╝melhuber to set up a full featured continuous delivery process for the team. The team's projects use Java and are built with Maven.

Using PMD for Static Code Analysis
After using Jenkins for some time to run the tests, package and deploy the products, it was time to make it even more useful: Add static code analysis. As a first step Elisabeth added a PMD report of a small set of important rules to the Maven parent of all projects. PMD creates a pmd.xml in the target folder which is picked up by Jenkins' PMD Plugin. Jenkins displays the found violations and tracks changes over time, showing a basic trend graph. (While SonarQube would be more powerful, we decided to stay with Jenkins because the team was already "listening" to it.)

Breaking the Build on Critical Violations
I like breaking the build on critical violations to ensure the developers' attention. It is vital, though, to achieve the acceptance of the team members when changing their development process. We thus started with a custom, minimal set of rules (in src/config/pmd_mandatory.xml) that would break the build. The smaller the initial rule set is the better. In the beginning of adding static code analysis to the build process, it is not about the code but getting the team aboard - we can always add more rules later. The first rule set might even contain a single rule, e.g. EmptyCatchBlock. Empty Catch blocks are a well known problem when analysing defects and usually developers agree with the severity of having them in the code and accept breaking the build for that. On the other hand, breaking the build on minor or formatting issues is not recommended in the beginning.

Here is the snippet of our pom.xml that breaks the build:
<build>
  ...
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-pmd-plugin</artifactId>
      <configuration>
        <failOnViolation>true</failOnViolation>
        <printFailingErrors>true</printFailingErrors>
        <rulesets>
          <ruleset>.../pmd_mandatory.xml</ruleset>
        </rulesets>
        ... other settings
      </configuration>
      <executions>
        <execution>
          <id>pmd-break</id>
          <phase>prepare-package</phase>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
This is more or less taken directly from the PMD Plugin documentation. After running the tests, PMD checks the code.

Keeping a Report of Major Violations
We wanted to keep the report Elisabeth had established previously. We tried to add another <execution> element for that. As executions can have their own <configuration> we thought that this would work, but it did not. PMD just ignored the second configuration. (Maybe this is a general Maven issue. For example the Maven Failsafe Plugin is a copy of the Surefire plugin to allow both plugins to have different configurations.)

The PMD plugin offers a report for the Maven site which is configured independently. As a workaround for the above problem, we used the site report to check the rules listed in src/config/pmd_report.xml. The PMD report invocation created the needed target/pmd.xml as well as a readable target/site/pmd.html.
<reporting>
  <plugins>
    ... other plugins
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-pmd-plugin</artifactId>
      <configuration>
        <rulesets>
          <ruleset>.../pmd_report.xml</ruleset>
        </rulesets>
        ... other settings
      </configuration>
    </plugin>
  </plugins>
</reporting>
Skipping Maven Standard Reports
Unfortunately mvn site also created other reports which we did not need and which slowed down the build. Maven standard reports can be selected using the Maven Project Info Reports Plugin. It is possible to set its <reportSet> empty, not creating any reports:
<reporting>
  <plugins>
    ... other plugins
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-project-info-reports-plugin</artifactId>
      <version>2.9</version>
      <reportSets>
        <reportSet>
          <reports>
            <!-- empty - no reports -->
          </reports>
        </reportSet>
      </reportSets>
    </plugin>
  </plugins>
</reporting>
Now it did not create the standard reports. It only generated target/site/project-reports.html with a link to the pmd.html and no other HTML reports. Win.

Skipping CPD Report
By default, the PMD plugin invokes PMD and CPD. CPD is checking for duplicate code - and is very useful - but we did not want to use it right now. As I said before, we wanted to start small. All plugins have goals which are explained in the documentation. Obviously the Maven report invokes PMD plugin's goals pmd:pmd and pmd:cpd. How do we tell a report which goals to invoke? That was the hardest problem to solve because we could not find any documentation on that. It turned out that each reporting plugin can be configured with <reportSets> similar to the Maven Project Info Reports Plugin:
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <configuration>
    ... same as above
  </configuration>
  <reportSets>
    <reportSet>
      <reports>
        <report>pmd</report>
      </reports>
    </reportSet>
  </reportSets>
</plugin>
Putting Everything Together
We execute the build with
mvn clean verify site
If there is a violation of the mandatory rules, the build breaks and Maven stops. Otherwise site generates the PMD report. If there are no violations at all, Maven does not create a pmd.html. There is always a pmd.xml, so Jenkins is always happy.

(The complete project, ready to clone, is here.)