Those frantic whispers scream.
I only see their shadow in you,
And I urge you to hear,
The still music in me.
We are apart together.
We can find key information. Key information is whatever anyone needs to do their work.
So what? What can we do to achieve this blissful informed state? What are you going to go about it?
People have many opportunities to document. We make the choice to document, or not, all the time…
…when do we choose to document? Usually when we are forced to, or the ‘doing’ of a task is assisted by a document…
…when do we want to keep a document? There is no easy answer, something will be useful if it is ever used. Beyond the base documentation requirements of our workplace, we are empowered to capture information based on our judgement of importance balancing cost and value.
What does it take to move documentation, that was functional during a task, to something suitable for keeping? Effort.
Ideally we want to reduce the effort overhead to zero so that we have a ‘documentation reflex’ – documentation that happens through work habits. Ask yourself if what you are doing is worth documenting. If it is, are you capturing it in a way that minimises your effort to document it?
The effort to change documents should also be minimal. Tools can help or hinder:
In most cases authorship should be shared so that everyone feels able to make a change. There is a cost to update ease when adding ceremony to a document (eg prescribing a certain format, or requiring a set of signatures). It is often the case that these things are added to stop a document from being updated – what is your change control policy? Only secure things from change with a reason, because change is not inherently bad.
In addition to simple opportunities, we may have requirements for specific documentation. These requirements are usually more formal, and are made evident through business or process requirements…
These become project deliverables in their own right – you just have to sit down and put effort into creating them.
When capturing documents, it is important to note that some are created, and others evolve. Some documentation will record a moment in time (like a diary), for example: options analysis, a decision, or meeting minutes. Whereas others will need constant change, for example: application training, comments within the source code, or a process checklist.
There is a grey area for what is a ‘created’ or ‘evolving’ document. For example the user interface design captured via a whiteboard. If the user requests a change, should the already documented user interface be revisited, or just the change request be captured? The choice in this case comes back to what you have identified as important to capture. Do you accept the initial design and change requests as diary-like documents, with the built system reflecting the current user interface? Or do you need to have an up-to-date model of the user interface?
Making the choice to have an evolving document is more expensive. A guideline can be to make a ‘created’ document the default output, then only evolve that document as a considered decision.
What really constitutes a helpful set of documents for software development? That is possibly a poor choice of words as there is not even a need to restrict ourselves to formal ‘paper’ documents for communication.
Have you ever heard:
Statements that probably indicate dysfunctional documentation, but not without cause, there are a number of challenges:
Looking at those challenges we can probably state the communication vision:
We can find key information.
So what is key information?
Key information is whatever anyone needs to do their work. Quite a broad scope, and probably the point of most disagreement in various documentation strategy discussions. How do we agree on a balancing point for the documentation content? It is too expensive to capture everything that anyone might ever need. So, how much will be captured so that it does not unduly hinder what we are doing now…or next year?
A helpful question to ask is: Who is the audience and what is their likely need?
OK, what tactics can be employed to capture key information?
Fine, we have our key information and it is valuable, how do I find it?
An example:
A software system is developed and maintained.
Identified audiences and their needs:
Communication Strategy:
To facilitate communication an intranet site is created which includes automatically produced documents (eg automated test output, automatic code documentation), a wiki is setup to store virtual artifacts, a forum is setup for the system users to ask questions and provide general feedback. A search engine indexes the whole lot, so the team can find information.
Note the focus is on valuable communication, rather than extensive documentation.
After discussing a JDBC ResultSet mapper recently. I’ve put up an initial solution at sourceforge.
In building a better bean processor I discussed some ideas for reflection mapping of a ResultSet to Object.
This time around we can look at a solution design.
Here is a UML diagram of the solution (click on the image for a bigger, clearer picture).
Note that the diagram contains a couple of example extensions for the DBUtils BeanProcessor and Spring RowCallbackHandler. One of the requirements for the ResultSetMapper is that it can be easily be plugged into these bigger frameworks.
Data mapping will occur against ResultSet columns and Object fields.
By default the Object field will require the @MapToData annotation, though this requirement may be turned on/off with ResultSetMapper.setAnnotationRequired(true/false). Why have it off? There would be no requirement to add an empty ‘@MapToData’ annotation. So, why have it on? The source code contains a documentary ‘@MapToData’ annotation to indicate that some magic is being performed on the field.
The mapping will use a NameMatcher to compare the field name with the column name (unless a MapToData.columnAlias is specified). A default NameMatcher – NameConverter – will use simple camelCase to under_score matching.
Data mapping will occur, in order of priority:
Inheritance requires that many target classes may be supplied to the ResultSetMapper. However, this means that there must be some way of choosing which target to create. To allow selection of target objects, an ObjectValidator will be used – every type of target class will be constructed from the ResultSet and passed to the ObjectValidator. (The default validator always returns true.)
The advantage of this approach is that the programmer only deals in their domain object, but it does require an overhead of creating extra objects for validation.
Solving this problem requires a couple of technical problem answers:
So the example domain from the previous post would now be:
// lang java
public abstract class Jelly {
@MapToData
Long jellyId;
@MapToData
String jellyType;
}
public class JellyAttribute {
@MapToData
String name;
@MapToData
String value;
}
public class JellyCompany {
@MapToData
String companyName;
@MapToData
String address;
}
public class JellyBean extends Jelly {
@MapToData
String targetMarket;
@MapToData
BigDecimal weight;
@MapToData (columnPrefix="flavour_", isAggregateTarget = true)
JellyAttribute flavour;
@MapToData (columnPrefix="colour_", isAggregateTarget = true)
JellyAttribute colour;
@MapToData (isAggregateTarget = true)
JellyCompany company;
}
public class JellyCup extends Jelly {
@MapToData
String productName;
@MapToData ( columnAliases = { "cup_volume" } )
BigDecimal volume;
@MapToData (isAggregateTarget = true)
JellyAttribute shape;
}
public class JellyCupAndSpoon extends JellyCup {
@MapToData
String spoonMaterial;
@MapToData
BigDecimal spoonLength;
}
At the moment I’m coding up a ‘BeanMapper’. Something to automatically transform a ResultSet into a JavaBean object. (Why would you want to do this? Write and maintain less code will probably do as a worthwhile cause.)
The DBUtils Apache commons project has a BeanProcessor that does a basic job. It is good for a simple mapping, however it does not meet the following challenges:
Challenge #1 can occur whenever inheritance is used, Challenges #2 and #3 are linked with improving performance (though I’m finding it difficult to imagine a scenario for #3 right now).
As well as the challenges there are some improvements that may be made:
So what would my ideal mapping solution look like in operation?
I would have JDBC DAO that maps a variable ResultSet automatically to a set of target classes…
// lang java
public interface JellyDAO {
public Jelly find(Long jellyId);
public List find(FindRequest findRequest);
}
public class JellyDAOJdbc implements JellyDAO {
List targetClasses;
List aggregateClasses;
BeanMapper beanMapper;
public jellyDAOJdbc() {
// The ResultSet may contain data for
// any of the following target classes.
targetClasses = new ArrayList();
targetClasses.add(JellyBean.class);
targetClasses.add(JellyCup.class);
targetClasses.add(JellyCupAndSpoon.class);
// The Target classes may contain the following classes
// that may also come across in the ResultSet.
aggregateClasses = new ArrayList();
aggregateClasses.add(JellyAttribute.class);
aggregateClasses.add(JellyCompany.class);
//
beanMapper = new BeanMapper(targetClasses, aggregateClasses);
}
private Jelly processResultSetRow(ResultSet resultSet) {
// Map the ResultSet to a Jelly class.
Jelly jelly = (Jelly) beanMapper.toBean(resultSet);
return jelly;
}
private List finder() {
// Obtain a ResultSet..
// Loop through result set..
{
jellyList.add(processResultSetRow(resultSet));
}
return jellyList;
}
}
The Jelly domain model might be something like…
// lang java
public abstract class Jelly {
Long jellyId;
String jellyType;
}
public class JellyAttribute {
String name;
String value;
}
public class JellyCompany {
String companyName;
String address;
}
public class JellyBean extends Jelly {
String targetMarket;
BigDecimal weight;
JellyAttribute flavour;
JellyAttribute colour;
JellyCompany company;
}
public class JellyCup extends Jelly {
String productName;
BigDecimal volume;
JellyAttribute shape;
}
public class JellyCupAndSpoon extends JellyCup {
String spoonMaterial;
BigDecimal spoonLength;
}
public class JellyRepository {
public Jelly find(Long jellyId);
public List find(FindRequest findRequest);
}
I would also have a database view or stored procedure with the following signature…
jelly_id, jelly_type, target_market, product_name,
spoon_material, spoon_length, cup_volume, flavour_name,
flavour_value, colour_name, colour_value, company_name,
company_address, shape_name, shape_value
The data was not longer required.
First came the horseman named Delete, he said in a thunderous voice, “You data will soon be gone.”
The user replied, “But what if I want to see it again.”
Next came the horseman named Trash, she said, “You data will be gone soon, but if you sign up for this simple insurance policy, it can be brought back – if you invoke the policy quickly.”
The user replied, “But I may want it at any time in the future.”
Next came the horseman named Archive, he said philosophically, “You data will not be available, except when it is.”
The user replied, “But I want it to be available at any time.”
Next came the horseman named Retire, and she said, “You’ve put effort into your data, you don’t want it disappearing. It may not be as active as it once was, but with good planning you may keep it working for you always.”
The user smiled and was happy, “Yes, I want them all.”
A few months ago, while considering the design of a new project…the issue occuping my thoughts was in the differences in possible design technologies. Two directions: one a relational database, two an object model. Why was it an issue? How are the designs kept in sync? Where does a developer turn to first if they want to make a change to the core design of an application that is expressed in many places (at least the relational database and the objects)?
So, I considered the idea of a ‘domain model’, turned it around a few times and thought it could be a good thing. Not only would it be the common language between various technical areas, if it was expressed in business terms, the testers and business people could also be involved in a discussion around it, or use it. Convinced this was something good, I Googled ‘domain model’ and found that 1. yes it was a good idea and 2. someone had written a book about it. I ordered Domain Driven Design by Eric Evans and have been reading through it.
Good book (pity it goes for the fashionable ‘xxx driven xxx’ title, which also sounds confusingly similar to Model Driven Development). It has clarified many things for me, and supported other thoughts, like the ‘Ubiquitous Language’ pattern… “A project faces serious problems when its language is fractured.”
Many standard patterns for domain components are listed and discussed in the book. One pattern is called a Repository. It troubled me because elsewhere in the world of development there is a DAO (Data Access Object) pattern. Why was I concerned? Because the two patterns initially seemed to be the same, which should be used? This is what I understand now.
Repository Responsibilities
DAO Responsibilities
Example: the domain model might represent plants, one entity may be a Tree which has an associated TreeRepository.
Implementation 1:
There is a database table in the background with TREE_ID, LATITUDE, LONGITUDE, HEIGHT columns. Perhaps we code TreeRepository as an interface which a JDBC DAO implements.
Implementation 2:
We now access to a location Service which stores the location of things. We also have a database table with TREE_ID, LOCATION_ID, HEIGHT columns. Perhaps we implement a TreeRepository that accesses both the location service and JDBC DAO to construct a full Tree object.
We recently bought a roomba robot vacuum cleaner…it gives us back some time. One of the best bits of technology that we have purchased lately.
It started me thinking about the mid nineties when I signed up with my first ISP and jumped into the internet and the early eighties when my father bought home a new Apple II computer.
Wonder what consumer robots will be like in 10 years?
Also, I wonder what will be ‘introduced’ in the next 10 year hop – nano-bots, bio-tech?