The Code scope  ...



Code scope is what I call the distance evaluation between two different locations of Code. Not only the physical distance, at a Code Octets quantity point of view, but also at a human logical point of view. This concept is of major importance for Source organization, but it is never discussed, mainly because it is close to impossible to clearly describe.


Though, the logical and physical scope is the very true basis for Sources organizing.


All older programmers, pefectly know when to cut a chunk of Code into smaller Routines, and how to do it. But the truth is that this is the result of years of experience. Describing this is even more difficult, because this interacts with another  problem, which is to know under what form the separations will be done: Sub-Routines / Procedures / Macros... So let us see the different points one after another:



The Code length


There is no real consideration to give to the length of a Code Chunk, per se. If the organization is simple, mono-purpose, even if the Chunk is hundreds of Lines long, and if there is no reason for you to cut it in smaller pieces, do not do it. This is a very exceptional case.


Most often, even if there is no logical requirement for dividing a Chunk of code into Parts, natural Blocks appear to the eye, that can then be broken into as many called sub-Routines as you might desire. 


For example, if we have a long flow of Cases selections ('If' and friends), and that the treatments of the cases achieve in several screens of Source, the calls of each treatment through an independent Routine (that will be called from this given point only) is then accurate. This will have several advantages:

1) The whole Cases selections will hold in fewer screens, so the overview will be much better. 

2) The independent Routines will be easier to maintain and develop. 

3) Pointing out the Routine by Search features will be made easier. 

4) If later, along your developments, one given sub-Routine reveals to be possibly called from another Source location, it will be there, ready for reuse, at no or low adaptation cost.


Out of the simplest cases, long chunks of Source are painful to maintain. Not only because of the screen moves required for reading it, but also because of the overall logical events, that you will have to understand and master again, at each modification.



The logical organization


The 'Pretty' theory of programming regularly recommeds to build an organization Table (representation) of our Applications before we start writing anything. In the real world, this does not make any sense. When you begin a new Project, usually, you have not the beginning of an idea of what it will look like when finished. And if you have any, you can be sure that this idea will reveal itself mostly wrong, in the end.


Defining the overall structure of a Source, before writing it, is nevertheless possible, but very uncommon. This happens, for example, to professional programmers who always do the same kind of work, with a very high level of specific experience.


In normal conditions, the overall organization of a Source appears by itself all along the developments. The natural attitude with this (and the proper way to go), is to keep our mind continuously open to structuring and re-structuring. That is, re-write. Re-writing is not so killing as the reward is great. As soon as a development becomes painful, this is because of a lack of logical organization.


While writing, a good rule to be applied is that, each time a Block of Code can be given some Name, this is the time to make it an independent Routine. The time eaten by the call and by the ret counts for nop, and there is no reason for not doing it.

 If   you can name it? Well, do it! Isn't it easy enough to cut and paste, define a Label Name and add a ret?



The Module concept


Historically, Modular programing has been the very first step that has driven the languages evolution to the disaster state it actually is. This concept is tightly bound to Code-Reuse and to multi-Files Management of the Sources, and results in what everybody can see everyday: Slow and fat Applications, difficult to maintain, difficult to debug and... unreadable Sources.


Nevertheless, the Module concept basic definition is interesting and may be really useful in Mono-File and specific programing. We can define a 'Module' as: 


'A Module is a Set of Routines having a strong relationship between themselves and a low relationship with the other parts of the Application'.


As it is, this concept, derived from the Multi-File programing and of the Code-reuse procedural approach -which are the real hell- is very simple to understand and provides a very effective rule for the Sources logical scope definition. 



The Forms


As a whole, we have the choice between 3 forms of Sources organizations: Sub-Routine, Procedure, Macro. 


When to use each one and why?


As opposed to what you can see in many actual Demo Sources, the Procedure is not the default way for organizing Blocks of Code. Procedure -as opposed to simple sub-Routines- implement a Stack frame for Parameters and, eventually for Local Variables, Registers preservations and Local Tables. There is no reason to use a Procedure if you do not send any Parameter to it. More than this, sending Parameters on the Stack, to a Procedure, is not the only way to go, in Assembly. Often times, the direct definition of a couple of Registers before (and/or after) the call is much, faster and smaller. Procedures should be reserved for reusable chunks designed to be called from several locations, with different Parameters. This is a very interesting technique but it is not so often accurate.


The sub-Routine is the natural assembly Source organization unit. While the Procedures end with some EndP Macros restoring the Stack, the sub-Routines end with a simple ret. How to define the Parameters and elements used by a sub-Routine depends on what and when. The simple way is to set Registers to the expected Values or Pointers. As soon as these Registers attributions become difficult, for example, because of the required numbers of information, or because of lack of flexibility, this is time to use the second sub-Routines way: Variables in Memory, that the caller will set up, and that the Routine will use (or/and reverse). Despite its rigid organization, a Routine can be called from several locations of one Source. Nevertheless, if a sub-Routine really expects to be called from several points, it is much better to use a Procedure, in order to avoid development difficulties. Procedures are more flexible and secure than sub-Routines. Another great way for introducing flexibility in the sub-Routine technique, is to perform the Routine call through a Macro that holds the Parameters (in and/or out) adjustment. The usage is then made close as powerful and flexible as the one of Procedures.


The Macros concept introduces a choice problem: When to choose the Macro way? When to choose the Routine or Procedure way? We have to consider the simplicity and power of the Macro Evocation, vs the Macro increase of Code length. Each Macro Evocation, inserts the Macro Code in the dead File. Macros should be reserved for small and often used Block of instructions that, eventually, require some powerful level of flexibility. So said, macros should then not be considered as a real Sources organization technique, but, rather, as a simple way to High Level Assembly.


For very wide Code Scope, both logical and physical, the Procedure is the organization of choice.


For short logical scope and wide physical scope, Routines are the way.


For very wide logical scope, very short physical scope, and very small Blocks of Code, Macros are great.

 ~~~~~~~