While doing some DITA training recently for a client I ran across an idea that struck me as being a good way to avoid spaghetti code. In retrospect, it’s one of those obvious “why didn’t I think of that?” ideas: a specialized topic just for holding conref-able text. But first, I ought to explain why this strikes me as being a good idea.
What is Spaghetti Code?
DITA is all about reuse. There’s potentially reuse at three levels: map, topic and sub-topic. At the map level it is easy to take a “chaptermap” from an existing ditamap and republish that as a separate document. Topics can easily be repurposed in new documents. Within topics, the conref mechanism is designed to share content at the paragraph or phrase level. There are two potential problems with using conrefs however: a writer may change (either deliberately or inadvertently) the content of a conref target directly, or the change is made to content which happens to be within a nested conref target. In both cases the change is propagated to whatever topics are referencing them, and unless you using an XML editor that can resolve conrefs in a target, you may not be aware that a change has been made until you look at your output. This is how spaghetti code develops: multiple layers of conrefs point to various topics contained in multiple maps. It gets increasingly hard to manage over time and should be avoided.
When you have spaghetti DITA conref-ed code, writers begin to get overly cautious about making changes to existing topics if they are unable to easily check the dependencies of the content of that topic on other topics that are conref-ing it. (This is why it is good to have a CCMS capable of checking topic dependencies).
Spaghetti code in DITA is a well-known issue: it is talked about in the “Content Reuse” chapter in the excellent DITA Best Practices book, and I attended an excellent presentation hosted by Jang Graat at the last DITA North America conference I was at that talked about the same issue. The solution they suggest is both simple and straightforward: don’t create spaghetti code in the first place. You do this by making sure that you keep all of your conref-able content in separate topics and maps that will not be published. This way all of the conref point one-way to these topics only and spaghetti DITA code does not develop with your conrefs.
The model this sets up is clear and elegant: simply create maps that contain all of the content that you intend to conref. If you are an Information Architect (or a “Documentation Architect“) find all of the content that gets reused in this manner and construct maps containing topics containing only reusable content. When new content is created and it is likely that it will be reused in future versions of a document, those new sections are added to the conref-only target topics in the conref-able map.
The additional twist to this strategy that I recently ran across was to create a specialized topic type for holding these conref-able target content topics. This helps to ensure that they can hold any type of content from the other topic types for reuse anywhere. It’s a terrific idea, since you gain extra flexibility with the conref-able content that can be stuffed into the topic, which can be used in any of the other main topic types.
The first instance I ran across of this idea was in a recent version of the Ixiasoft DITA CMS in a deployment done for a client. It turns out that it is a re-implementation of an idea that goes back at least to 2006 when it was introduced as the ditacomponent.dtd
within the XMetaL XML editor. In the implementation I saw it was put into a new topic type called reusable-content. The purpose of both of these is to have a separate topic type whose content cannot be directly published, and whose sole purpose is to be a repository for reusable conref-ed content. There are a couple of potential drawbacks: since it is not standard DITA some tweaking may be required when it comes to ensuring that output works smoothly, and if sharing content with other firms/organizations is paramount, you will need to ensure that your exported DITA files are “flattened” when it comes to their conrefs (i.e. conref-ed content is contained directly in the exported topic instead of as a conref). Still, it strikes me as being a good idea and one ripe for inclusion in a future DITA specification. It seems like the idea was considered way back when, but was nixed as it was seen as “enforcing a particular best practice for managing reuse“. Still, I think it would be nice to have it as available option that was also part of the standard DITA spec. It certainly makes a lot of sense to use this approach for any new implementation of DITA, as technical writers need to think and plan for sub-topic reuse rather than leaving it wide open, which so often results in spaghetti code.
Anything that gets authors to actively plan and write for sub-topic reuse is a good idea. I don’t know about you, but I prefer my spaghetti on a plate with tomato sauce, not in my code.
Nice post. Yes, this is really the way to go. It’s actually how things work in Trisoft by default. You can still create spaghetti code in Trisoft if you really want to, but it’s so easy to use dedicated topics for reusable content that there’s really no point.
One thought, though – wouldn’t a dita container topic offer the same kind of flexibility that you get from the kind of specialized topic you described?
http://docs.oasis-open.org/dita/v1.0/langspec/dita.html
I hadn’t realized that the Trisoft CMS uses a similar mechanism, so clearly the idea is widespread. I am surprised that a proposal for something more formal hasn’t made it into the DITA specification by now, since it seems like there are a number of takes on the subject, and over time things will simply become more divergent. I can understand the original idea for not wanting to prescribe only one solution back in 2006, but at this point it seems like the horse is long out of the gate…
And yes, you are right, a DITA container topic — one which would encompass all major topic types — would work, and in fact would be ideal. Am thinking less of “specializing” an existing major topic type (concept, reference or task) than of simply having an encompassing topic type parallel to the main topic types (so, “specialized” from the parent DITA topic, as you suggest) which is used solely for holding conref-able content.
The difficulty with using a DITA container topic is that its DTD must reference the declarations for each topic type and domain used in the content set. The default content types in the compound element won’t include a company’s own specializations unless someone thinks to extend the declarations. So it remains a best practice because the idea is workable, but not general.
The idea of central referencing goes by several names. I’m warming up to a term I learned from Mark Lewis of Quark: warehouse topics and maps.
You can actually simplify conditionality through swapping out of warehouse topics. If a paragraph can hold either of Linux and Windows-specific information, then rather than putting both content within the paragraph with conditional phrase wrappers keeping the parts separate, just conref the paragraph and have two warehouse topics by the same name, each with the same target paragraph but with different content in the respective paragraph. At run time, provide the appropriate warehouse topic for the build set. The method obviously only applies to mutually exclusive content, so use it as appropriate.