[Lazarus] Circular references and code quality

Alexander Klenin klenin at gmail.com
Tue Oct 4 12:36:01 CEST 2011


2011/10/4 Juha Manninen <juha.manninen62 at gmail.com>:
> There is lots of duplicate code and data definitions between Lazarus
> TProject and TLazPackage (and their ancestors).
> I tried to improve the situation by creating a common base class for them.
> It is not possible because it ends up with a circular reference hell.
> Almost 2 years ago I suggested to solve the problem in language syntax
> somehow.
>   http://lists.freepascal.org/lists/fpc-devel/2010-January/018909.html
> The comments always tell to use interfaces and abstract base classes, and
> claim that this feature enforces good design.
> Bollocks!
> This feature enforces BAD design and implementation. Lazarus itself is an
> example of it.
> Is copy-pasting code between Project and Package a sign of good design. IMO
> it is not.
> Is the class structure somehow flawed if such problems happen. No it is not.

While I agree that Lazarus contains some badly designed code,
I am strongly convinced that adding even more circular references will
make it worse, not better.
A proper alternative is moving to a good object-oriented design.
Yes, that includes using interfaces and (sometimes abstract) base classes ;-)

There might be pains in transition, especially is there is a strong requirement
for keeping some legacy API compatible (as was the case with my
attempt to fix PropEdit).
However, I have never encountered a case where existing language
features were not sufficient
for a proper design (as opposed to compatibly fixing existing design).

Please state more specifically what problems you encountered with
TProject/TLazPackage and I am confident we will find a solution.

Now, as I stated above, the only real problem is that proper design often
involves splitting gigantic units into a reasonable parts, which may pose
a problem if there is lots of code relying on the previous monolitic design.

To combat this, I'd suggest "reexport" aka "unit inheritance" feature,
where a unit is allowed to fully re-publish interface of another unit.

To illustrate:

unit OldBigUnit;
reexport Part1, Part1;
---
unit Part1;
interface
  type T1 = class ...
---
unit Part2;
interface
  type T2 = class ...
---
program LegacyCode;
uses OldBigUnit;
var
  a: T1; b: T2;

-- 
Alexander S. Klenin




More information about the Lazarus mailing list