Development Practices
XWiki development follows several rules listed below. If you're a Committer or if you simply wish to contribute please take the time to read them as you're expected to follow these rules.
General Development Flow
- Whenever we start working on a topic (a sufficiently important one), we send a proposal email to the list to explain what we're going to work on, to gather feedback and to get agreement.
- In the proposal email we propose a roadmap, i.e. dates that are in sync with product roadmaps (for example, say: "this feature is planned to be finished for XE 1.7M2).
- Once we get the agreement, we create a JIRA issue and assign oneself (we don't forget to set the fix for version)
- If it takes long (say more than 1 week) we regularly publish feedback on the progress and possibly revise the dates if need be. We should absolutely warn if there's a risk of not delivering as planned. This is crucial.
- Commits should be done regularly and more than once per week (the more the better). It should never ever be less than once per week.
The goals are several:
- Provide visibility to others
- Ensure agreement on the work being done (it's too stupid to do a lot of work and only find when it's finished that it wasn't the right way to do it and it has to be all redone again)
- Allow us to have product roadmaps
- Provide the ability to help someone if he's lagging behind or has issues
Continuous Integration
See the Continuous Build page.
Automated Builds
XWiki has an automated build system and developers are asked to use it on their local machines to prove that their changes work before committing them to the Source Repository. See the Building page for more details.
Frequent Releases
We are following this release cycle for main product releases:
- a 3 weeks release cycles for milestones (+/- 1 week)
- a 2 weeks release cycles for RCs (+/- 1 week)
- a 3 months release cycle for final versions (+/- 1 month)
We're doing this for the following reasons:
- allow users to test the released milestones and provide feedback and thus help us stabilize them
- provide a good release rythm so that users can see the project is alive and dynamic
- making a release forces us to be "clean" and to finish tasks that have been started as much as possible and not leave them in a 80% finished state. This includes documenting the release and testing it. If this is pushed to the end (like every 3 months or more) it never happens or is done very badly.
Copyright header in source files
All files (including configuration files) must have the following copyright statement.
For Java files
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
For XML files
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
-->
Coding Conventions
See the Code Style page.
File encoding
The following rules must be taken into account when the need for writing non-ASCII content in the XWiki sources arises:
- All Java source files must contain only ASCII chars, Unicode escapes inside strings when needed, and XML entities in javadocs. Since we don't use @author tags, this should not be a problem.
- All translation files must contain only ASCII chars and Unicode escapes (stronger than the Java properties specification).
- All wiki documents sources must be stored in UTF-8.
- Other XML files should always specify their encoding in the <?xml> header, and it should be UTF-8 as often as possible.
- All other textual resources must be stored in UTF-8, minimizing the use of non-ASCII chars.
Currently, only the XML rules are broken, but this is not a serious problem since the XML reader can detect and use the charset/encoding specified in the XML header.
JIRA Best Practices
Here are some rules on how to use JIRA for XWiki projects.
Rule: Always put a JIRA issue reference in commit messages
The rationale behind this:
- One consistent way to manage all the work to be done on the XWiki project. It also means there's no unaccounted work, meaning anyone can go to JIRA and query it and see what everyone has been working on.
- Automated release notes/change logs. When we release a version we can simply do a JIRA extract and it'll give the full change log of what happened. This is really important for our users to see what has been done when in XWiki.
- Traceability. When you use the JIRA issue number in your commit, the JIRA subversion plugin can show the modified files directly from JIRA. This is quite useful later on, when someone is looking at a JIRA issue and wants to see what was modified. In addition Fisheye is also integrated with JIRA and when you browse the source repository you can see the JIRA issue associated with files.
Of course this shouldn't be done for any trivial things like adding a small javadoc, renaming a single variable, cosmetic changes, svn ignore, etc.
JIRA issues can be marked "confidential", e.g. to hide the details of a security issue until it is fixed. Such issues should also be referenced in the commit message. However, avoid exposing the details of the issue in the commit message (some time will pass until the code is released) by choosing a more neutral description.
The general strategy goes like this:
- When you plan to work on something, create a JIRA issue and assign it to yourself or simply assign an existing JIRA issue to yourself if one already exists
- Implement it
- Commit it with the JIRA issue number in the commit message
- Close the JIRA issue
- Another acceptable variation is:
- Implement something
- When you want to commit it you realize you don't have any JIRA issue to put in the commit message so don't commit.
- Create the JIRA issue
- Commit with the JIRA number in the commit message
Rule: Don't create issues for unreleased work
Imagine that someone has been working on a given issue for a given version. Then someone else notices a problem related to the work done. If the version has not been released then you shouldn't create a new JIRA issue for reporting the problem. Instead you should reopen the issue (if it's been closed) and add a comment to it.
Otherwise we'd end up having a JIRA issue with a "Affects" field equals to the "Fix For" field and ending up in the Release Notes. That would be unnecessary since end users would never have seen the problem since the work would have never been released with the problem in it...
Rule: Don't create unnecessary issues
- If you want to know whether you should create a JIRA issue or not, ask yourself the question: "is my change going to affect any user or any extension developer in any way"? If the answer is yes then you must create a JIRA issue
- If you're fixing something related to build then it's not mandatory to create an issue. However if you do make sure you use the special component usually labeled "Build, Infrastructure and Tests" in our JIRA projects. We're excluding issues in this category from our release notes.
Rule: Use nice user-friendly titles
When you create a JIRA issue always take the time to put a nice title for the issue. The title must be understandable by a user so don't describe the issue technically but rather in what way it affects users. For example don't say "Fix the addXXX API to return an Array List" but rather "Allow creating several pages at once".
Rule: Don't set a "Fix For" field for invalid issues
Issues that are closed with "Won't fix", "Duplicate", "Cannot reproduce" or "Incomplete" must have a "Fix For" field set to "unknown" so that they don't appear in the Release Notes, as JIRA doesn't make the distinction visible and this causes confusion.
Rule: Close issues that XWiki committers don't plan to implement
- We close issues that we know we won't fix (using a "Fix For" value of "Duplicate", "Incomplete", "Cannot Reproduce" or "Won't Fix"). We might not want to fix them for several reasons but one reason is that the issue is for an old XWiki project version.
- This is especially true since XWiki committers are only officially supporting the last 2 versions (last released + version in development). Of course, any committer wanting to
fix any old issue is free to do it.
- This is especially true since XWiki committers are only officially supporting the last 2 versions (last released + version in development). Of course, any committer wanting to
- Leaving these issues open is not a good idea since:
- It sends the wrong signals that we're going to fix the issue
- The issue can still be found with a search even if closed
- When we close it then the reporter can explain why it's so important for him/her, or not. Which we wouldn't know if we hadn't closed it
- Contributors can reopen issues and attach a patch or just create a new issue
- It means that for all other issues we plan to fix them at some point
Using bird names for Skins
We have decided to name XWiki official skins using bird names. We are currently renaming the existing skins. Any new skin must use a bird name. It's recommended to send a proposal to the list whenever a new skin has to be named.
Here are some potential ideas for future names:
- Dove
- Emu
- Kiwi
- Grasswren
- Condor
- Warbler
- Kestrel
- Redtail
- Pigeon
- Booby
- Sparrow
- Blackbird
- Parrot
- Peacock
- Finch
- Wren
- Crow
- Turkey
- Thunderbird
- Piasa (a local phenomenon, from a primitive painting on the cliffs on the eastern shore of the Mississippi, attributed to the Piasa tribe, which looks rather like a griffin)
- Thunder Chicken
- Kingfisher
- Swallow
Subversion Practices
Applying a contributor's patch
Please use the following commit log message template:
Patch submitted by <contributor's name>
Reviewed by <reviewer's name>
<additional comments here>
This gives credit to the contributor.
Also make sure to add the contributor's name to the Contribution page.
This is important to give proper recognition to our contributors.
Subversion configuration and line endings
It's important that everyone's subversion client is configured properly, especially for line endings. See http://www.apache.org/dev/version-control.html#https-svn and http://svnbook.red-bean.com/en/1.0/svn-book.html#svn-ch-7-sect-2.3.5 for more details. Another important aspect is the automatic expansion of the @version $Id$ line we include in all Java source files, to identify the version of a file.
Please add the content of the following file to your Subversion config file (~/.subversion/config): config
Back-end Development Practices
Component Development
Read the Component Module documentation for details on how to write components.
Backward Compatibility
We must pay attention to backward compatibility. We have decided to use AspectJ Aspects for implementing backward-compatibility, as described in this blog post.
This allows us to get the following advantages:
- We keep backward compatibility
- We get clean code and this allows us to get also a clean Javadoc since the javadoc is applied without the Aspects being weaved
- All backward compat code is gathered in a single place
- It's easy to remove deprecation when required
Here's an example of such an Aspect: http://tinyurl.com/4wlzr3
Deprecation Strategy
Our rule is to keep @deprecated methods/classes for 2 final releases after the version where they were first added as been released as final.
For example if a method is deprecated in, say XE 1.3M2 then the method will be removed in 1.6M1 or after. Of course any major new release can deprecate anything. For example a XWiki 2.0 release is allowed to break backward compatibility (obviously we need to be careful to offer a migration path for users of previous major versions).
Note that for this to be easy anyone deprecating methods must add the information of when it was deprecated. For example:
* @param time the time in milliseconds
* @return the time delta in milliseconds between the current date and the time passed as parameter
* @deprecated replaced by {@link com.xpn.xwiki.api.Util#getTimeDelta(long)} since 1.3M2
*/
public int XWiki.getTimeDelta(long time)
{
return this.util.getTimeDelta(time);
}
Front-end Development Practices
JavaScript Best Practices
All javascript should be in the <head> of the document.
There are a variety of practices which lead to less useful more error prone pages which sometimes violate WCAG standards, these are almost impossible if all javascript in inserted into the head.
See this email thread
Avoid using javascript in attributes such as onload, onmouseover, etc. Doing this can cause problems with event handlers and is sometimes WCAG invalid.
Users should be able to do anything without javascript that they can with it.
Javascript should only exist to make your web experience more enjoyable.
External libraries
XWiki bundles several libraries to ease the development of front-end components. Amongst them are:
- Prototype.js (DOM manipulation, AJAX library, OOP-style classes. See http://www.prototypejs.org/ )
- Smartclient (Rich AJAX widgets. See http://www.smartclient.com/ )
- Scriptaculous (Drag and drop, animation framework, AJAX controls, DOM utilities and unit testing. Add-on for the Prototype library. See http://script.aculo.us/ )
For an exhaustive list, including XWiki internal libraries, see FrontendResources
Front-end components should rely on components provided by those libraries as much as possible.
The introduction of new libraries should go through a vote on XWiki devs list. Only libraries which bring functionalities that none of the already provided external or internal libraries do are likely to be considered.
XWiki Namespacing
All XWiki's JavaScript code should be under the XWiki namespace. A good practice is that each script tests the existence of the XWiki object before adding its methods and objects :
XWiki = new Object();
}
Methods, classes and properties that have sense only in one module should be created under a module object of the XWiki object.
Example:
XWiki.dataEditors = new Object();
}
XWiki.dataEditors.XPropertyOrdering = Class.create({
// [snip]
});
Methods, classes and properties that have sense in all XWiki pages can be considered generic and be create directly under the XWiki object.
Example:
* Build a resource object from a wiki resource descriptor (aka fullName).
*/
XWiki.getResource = function(fullName) {
// [snip]
}
Backward compatibility and deprecation
As for back-end development, we should take care of backward compatibility. There are applications developed on top of XWiki that uses its JavaScript APIs. The rule for deprecating a JavaScript API (be it an object or a method of an object) is to move or write code to maintain compatibility in the compatibility.js file under the xwiki folder. We should always wrap deprecated code to log its usages. This will make the life of applications developers much easier.
Example of deprecation code:
* Deprecated since 1.9M2
*/
window.displayDocExtra = XWiki.displayDocExtra;
window.displayDocExtra = window.displayDocExtra.wrap(
function(){
warn("window.displayDocExtra is deprecated since XWiki 1.9M2. Use XWiki.displayDocExtra instead.");
var args = $A(arguments), proceed = args.shift();
return proceed.apply(window, args);
}
);
Bug Reporting
The bug reporting system resides at http://jira.xwiki.org/
XWiki.org Rules
Some rules to follow when making modifications on xwiki.org.
Don't remove important pages when they are moved
Rationale: Users will save links and when they navigate to them later on these links will be broken.
Solution: Add a redirect script to redirect to the new page
Implementation: Use this script:
{{velocity}}
$response.sendRedirect($xwiki.getURL("newSpace.newPage"))
{{/velocity}}
Don't use URLs for links to *.xwiki.org
Rationale: If we change the URL format or the domain the links will be broken
Solution: Use the wiki:Space.Name notation