Say I have some classes that are using the latest ABL keywords. In particular a new keyword or a keyword that replaces another UDF. Suppose that I want this code to run in multiple versions (let's say 10.2B and later).
One approach is to create a branch per supported OE version, and make sure the code is tailored to that OE version. Another approach is to create an include file which can conditionally include stuff based on the PROVERSION or KEYWORD-ALL keywords. There might be other conditional switches (maybe a &GLOBAL-DEFINE of my own that acts as a master switch).
In some cases, I will have to branch. For instance, if I am using the JsonObject classes (which are only in 11.0+), the code in 10.2B cannot be easily conditionally included/excluded.
However, there are cases where I can write an include which can use either the new ABL GET-FOO() statement or my fnGetFoo() UDF.
I see the conditional approach as being useful because it means I only have to maintain a single branch of this code. It can get mighty unreadable and potentially unwieldy.
We are using a mix of branches and conditional compilation: mostly based on ProVersion, but also for GUI vs. TTY code (typically using .NET APIs vs. OS-COMMAND etc.)
Minor diffs are easily maintained using conditional compile.
When a whole module (like our BPM Interface, WebServices vs. native interface) is fundamentally different in 10.2B vs. 11.x two different branches create far simpler code.
Visual Designer code requires also branches, when using new attributes in 11.x, like office2010 style, .NET 4.0 types in resx files etc.. You can't use conditional compilation in InitializeComponents or resx files.
An SCM tool with great merging capabilities is key, I'd be lost without Perforce!=
One of the virtues of branching is that it is more painful ... which means that when one gets to a point that one no longer has to support the earlier version, one can abandon it and thereby cleanse the code base of the old stuff. The problem with conditional compilation is that it tends to live on forever garbaging up the code and no one ever cleans it up.
Which said, a lot depends on context. If, like Mike, one is providing a code base which might get used across a lot of versions, then having a single code base has some virtue whenever the differences are minor since one can always acquire a new client with an older version. But, if one is creating a product for one's customer base and one is in a position to keep them current on releases, then branching and abandonment seems indicated.
Didn't you mean to say "less painful"?
> Am 24.06.2014 um 20:12 schrieb "Thomas Mercer-Hursh" :
> One of the virtues of branching is that it is more painful ..
No, more painful, particularly if one has to keep adding every new change to every branch and then figuring out whether it needs to be modified in that version and so forth.
I'm not thinking of the SCM tool. I am thinking that if I have a body of code that has 4 branches for different versions, each addition or change that I make I have to make that decision about whether or not it has to be branched and if it needs to be branched then I have to come up with new pieces for each relevant branch. I suppose one has to consider that for in situ version checks too, but it seems that there is more overhead with doing the branching.
Mostly, I don't like doing either one!
Flag this post as spam/abuse.
“Mostly, I don't like doing either one!”
But that’s not the question here and thus irrelevant in this thread – unless you are in the luxury situation of either not requiring latest language features or getting all your customers to upgrade to 11.3 or 11.4 at once.
The issue I was trying to make with respect to upgrades is that if one has a customer population which one can keep reasonably current, like just 2 or maybe 3 versions at a time, then one of the virtues of branches is that when one leaves behind a particular version, one can simply abandon those branches and the code is essentially automatically cleaned of the version kludge. Whereas, if one has proversion tests and the like buried in the code, they are likely to persist long past where they are needed.
I agree with Mike. We use branches for each version , and as long as the scm tool manages repeated merging, (which , let's face it, most of them do these days) the problem goes away.
You just need to be careful of the workflow. Get that right, it's a doddle.
We use conditional compilation for small changes, but have a policy of always wrapping these conditional entries in some special comment markup & listing all such changes in a master text file.
This means that when we drop support for a version, we can quickly find all special code for the old version & strip it out (we've also got a policy that you add the conditional code in a way that makes it easy to strip out).
In practice, this has worked out pretty well so far.
For larger changes we would use branches (we use Mercurial, so merging changes between branches is cheap) - as Thomas said, this makes it very cheap to drop an old version.