In Branching in ABAP? I described our approach to manage concurring requests for program changes using a branching-like technique.
After 6 months of “living” this approach, I would like to give an overview of our experiences.
Things to be aware of
New methods, attributes and types in classes
Instead of creating them in our branched sub-class, we create them in the master and pass them immediately to the productive system. Since they are not uses if not in the sub class, they do not influence the behavior of the class
Big program sources
We had some really big reports containing many local classes. Merging is very annoying here. We decided, in accordance with the SAP programming guidelines, to split such sources into includes, one for each: class def, class imp, all report events, data declaration, all screen modules.
Master changes in report includes
A change of the master branch in includes can lead to syntax errors in branches – especially when one adds new methods or attributes. Always make a check of the branched versions around when doing this.
Dictionary objects, messages and others
We create and modify those non-source objects directly in the master branch and put them to prod system as soon as possible. Keeping track of different dict types is a mess. When heavy modifications occur, we use new objects instead of modifying the existing ones
Things we introduced
We started leaving the sources in the original packages. But since we use also a newly programmed “branching cockpit”, it comes handy to put all branches in dedicated packages. We did it like this:
- one general branching package
- sub-package for each developer
This keeps it simple to have an overview of all branched objects. Since the objects vanish after merging, these packages will not overwhelm with objects.
One of our programmers wrote a beautiful cockpit transaction that selects all branches and objects related and offers developer notes to be stored and integration of merging as well as creating new objects following the naming convention. Each branch has a dataset in a z-table containing also a status, creation and change dates, responsible person and so on
In a simple case, a new transaction with the branch name in it can be given to the user for testing it. But when it comes to changes that are deeply nested in several programs, this is difficult. So we created a user parameter for the actual branch. Then we coded a class that determines the possible name of a class or a program source within this branch. Whenever we want to be able to call branched versions of classes, we use this class to instantiate the object. It goes like this:
zcl_dv04_branch=>get_branch_name( exporting iv_name = 'ZCL_CS01_CONF2_TABLE' " 30 Characters importing ev_name_br = data(lv_type) " 30 Characters ). create object mo_conf_table type (lv_type) exporting * io_data = " Datenobjekt für die Rückmeldetabelle io_model = me iv_factory_calendar = mv_factory_calendar iv_present = abap_true. " allgemeines flag
The method call constructs the name of the given class in the branch and checks the existence. If existing, it returns the branch type, if not, it returns the original type. There are similar calls for reports and function modules. Here’s the coding of the method:
method GET_BRANCH_NAME. data lv_branch(3). get parameter id 'ZDV04_BRANCH' field lv_branch. if lv_branch is not initial. * i.e. 'ZCL_CLASS_TO_BRANCH___________ or 'ZP_PRINT_PROGAM_______________'. ev_name_br = iv_name. translate ev_name_br using ' _'. data(lv_offset) = 30 - strlen( lv_branch ). ev_name_br+lv_offset = lv_branch. data(lv_pattern) = ev_name_br && '%'. select count(*) from trdir where name like @lv_pattern into @data(lv_found). if lv_found = 0. ev_name_br = iv_name. endif. else. ev_name_br = iv_name. endif. endmethod.
We really are able to manage simultaneous program changes now, although there are cases in which we do not use branching because of unfavourable constellations in the dependencies of older program coding. Merging is a challenging job, but the advantages outweigh this.