I am wondering if the following using unit order is correct.
uses
FastMM4 in 'Fast\FastMM4\FastMM4.pas',
VCLFixPack in 'VCLFixPack.pas',
FastMove in 'Fast\FastMove\FastMove.pas',
FastCode in 'Fast\FastCode\FastCode.pas',
FastMM4Messages in 'Fast\FastMM4\FastMM4Messages.pas',
Why should I bother with the order?
There may be a few reasons:
Some units perform actions at startup. The order of such actions may be important, like FastMM4, which replaces the default memory manager with its own. This should be done before any memory is allocated.
If several units contain duplicate identifiers, the "last" one overrides the previous one. This may be on purpose, or it may be by accident. The other identifiers are still accessible, but not without qualification with the unit name.
The same as for actions at startup, actions at the end of life my be important too, and their order.
Note that it is not guaranteed that the order is preserved. If one of the units uses another, that one must be loaded first. To make a unit really the very first, make it the first in the .dpr or .dpk file.
You have three separate pieces of code here:
FastMM
VCLFixPack
FastCode
It is important to install the replacement memory manager, FastMM, before any heap allocations are performed. So I think it is clear that must be the first unit to include. And you may as well keep the two FastMM units together.
The other units make changes to the code in memory, to fix bugs (VCLFixPack) or to improve performance (FastCode). Although you have separately identified FastMove and FastCode, in reality, the FastCode unit actually installs a suite of improved functions, defined over a dozen separate separate units.
It seems quite likely that it would be important to install the VCL fixes before the VCL units are included. So VCLFixPack should appear before any VCL units.
As for FastCode, since it only influences performance, you could perfectly well use it at any point in the .dpr file. It probably does not matter if the initialization code runs with the vanilla RTL code. That said, for sake of consistency it makes sense to keep together all these units which change the behaviour of the runtime. So I would write your .dpr uses clause like this:
uses
FastMM4 in 'Fast\FastMM4\FastMM4.pas',
FastMM4Messages in 'Fast\FastMM4\FastMM4Messages.pas',
FastCode in 'Fast\FastCode\FastCode.pas',
VCLFixPack in 'VCLFixPack.pas',
....
I put FastCode before VCLFixPack because logically the RTL is at a lower level than the VCL. However, it does not matter either way around. But you've got to pick one, and that was my reasoning.
I also omitted an explicit reference to the FastMove unit. That is used by FastCode, along with a host of other units, and if you are going to omit the others, you may as well omit FastMove.
Related
The question is related to my previous question:
access violation at address in module ntdll.dll - RtlEnterCriticalSection with TCanvas.Lock
Apparently there is a bug in Delphi's code (see QC 64898: Access violation in FreeDeviceContexts). This bug goes all the way until D2010, AFAIK.
The suggested workaround worked fine so far. Now I have a dilemma.
I don't like the idea of using a private copy of Controls.pas in my project - I'm not sure it is safe. The Controls unit is a very low level unit, and I really feel it's a drastic move, considering that my huge application works fine, except for the mentioned problem. I'm also not sure if/how to rebuild all components/units that rely on the Controls unit in my project.
Is it possible to patch TControlCanvas.CreateHandle(), which uses an internal CanvasList and private members?
NOTE: I will be using the patch for this project only (Delphi 5). I don't mind hard-coding the offsets. AFAIK, patching privates always uses hard-coded offsets, based on the compiler version. I might be able to deal with privates myself (without class helpers), but I have no clue how to handle CanvasList and FreeDeviceContext(), which are declared in the implementation section of the Controls unit.
As discussed in the comments, it is possible to access the private and protected members of classes, even in older versions of Delphi without "class helpers".
However, the problem in this case revolves around the details of a particular method implementation, not just being able to access or modify private member variables. Further, the implementation of a particular method which makes use of an implementation variable in the unit involved. Specifically the CanvasList variable that you have noted.
Even with the benefit of class helpers, there is no simple way to access that implementation variable.
Your current solution is the simplest and safest approach: Using a copy of the entire unit with a modification applied to the specific method required to solve the issue.
Rest assured, this is not an uncommon practise. :)
Your only problem with this approach is to be sure to manage the fact that you are relying on this "privatised" copy of the unit when standing up new development environments or upgrading to new versions of the IDE.
In the case of new development environments, careful project configuration should take care of things (and of course, your modified Controls.pas unit is part of your version controlled project).
In the case of upgrading to newer Delphi versions, you simply have to remember to revisit the modified Controls unit in each new version, updating the private copy in your project and re-applying the modifications you have made as appropriate. In most if not all cases this should be straightforward.
But I Really Want to Access the CanvasList Variable
As I say above, there is no simple way to access the implementation variable used in that unit (which will be necessary if you were to somehow contrive to "patch" the code at runtime, rather than replacing it with a modified copy at compile time).
But that implies that there is a **non-**simple way. And there is.
Like any data in your application, that variable resides at some memory address in your process. It's only the compiler scoping rules which prevent you from addressing it directly in source. There is nothing stopping you figuring out how to find that location at runtime and addressing that memory location via a pointer as you would any other "raw" memory address to which you have access.
I don't have a worked up demonstration of how to do that and strongly recommend that trying to implement such a solution is a waste of time and effort, given that an easier solution exists (copying and modifying the unit).
Apart from anything else, depending upon how reliable the method is for determining the memory location involved, direct access to that memory location could prove potentially vulnerable not only to differences between compiler versions but even to changes arising from compiler settings.
In terms of the end result, it is no better than copying the unit but is certainly far harder and far less reliable.
Whilst moving some applications from Delphi XE2 to XE5 I've noticed that there are a number of units listed which are no longer needed.
This is turn lead me to tidying up the uses section of the interface which leads to my question.
Is there a recommended order for units in the interface? I know they are loaded in reverse order, but should I be organising them by Usnit Scope.
For example should MyCompany.* be listed at the start or the end? Should I place the Vcl.* before the System.*
update
In general I will include my Units in the implementation rather than interface. I'm grasping more about whether there is a hierarchy to Delphi's own units...
For example I have encountered one issue where listing the Windows unit before System.SysUtils changes the version of DeleteFile that is used...
Explicit Question
Should the order of uses be
Winapi*, System.*, Vcl.*, or the reverse?
There are some risks associated with uses list refactoring:
Later used units will override symbols (methods, classes, vars, consts, ...) of units used earlier (scoping).
This can introduce (more or less) sublte bugs into your program.
Reordering units can change the order in which intialization and finalization sections are run.
There are also some advantages:
Faster compiling speed
Smaller executables (Only if any removed units had initialization or finalization)
Avoiding / Preventing uses circles (although uses circles are often a sign of a sub optimal OOP design)
Having said that and after your question update:
I tend to do the same thing that David already wrote: Order the units from low level to high level.
There are tools that can help you with finding unused units and also arranging the used ones in the best order. (Peganza Icarus / PascalAnalyzer and ModelMaker)
It's hard to say what the compiler really does (especially since there are now multiple compilers), but putting units with the least dependencies first should make it easier for the compiler to build the dependency tree.
Read http://docwiki.embarcadero.com/RADStudio/XE3/en/Programs_and_Units and http://docwiki.embarcadero.com/RADStudio/XE5/en/Using_Namespaces_with_Delphi articles.These 2 articles are explaining exactly what you've asked.
The TMS Software, author of many components for Delphi - recommend on their blogpost the following order:
uses
// 1. fpc/lazarus/delphi units,
// 2. 3rd units,
// 3. my open source units,
// 4. project units
It is actually the best option in my opinion. You can change the order. Important is only to remember that when the function/class name will be used in more than unit, the last one unit will be used.
In Delphi we can do this:
interface
var
test: string = 'this is a test!'; { compiler accepts that }
But we can not do this:
implementation
procedure showTest;
var
internal_test1; { compiler accepts that }
internal_test2: string = 'another test'; { compiler error }
I hope some user from Embarcadero could answer that. :-)
Global variables' values are assigned from compile-time constant expressions, and they're stored in the program's data segment. That is, space for those variables is allocated physically in the EXE file, so when the OS loads the program, those variables are loaded implicitly. The compiler can ensure that those variables are initialized without executing any code at run time. It just stores their initial values in the EXE file.
Local variables, on the other hand, do not exist until run time. There is no physical space in the EXE that will always refer to those variables. To initialize them, the compiler would have to generate code to assign values to them.
Global variables can be initialized because it was a technically easy thing to implement in early compilers, and it's essentially a free feature at run time, requiring no execution of any instructions by the CPU.
If you want to initialize local variables, you're free to write the code yourself; that code can do exactly what any compiler-inserted code would do.
Niklaus Wirth was a Computer Scientist researching and teaching the design of Languages and Compilers. When he designed the Pascal Language and Compiler, some of his design goals were to make the compiler small fast and efficient, and to partition tasks so that the compiler did things that were easy for the compiler, and the programmer did things that were easy for the programmer.
In line with these goals, he designed a Single-Pass compiler, that only had to read the source code once, and understood everything the first time through. He also designed a compiler with a very simple state machine: everything is done in order, in correct order, only in correct order.
By doing so, he was able to easily get a very small, fast, efficient and correct compiler, in contrast to C compilers which were notoriously difficult, incorrect and inefficient, and FORTRAN compilers, which were slow and large.
Doing static constant allocation once, at the start of the program, is one of these design decisions that allows you to write a small, fast, efficient, correct compiler.
Decades ago, Borland wrote a Pascal compiler that was small, fast, efficient and correct, and it competed successfully again more expensive products from other companies (such as MS) that allowed out-of-order declarations and other generally useful and helpful options that made the compiler more slow and difficult, but made programming easier.
In other words, MS choose to partition the tasks between compiler and user differently than Borland/Wirth did.
And the MS Pascal compiler was dropped a very long time ago. But the Borland compiler continues as Delphi.
Computers are a lot faster now than they used to be, but the task of writing a small, fast, efficient, correct compiler remains the same. New features are not free. Adding complexity to compilation comes at a cost. Even a simple feature is messy if it has to be added as an exception to the way the whole compiler and language were designed right from the very beginning.
I have a large codebase which I am working with which has units like this:
unit myformunit;
interface
type
TMyForm = class(Form)
end;
procedure not_a_method1;
procedure not_a_method2;
var
global1,global2,global3:Integer;
...
In short, the authors of the code did not write methods, they wrote global procedures. There are tens of thousands of them. Inside these procedures, they reference a single instance of MyForm:TMyForm.
I am considering writing a parser/rewriter utility that will turn this code into "at least minimally object oriented code". The strategy is to move the interface and implementation section globals into the form, as a start. I realize that's hardly elegant OOP. But it's a step forward from globals.
If I could do this on one unit at a time, I might be able to repair the breakage in the rest of the project, if I only did it on one form at a time. But I'd like to reduce the amount of time it takes to rewrite the units, instead of doing it by hand. Some forms have 500+ procedures and 500+ interface and implementation global variables which are in fact, specific to the state of a single instance of the form that they are in the same unit with.
Basically, what I will do if nothing like this exists is write a parser based on the Castalia Delphi parser. I'm hoping that perhaps ModelMakerCodeExplorer, or castalia, or some other similar tool has something that would at least do part of what I need for me, so I don't have to build this utility myself. Even if I do have to build it myself, I estimate it might automate about a thousand to two thousand hours of grunt-work for me. I can at least run it, and then see how much breaks, and then revert or commit after I've decided on a level of effort to refactor this code.
Alternative strategies that accomplish the same goal (go from zero encapsulation and zero OOP, to more encapsulation, and slightly more than zero OOP, in an incremental way, on a large, unstructured delphi codebase that only used objects when it was unavoidable, and never had any idea about real OOP) are welcomed.
Changing the globals to form fields seems like just cut and paste them. You might consider moving them in a dummy procedure and use MMX to normalize the declarations first.
Then use ModelMaker Code Explorer to move the procedures and functions into the form, which is only just cut and paste in the Member View.
Not necessary, but as a next step remove the references to the form instance from the method bodies. This can be achieved by find and replace.
Or did I miss something?
The Delphi Sonar plugin (open source) does not fix the code but can be used and configured to search for 'bad code':
The Delphi Sonar plugin enables analysis of projects written using
Delphi or Pascal. It was tested with projects written in Delphi 6, 7,
2006 and XE. This plugin is a donation of Sabre Airline Solutions. Its
tests include: Counting of lines of code, statements, number of files,
classes, packages, methods, accessors, public API (methods, classes
and fields), comments ratio, CPD (code duplication, how many lines,
block and in how many files), Code Complexity (per method, class,
file; complexity distribution over methods, classes and files), LCOM4
and RFC, Unit tests reports, Rules, Code coverage reports, Source code
highlight for unit tests, “Dead” code recognition, Unused files
recognition.
We have a project full of custom components that today is working in Lazarus and Delphi.
I'm thinking in code interfaces on it, but I am not much familiar with them. What I would like to know is: What are the implementation nuances from Delphi and Lazarus interfaces? There is something that I should be specially aware? Will I have to code really different things?
Background explanation:
I think the components could benefit from interfaces, or at least, I will learn more from them. For example, one of the components make communication to many different hardwares using serial port. But user should use only our component to create the application. So we have the component and one class to each of this hardware that descendant from a base class. At run-time we create the specific class inside the component.
Not sure this last explanation was needed, but I can write more if any of you need it.
In Free Pascal, the interface type depends on mode. Basically there is mode COM or CORBA . COM is default and roughly compatible with Delphi. CORBA is a more simpler case without the reference counting. (and thus also not generating calls to refcounting functions). So basically a FPC Corba interface is like the hypothetical ancestor of the IUnknown interface.
Besides this, there are sometimes some differences wrt when interfaces are released. Delphi tends to save decreasing the refcount at for the end of the procedure or block (in larger procedures), while FPC sometimes is known to release them sooner, typically immediately after the statement of last use. Both are legal implementation choices btw, base on which scope is used for temporary variables. (only on the function level, or also in deeper nested blocks)
However this sometimes reveals hidden (bad) assumptions in code, specially when using interface references and object references within one procedure that might "survive" in Delphi, but not in FPC. It is a typical case that shows that long-time working code is not necessarily correct. One might only notice hidden assumptions when changing implementation
(added later:) note that you can use COM style on *nix. It mainly is the insertion of calls to reference counting routines that set the two interface types apart. Not what system (COM, Corba or simply in RTL reference counting) those calls are routed to.
Note that I think the COM vs Corba names for both interface types were badly chosen. Corba interfaces are refcounted actually, but traditionally this refcount is manually handled, because Java does not support externally handled interfaces in an automated manner.
Added 2021-11-06: It seems that Delphi Alexandria now follows suit