Tuesday, March 20, 2018
Declaring units in a specific order in code would facilitate the code maintenance in the future.Introduction
When we're organizing our things, we tend to keep closer to us all objects that we use daily, right?
So it should be with the units of a project.
The order that units appear in the code could facilitate or not the maintenance.
In that article, I will show you what order I use to declare units in my own projects.Compiler
The units, also known as modules, compose the projects.
Every project must be divided into logical units and make that division it's not always easy, because it involves an abstract and logical level of thinking.
After dividing the project units, we also need to concern with third-party units.
Nowadays it's almost mandatory that we use lib's and frameworks. Mostly, they are Open Source projects.
Such third-party units make our work easier, as they already have ready-made artifacts that speed up the development of projects.
In addition to these third-party units, we also have the default units located in Run-time Library (RTL) or VCL/LCL, which have many interfaces, classes, functions, and artifacts, ready-to-use.
So, what order we should declare such units in our code?
Here is the order that I propose:
unit MyUnit; uses // 1. fpc/lazarus/delphi units, // 2. 3rd units, // 3. my open source units, // 4. project units
When the compiler starts parsing your code and it arrives at
MyUnit, it will read the units in the sequence in which they were declared there may be some optimization, but the important thing is the final result, which depends on the order above and the identifiers (classes, interfaces, functions/procedures, variables and constants) will be "stored in order" in which they were declared.
So, I propose to declare, initially, all units that are standard to the compiler and IDE. Then, all third-party units such as libs and frameworks. After, all units referring to your public projects, be them OpenSource or shared within sectors of your company. Finally, we declare all units of the project itself, that is, the project we are currently working on.
And why is this important?
The reason is because the compiler needs to know in which unit a particular artefact (class, function, etc) is located.
The rule is that:
If you have 3 units (
Unit3 ) and each has a class named
TFoo, the compiler will "inform" your code that
TFoo is located in the last declared unit.
uses Unit1, Unit3, Unit2;
Notice that I reversed the numerical order. First is 1, then 3, and finally 2.
Where is located
TFoo class when you'll use it in your
The answer is: In
Because it was declared by last.
Imagine that the compiler is putting a reference table into memory for all the identifiers it finds. First, it finds
TFoo when it reads
Unit1. Then, it finds it again when it reads
Unit3. At this point it overrides the reference that says that
TFoo is in
Unit1, because it is now in
Unit3. Finally, when it reads
Unit2 the identifier is repositioned again.
If in that same
MyUnit I need to use
Unit1, I am required to qualify the class with the unit name instead of just using identifier:
Foo := Unit1.TFoo.Create...
You can see another example hereSections
In the Object Pascal language we have two places (sections) where we can declare the units that will be used.
We can declare in the interface section or in the implementation section.
Is it worth declaring Units in the implementation section?
In my opinion, no.
In doing so, you will have 2 places to organize the precedence of the Units, meaning you will have more work.
Because the Object Pascal language does not support Circular Reference between Units, one of the reasons for having the option to declare Units in the implementation section is to allow this bi-directional reference between them. However, this also indicates a bad design in the division of the project units.Conclusion
Defining the order of declaration of the units in each unit of your project can be extremely important to facilitate maintenance and organization.
As you add new identifiers, you will be sure that the compiler will give you "priority" to use the identifiers for your project, without having to prefix it with the unit name.
If you add some identifier and it conflicts with another unit that has the same name, simply prefix that identifier with the name of the unit, either from third parties or from the environment itself. However, this conflict will not exist in the identifiers of the units of your project.
Therefore, in your code, you should better "get closer" units that belong to the project, because they are more used, than from other auxiliary units.
Marcos Douglas B. Santos
This blog post has received 4 comments.
Previous | Next | Index