The fools with the tools make the rules.
– anonymous


Rules

Following rules should be followed all the time. Everybody must follow the rules.

The first rule of midPoint development is: You do not talk about midPoint development rules.

MidPoint development has no strict unbreakable rules. Just guidelines. Every member midPoint development team is expected to use his brain all the time. We rely more on the judgment of midPoint developers than we rely on the ephemeral power of the rules.

Guidelines

Guidelines are just recommendations. Guidelines describe the method of doing something in the common case. They are kind of best practice. Guidelines should usually be followed, but they are not cast in stone. Everybody may choose not to follow guidelines if they know what they are doing. Guidelines may also be dangerous in some (rare) situations. Therefore everybody must choose not to follow a guideline in case that following a guideline would cause major problems in the project.

However, if you do not follow the guidelines please be prepared to explain why you have done what you have done. The best way how to deal with this is to document all exceptions from the guidelines and especially document why the guidelines were not followed. Use source comments, wiki, comments in jira or any other method that records the reasons.

Mostly Linear Development

We keep the development as linear as possible. It means that vast majority of the development happens directly in the master branch. We usually try to avoid excessive branching and merging. Also the release process is mostly linear.

Short-living feature (topic) branches are perfectly OK. Those branches are even recommended for bigger features that risk breaking the code on master branch. However, try to merge the feature branches to master as soon as possible. Do not wait while your feature is done. The right time to merge is as soon as the risk of breaking master branch is low.

Practice:
Update you workspace frequently. Commit frequently. Keep the code synchronized.

Why we want this?
Branching means that the code in the branch is developed in isolation. This complicates the subsequent merging as the main branch (master) also evolves in the meantime. The merging usually requires a special integration step which takes extra effort and is quite unpredictable. We prefer continuous integration of the code. We do not want explicit integration steps.

MidPoint development is not using gitflow. There is no develop branch. The master branch is the branch when all the development happens.

Continuity

Keep the system working. As much as you can. You should not commit a code that breaks the build and the happily go home. If you have code that breaks the build, fix the system before you commit. No matter where the build fails (in what component) just go there and fix it. If you cannot fix it, then talk to the developer that can fix it before your commit and agree when it will be fixed. You can make commit that breaks the build only if you are sure that someone else will fix it in the next hour or so. And you are expected to stay online during these few hours and make sure that it is really fixed. If it is not, you are expected to roll back the changes and make the system buildable again. If you are going to make a major change that can break the system for few days, you are required to branch the code and merge it back when it will work again. The same principle also applies to broken tests, but with a less strictness in this case.

In short: The system should be buildable all the time and the tests should pass.

Practice:
Build the code before commit. Building the complete code takes few minutes if you skip the tests. Also execute the tests at least in the component that you have changed. Have a look at Continuous Integration to make sure that the build is OK and that the tests pass.

Why we want this?
As the whole team shares the code breaking the code affects all team members. Breaking the master branch interrupts the work and therefore it means a waste of time. Even a short interruption may be considerable waste if it is multiplied by many developers.

No Code Ownership

We do not have "my code" and "your code" in midPoint. All code is midPoint code. Anybody may change any code at any time - assuming that he knows what he is doing (but also see "Continuity" guideline). However, midPoint code base is quite big and complex. It is beyond a capability of any single developer to understand all the code. Therefore if you are not confident that you know what you are doing please contact the original author (it should be identified in the source file header). Or contact the architect. Or just ask anybody.

Why we want this?
Because of continuity and efficiency. You need to fix all the code that is affected by the change you have just done. It does not matter whether the code that needs to be fixed is created by you or not. It needs to be fixed. Right now.
Sharing the code also spreads understanding through the team.

Test-Driven Bugfixing

If you encounter a bug write the test first. Then fix the bug. Do not be tempted to fix the bug right away. See Test-Driven Bugfixing page for details.

Practice:
Replicate the bug in a test (most likely an integration test). See how the test fails (this is important). Fix the bug. See the test pass.

Why we want this?
Tests make sure that the code works. But how we can make sure that the tests work? That they do what they are supposed to do? We can write tests for the tests but that is quite insane. We rather write the test when the bug is still there and see that the test fails. This is an indication that the test works well to detect the bug. Ten fix the bug and see that the test passes. This is an indication that the bug is gone.

Coding Guidelines

General Guidelines

Error Handling

Avoid using throws Exception, catch (Throwable t) and similar rough constructs. Use the most specific subclass for thrown exceptions. If you catch exception, either react to it or re-throw it. Avoid using {{catch (FooException e) { // do nothing }} as much as you can.

No More Hacking!

MidPoint is no longer a young product. During the years midPoint matured and now it is reasonably stable system. However, we will not pretend that everything in midPoint is perfect and that we do not have any technological debt. As all practical systems there are things in midPoint that really need improvement. As midPoint has matured the developers also need to behave responsibly. Therefore this is the plan:

Code Structure Guidelines

Components

Components are midPoint building blocks. The bricks that we use to construct the system. Components are meant to be well encapsulated. Components hide most of the details inside and expose the functionality using well-defined interfaces. Component internal structures and methods should never be accessed directly from other components (regardless of whether these are marked as public) - except for components explicitly designed to be shared libraries. See also Interfaces section below.

Each component has at least one primary maintainer in midPoint core team. Maintainer is not owner of the code. We do not follow a concept of code ownership. Maintainer just coordinates the development of the component. Maintainer should make sure that the all the component development efforts make sense, that the changes made by two developers do not conflict and that the component will be stable. The maintainer is not expected to do all the work by himself. Others are not prohibited to touch the component code. Quite the contrary. Everybody is more than welcome to fix bugs and make reasonable improvements anywhere in the system. However, if someone is doing a major change in the component, he should talk to the maintainer before doing that change - to make sure that the change will not clash with other activities, will not endanger deadlines and will not ruin a long-term plan for component development.

It is not possible for one person to understand all the details in the entire system. Therefore we need to split the knowledge a bit. The maintainer should understand exactly how the component works. He is expected to understand all the details, to be able to explain every line of source code in the component (or know where to look for an answer). Other team members will ask question in case they do not understand something about the component.

Each component should have a short name, e.g. foo. This name should be unique in the whole project. The name should be consistently used to identify the component. Especially:

Motivation: We want to recognize components at the first sight. We want to immediately see what component is causing a problem in exception stack traces. We want to be able to easily find out what components are in a service assembly by just looking at the file names. We want to navigate the source tree easily.

Each component should have a wiki page describing design of the component. The wiki page should describe ideas and motivations, contain diagrams and figures. The goal of the wiki page is to explain why the component is created like this (motivation) and provide a basic overview of how it works. The wiki page should be used as an entry point for people new to midPoint and also as a way how to communicate component design to others in midPoint team. The wiki pages should not dive too much into the details how the actual source code works. Use comments in the source code to describe that. The page should be short enough to maintain it efficiently. Outdated design page is misleading and it is often worse than no design page at all. Please keep the design page up to date.

The component should also be listed on Source Code Structure wiki page.

Interfaces

Keep in mind that interfaces define the contract. Interfaces are much more than just a code. In short, all interfaces should have good description of all operations and data structures. Use annotation elements in WSDL and XSD and javadoc in Java. Use them a lot.

Full recommendation regarding interface definition can be found here: http://www.nlight.eu/documents/interface-definition.pdf

If the interface is meant to be public it should be listed in Interfaces page.

Dependency Guidelines

Keep number of dependencies reasonable. Do not add new dependency just because you need one simple function that you can easily create and maintain yourself.

Be careful about dependency versioning. If we use a dependency, we use single version of that dependency in all midPoint components. As our dependencies can have dependencies of their own, this may be quite tricky (a.k.a "dependency hell"). We are using dependency convergence plugin to check for some bad situations. But this plugin is not almighty. Therefore be careful.

If you add any new dependency, always notify midPoint architects. The dependency need to be checked for licensing compatibility. Also, NOTICE file may need to be updated. We also want to limit dependency creep. This is very important.

As a rule of the thumb, is it always a good idea to discuss all dependency changes with midPoint architects.

See Also