generated code should not checked into a VersionControlSystem (CVS, SVN, GiT)

Inside a MDSD (ModelDrivenSoftwareDevelopment) project there are different types of code (see also Heiko Behrens article)

Manuelly written code

Code never be generated, always manually written. This can be some base framework classes or code only used at some places not worth to generate like Utility- or Helper classes.

Generated unchanged code

Such code will be always generated and never changed manually. Classes will be re.generated at each run of the generator – existing files are overwritten or destroyed before.

Generated but editable code

This is code where its useful or ecpected that the generated code will be changed or extended. If files exist, they will not be overwritten – new files will be added and generated first time. (generate-once)

Generation Gap Pattern

The main problem with generated code is always how to combine or separate generated code and manually changed / extended code. That’s the point where in most cases the Generation Gap Pattern will be used:

Generated classes will be generated into a directory which is cleared before generation. Subclasses will only generated first time into another directory where they can be changed.

In practise some problems happen – per ex. “Ghost Classes” after refactorings / renaming. Also you cannot differ between generated and changed Subclasses – so all will be checked into VersionControlSystem.

To make this more practicable, Heiko Behrens describes „Conditional Generation“ where generated and changed Classes are clearly separated. oAW Workflow can use a “Vetostrategy”: Before generating an artifact it will be tested if there’s already a changed artifact into another direcrtory – and if found no new generation happens.

This is described in detail in Heiko Behrens article „Generation Gap Pattern“. If you dont have read this article, please do now. I expect that you know the VetoStrategies described by Heiko !

Thanks to Heiko Behrens I got the information about oAW „VetoStrategy“ which was new for me – never read about it in the docs or forum. Now I was inspired to find some solutions for my project better then previous workarounds.

At first I must say, that I have some problems to use the „Generation Gap Pattern“ as generic pattern if generated code also has to be modified in MDSD projects. Working as softwarearchitect and designing an entity model (esp. in the domain of Enterprise Business Applications), I very carefully think about inheritance strategies / hierarchies. (esp. if all must be mapped from Hibernate or EclipseLink to a database)

… then the inheritance – hierarchy becomes “dirty” from my point of view. In big projects suddenly hundreds of classes are “twice” – and the only reason is technically: because its a modeldriven project ?

I only want to use abstract / concrete classes or super- / subclasses if I need them from my use-cases or software architecture, but not because I’m using a generator – framework.

As always using a pattern you should ask: is it the right pattern or are there other ways to reach the goal ?

From my opinion: the “Generation Gap Pattern” helps in many cases, but not always. Heiko Behrens shows how the use of “VetoStrategies” in oAW workflows will help handling the files and folders, but its no solution to avoid getting many classes twice which bloats the architecture.

Protected Areas

So we again have to find an answer how to separate generated and manually written code without breaking the rules of best practises in MDSD projects.

There is another way: „ProtectedAreas“. STOP crying 😉 please read ahead – I try to use protected areas something different then normaly !

What are „Protected Areas“ ?

If there are some parts of the code where its allowed to modify or extend, then the Begin and the End are marked as special comments identified by an unique ID. Inside these protected areas the default code will be generated and the area will be marked as DISABLED, so if regenerating it will be overwritten.

If a developer modifies / extends the content af a protected region, then this region has to be ENABLED and the changes are protected after regeneration. Using „Protected Areas“ the structure and inheritance of your classes remain unchanged – exact the same as using it without a generator.

How are „Protected Areas“ normaly used ?

Whats the drawback ?

Now classes have protected areas, can be overwritten if regenerated but then they will be checked into VersionControlSystem – thats bad, because there are many classes without changes: only generated content. That breaks the rule “never check-in generated code”.

Also you dont see which classes have changes and which are untouched after generation.

Protected Regions using VetoRedirectStrategie

Here’s my solution

at start of generator-workflow clear „src-gen“ and „veto“

generator scannes „src-gen-pr“ and caches ENABLED ProtectedAreas

„only-generated“ classes will be generated into „src-gen“, also classes with „ProtectedRegions“ without a veto

classes with ENABLED „ProtectedRegions“ are stored in „src-gen-pr“

while generating the generator checks using “VetoStrategy” if a class is already in „src-gen-pr“. If found, then the generated output is redirected into „veto“ directory where the new generated class together with ENABLED ProtectedRegions (from cache) is written to

as last step of generation the files from „veto“ are compared with corresponding files from „src-gen-pr“. Only if they differ, the new ones will be copied into „src-gen-pr“. Now we are sure only really changed files will get a new modified flag and checked into VCS.

The Workflow

Generated-only and manually changed code now is clearly separated. Only changed artifacts will be commited into VCS and the Inheritance structure is unchanged.

Of course I have to watch, that a developer changing „Protected Regions“ doesnt forget to activate them (ENABLED) and to move the file into „src-gen-pr“ if not already there.

If you want to check if a developer ENABLED a protected region, but forgets to move into „src-gen-pr“ you simply can add a step at start of your workflow: scan „src-gen-pr“ for protected regions – if some enabled are found, stop workflow with warning.

If you want to check if a developer forgots to enable a protected region after making some changes, you can include something like a checksum into the region and write a component to test these before starting to generate.

All is possible you see – but its of course a matter of time: each extra step will slowdown generation performance.

(Tip: sometimes the Local History of Eclipse helps – but there’s currently a bug: oAW generator overwrites the last Local History entry instead of inserting a new)

Inside the default code of a „ProtectedRegion“ I always insert a comment like:

Disabled Protected Region:

Enabled Protected Region:

Some Tech Infos HowTo implement a RedirectVetostrategie

tested using:

Eclipse 3.5M6

openArchitectureWare 4.3.1 (If you already use the plugins from Eclipse Modeling Project you have to change the namespace)