My Latest Programming-Technique Improvements
Tue Apr 23 11:34:58 EDT 2013
Over the past couple weeks, I've been trying out some new things to make my code a bit cleaner and I've been having a good time of it, so I figured I'd write up a quick summary.
Composed Method
First and foremost, I've been trying out the Composed Method of programming. This is not a new idea - indeed, it's a pretty direct application of general refactoring - but the slight perspective change from "factor out reused code" to starting out with clean, small blocks has been a pleasant switch. The gist of the idea is that, rather than writing a giant, LotusScript-agent-style block of code first and then breaking out individual components after the fact, you think in terms of small, discrete operations that you can name. The result is that your primary "control" methods end up very descriptive and easy to follow, consisting primarily of ordered phrases specifically saying what's going on. I encourage you to search around and familiarize yourself with the technique.
import static
Java's import static
statement is a method-level analog to the normal import
statement: it lets you make static methods of classes available for easy calling without having to specify the surrounding class name. Most of the examples you'll see (like those on the linked docs) focus on the Math
class, which makes sense, but it applies extremely well to XPages programming. Pretty much every app should have a JSFUtil
class floating around, and most should also use the ExtLibUtil
class for its convenience methods like getCurrentSession
:
import static com.ibm.xsp.extlib.util.ExtLibUtil.getSessionScope; import static com.ibm.xsp.extlib.util.ExtLibUtil.getCurrentSession; // ... getSessionScope().put("currentUser", getCurrentSession().getEffectiveUserName());
Night and day? Not really, but it's a little more convenient and easier to read.
Now, as the linked docs above indicate, import static
comes with a warning to use it cautiously. Part of this is Java's cultural aversion to concision, but it's also a good idea to not go too crazy. When the methods you're importing are clear in intent and unlikely to overlap with local ones (like those in ExtLibUtil), it makes sense, particularly because Designer/Eclipse allows you to hover over the method or hit F3 and see where it's defined.
createDocument
Since creating a document in the current database with a known set of fields is such a common action, I've taken a page from one of our extended methods in org.openntf.domino and have started using a createDocument
method that takes arbitrary pairs of keys and value and runs them through replaceItemValue, along with a helper method to allow for storing additional data types (since I'm still using the legacy API for these projects):
protected static Document createDocument(final Object... params) throws Exception { Document doc = ((Database)resolveVariable("database")).createDocument(); for(int i = 0; i < params.length; i += 2) { if(params[i] != null) { String key = params[i].toString(); if(!key.isEmpty()) { doc.replaceItemValue(key, toDominoFriendly(params[i+1])); } } } return doc; } protected static Object toDominoFriendly(final Object value) throws Exception { if(value == null) { return ""; } else if(value instanceof List) { Vector<Object> result = new Vector<Object>(((List<?>)value).size()); for(Object listObj : (List<?>)value) { result.add(toDominoFriendly(listObj)); } return result; } else if(value instanceof Date) { return ((Session)resolveVariable("session")).createDateTime((Date)value); } else if(value instanceof Calendar) { return ((Session)resolveVariable("session")).createDateTime((Calendar)value); } return value; }
In use, it looks like this:
Document request = createDocument( "Form", "Request", "Principal", getCurrentSession().getEffectiveUserName(), "StartDate", getNewRequestStartDate(), "EndDate", getNewRequestEndDate(), "Type", getNewRequestType() );
The result of these changes is that I'm writing less code and the intent of every line is much more clear. It also happens to be more fun, which never hurts.