This file describes the way we work. Reading this file will help you to understand the organization of the Qabel project. If you want to contribute to Qabel -- depending on your experience with open source projects and GitHub -- please scan this file on how to do this.
This file is for contributors, reviewers and integrators alike.
- Contributor Anyone that contributes to a Qabel GitHub repository in any form. Anyone can be a contributor.
- Reviewer Anyone who comments on a pull request, wiki page or proposal in the form of an issue -- after reading through it -- with the intention of improving it. Anyone can be a reviewer but when it comes to making something official (e.g. merging a pull request into upstream master), words from some reviewers may have more weight than words from others.
- Integrator Anyone with push access.
We use issues to ask questions, discuss ideas, organize tasks, look for help and so on -- not just for reporting software bugs. Issues are our main tool for collaboration.
We are using pull requests with the fork & pull model. If you are not familiar with collaborating on GitHub, see this help.
- Create a new branch in your fork for each new pull request. Base these branches on the latest commit in the branch you want your changes to be merged into (often this is master) from upstream -- keep your fork in sync.
- Address one bug fix, feature or proposal (on how to handle one particular topic) per pull request.
- It is often a good idea to discuss the things you want to do in an issue prior to actually writing code for something which may not be merged anyway.
- Pull requests should be based upon an issue. If merging your pull request would resolve an issue, you can mention this with special syntax.
- Only make your pull requests depend on an other (not yet merged) pull request if is technically necessary. E.g. the code in PR b uses functionality implemented in PR a but a is not yet merged.
- Clearly mention this dependency in the initial description of the pull request.
- Reference all necessary resources (e.g. issues, pull requests, wiki pages, documentation, non GitHub resources, ...) in the description of your pull request.
- Force push
git push -f
only when asked for by an integrator. Rebasing should only be done if it is needed or really useful. - Push additional (fix) commits to your pull request to incorporate changes (e.g. which are needed due to the review of the pull request).
- Never abandon a pull request and create a new one for the same thing unless you are asked for by an integrator. When doing so, always reference these pull requests to one another.
Prior merging a pull request, the following conditions must be met.
- All discussions must be resolved.
- This includes comments on outdated diffs (of course they are resolved when the diff is outdated due to resolving).
- After merging a pull request the code in the affected branch must still compile and all the tests that work without the merge must still work.
- At least one integrator needs to acknowledge the pull request.
- The integrator who performs the merge takes responsibility and therefore should have reviewed the pull request in the state that will be merged.
- Remember that force pushing can alter the patch set of the old commits -- not just the hashes ;)
The integrator who performs the merge decides on how to perform the merge. Sometimes manual merges need to be done. Sometimes even a manual reabase and/or merge can be helpful (e.g. to fix history issues the contributor cannot fix or the integrator want to help the contributor with). Merging via the GitHub web interface (the green button) should be preferred.
Code without tests is broken (if it isn't broken yet, someone will break it in the future - and you can't prove it still works). Include simple, small and readable tests in your changes. Remember: tests are part of your code and equally important as the "rest" of the code.
- One commit can incorporate a big or a small patch but address one thing per commit.
- A commit does not include unnecessary changes. This is especially true for changes due to auto formating and fixing spelling errors in comments. Adding / changing documentation to added / changed functionality is not unnecessary here.
- If one specific commit solely resolves an issue, use this special syntax.
Commit messages have a subject + an optional description or additional information -- not a single long line or sentence. The description / additional information is a new paragraph. Just think of a commit message as an e-mail with a subject and a body with the diff attached to the e-mail.
Example commit message:
Implemented multi sub-key support
Old getters are marked as deprecated. They will be removed when all other methods have been changed to the newly returned lists.
We do not dogmatically follow a particular style guide but generally the Code Conventions for the Java ™️ Programming Language are a good starting point.
Regarding the look and feel most -- but not all -- of this is reflected by the Eclipse default settings.
- Use 4 SPACES instead of tabs.
- Try to fit your code into 80 characters but do not wrap your line of code just for the sake of wrapping it. Use 120 in your auto format settings.
- Statements like
if
always with{ }
. Do not just writeif (foo) bar;
- Our code does not need to be compatible to versions below Java 7. That means you can and should use Java 7 features and syntax.
- Developers want their software to always be in a defined and consistent state and this should be preferred but sometimes it is not possible. In such cases not only document these conditions but also handle unwanted conditions.
- E.g. there are cases where an
initialize()
method needs to be called after an object has been created (i.e. the constructor has been invoked) to fully initialize this object but before other methods work as intended. Such dependencies must not only be documented (using Javadoc) but also the methods which depend on a call ofinitialize()
must check if this call has happened and give a meaningful error if not. In cases like this we use anIllegalStateException
.
- E.g. there are cases where an
- Use Exceptions to control application flow. Returning
null
or empty collections when the happy path of a method is not met leads to defensive programming or exceptions elsewhere in the code where they are hard to track. In such cases, just throw a meaningful exception with a helpful message. The exception, if contained in the methods signature, tells each caller what to expect. The message combined with the stacktrace tells each debugger where to look and what to look for.
Qabel is a big project and it has a lot of code which will be called from other components -- e.g. from a module. Code -- especially public methods or classes -- must be well documented. Well means class, method and parameter names should speak for themselves. Nevertheless often additional Javadoc is needed to understand what is going on. These comments should contain actual information and not repeat things the class, method or parameter names should provide anyway.
Bad example:
/**
* Get the Runtime.
* @return Returns the time.
*/
public long getTime();
Good example:
/*
* Get the runtime since application start.
* @return Returns runtime in milliseconds.
*/
public long getRuntime();
As it can be seen even simple getter or setter might need Javadoc to provide valuable information. Of course this does not mean every trivial getter and setter need Javadoc.
Code should speak for itself. Nevertheless there will be code which needs an inline comment to explain some details to the reader (i.e. developer).
The code should look the same regardless who wrote the code. Look into the code if you are unsure about how to do something. Example: If you often happen to find code like
catch (SomeException e) {
logger.warning("SomeException occured while doing something. " + e.getMessage());
return false;
}
don't do something like
catch(SomeException e1)
{
System.out.println("SomeException occured while doing something.");
return (false);
}
You will find code which is not conform to our style (e.g. you will find spaces instead of tabs). Never address style issues in your pull request or commits. Big patch sets just for re-formatting the source code will not help anyone. Try to commit conform code in the future instead and eventually the style will become conform. Of course big refactoring patch sets may still be a good idea after reaching certain milestones but this has to be discussed (e.g. in an issue) beforehand.
Use provided functions like encryption or constant time comparison instead of writing new code. See the public crypto functions in Crypto Utils and Drop Message Crypto Util
In order to uphold the security level of Qabel you really MUST carefully read the following linked notes if you plan to write code that directly uses crypto routines or even plan to write your own crypto functionality.
Additionally you should be aware of certain network attacks and the problems they base on if you write network message initiating code. To name one example: compression of external initiated messages (e.g., acknowledge messages) can leak information, if a part of the message can be chosen by the initiator (see CRIME). Thus we do not want to compress such messages (i.e. drop messages).