S T R U C T O R I Z E R - User Guide
Diagram > Outsourcing

Outsourcing of elements to a subroutine

Since release 3.27 you may select a subset of your diagram and automatically outsource it to a new subroutine just in a flash!

Imagine the following example of a statistical calculation. It starts with the manual input of some numerical values, then computes their average and finally derives the standard deviation.

You may want to decompose this algorithm. Let's start with the standard deviation. Select all elements involved in this part of the computation:

Outsourcing demo - the original program

To convert the selected part into a subroutine you may:

  • select menu item "DiagramOutsourcing icon Outsource",
  • select context menu item "Outsourcing icon Outsource", or
  • enter <Ctrl><F11>.

Outsourcing demo - menu item Outsource

You will simply be prompted for a routine name:

Outsourcing demo - the name prompter

That's all what you have to do (most times, at least)! Structorizer will automatically analyze what arguments the routine needs and whether it is to return a value, then it will move the elements to the new routine created with this signature and also push the routine diagram to the Arranger. If the main diagram had not been in the Arranger before then it will be pushed there, too:

Outsourcing demo - the created subroutine for standard deviation

In the original diagram, the selected elements will have been substituted with the respective routine call. The replacing CALL element is automatically selected (and hence highlighted). Note that the result is immediately ready for execution!

If the parent diagram hadn't resided in the Arranger then a new group will be created named after it. The new subroutine diagram will automatically join all arrangement groups its parent diagram has been member of (see the red box in the screenshot below).

Outsourcing demo - the odified main algorithm

Looks nice? Well, but what about diagram regions that produce more than a single value, which other parts of the algorithm rely on? Let's try with the input part next — it introduces both the count variable and the readings array, which are both used by subsequent code:

Outsourcing demo - outsourcing the input sequence

Rather than creating and sharing a dedicated record (struct) type for exactly this routine return value, the converter makes use of the ability to fill arrays ad-hoc with values of different types (which is still simpler in Structorizer, but also bound to cause trouble on export to several programming languages, on the other hand).

In Arranger, the new subroutine will also be member of the arrangement group (the bounding box of which can be visualised by switching on the "Show groups" checkbox):

Outsourcing demo - routine with two results

And how is the CALL integrated in the main program? Let's have a look:

Outsourcing demo - call of a routine with several results

As you can see, an array variable with a generic name is introduced to receive the values from the routine, then the values are extracted one by one and put into the actual target variables. (This method may not look so nice but is very effective in Structorizer. We have to admit, of course, that it may cause trouble on code export to some strictly typed languages, where you would have to make use of record/struct types instead. A future release might make use of the record concept already introduced with release 3.27 here.)

Consequently, outsourcing the average calculation is just as easy as before:

Outsourcing demo - outsourcing the average calculation

So we get the third subroutine in a blink, too.

Outsourcing demo - the outsourced average calculation

The main program has shrunk a lot, this way:

Outsourcing demo - main statistics program after three outsourcings

It should not be necessary to mention that the outsourcing can of course be undone in the main routine (and redone etc.). The undoing in the parent diagram will not delete the created subroutines, however. You may simply remove ("drop") them if you want to get rid of them.

Note, on the other hand, that the emerged group of diagrams is consistent now. It is ready to be saved as arrangement, simply by selecting the group entry in the Arranger Index (right panel) and clicking the "Save changes" item in the context menu. You will be offered to store the group either as compressed archive or as a set of nsd files with a referencing arrangement list file:

Outsourcing demo - saving the group

Admittedly, this was only half the truth - there are cases where Structorizer may not cope with correctly identifying the needed parameters and result values. Then you will have to accomplish the result yourself. But we think that even in these cases the "Outsourcing" function will facilitate your job to decompose an algorithm grown too complex. Let's see an example in the following section.

Outsourcing with record types or includables involved

Consider the following algorithm, which simply derives a slightly modified date from a given date (without calendar corrections). Here a record type is involved, which the main program and the outsourced subroutine (from the selected elements) will have to share. You start the outsourcing as described above:

Outsourcing with record types

But Structorizer detects that the type Date defined in the main program must also be known to the subroutine diagram and thus decides that it has to be tranferred to an Includable diagram that both main and subroutine need to include. Therefore you will be asked for a name for that additional diagram:

Outsourcing - includable name query

After having commited the question, you will obtain two new diagrams, the includable and the subroutine:

Outsourcing with includable (Arranger view)

The main program will have changed as follows:

Defective main after outsourcing with record variable

As you can see in the Analyser report list, the result is not quite correct. A record variable cannot simply be introduced by assignment (unless the assigned value is a record initializer). So we must re-introduce a declaration like the one moved to the subroutine (where it is also necessary, so it wouldn't have helped just not to select the declaration before outsourcing — in that case the subroutine would have been defective instead). For the current version of Structorizer an automatic solution of this situation is still slightly too complex.

Main progam after outsourcing and manual correction

By the way: If the record type had already been included by the main routine (instead of having been defined locally) before outsourcing, however, then the subroutine would have inherited that include item automatically without asking.

Remark with respect to the arrangement groups introduced with release 3.29: On outsourcing, Structorizer ensures that the derived subroutine and a possible includable diagram will automatically be added to all groups the originating diagram is member of, such that consistency is preserved.

Counter-indications against outsourcing

There are algorithm subsets, however, which cannot easily be outsourced. Not surprisingly, they are usually provoked by unstructured diagram elements like Jumps (EXITs). If the selected region of the diagram contains EXIT elements, which intend to direct the control flow to targets outside the selection then we get in deep trouble. Look at the following nonsense example. It contains a CASE selection with several kinds of outbreaking elements — exiting the inner loop, the outer loop, the entire application, or the current routine or program, respectively:

Outsourcing demo - diagram with compromising jumps

If we liked to outsource the selected elements then three of the Jumps point outwards the subset, only the empty Jump (equivalent to leave) has a target inside the selection: the input instruction beneath the FOR loop. The exit command is not a problem, either — its semantics is independent of its location, it will always abort the entire execution. With the 2-level leave it is different: its target is the REPEAT loop, which will be outside the routine and hence unreachable, the leave 2 instruction is going to be illegal therefore. The return instruction, on the other hand, will change its semantics drastically: Instead of ending the outer program it would now just leave the subroutine, this way compromising the program logic. (And there is no easy way to maintain or restore the original logic.)

Structorizer tries to detect such cases and vividly warn off outsourcing element sets of that kind:

Outsourcing demo - warning on problematic Jumps

If you really know what you do and you have an idea how to mend the defects provoked by the outsourcing then you may go on, otherwise you better back off.

Note that Jump elements of type throw (exit on error) don't usually cause trouble because the TRY context of the replacing CALL element remains the same.