[fpc-devel] Design ideas ... [[Re: Attn: Sven Can not use "specialize" to resolve forward declaration]]

Martin Frb lazarus at mfriebe.de
Thu Dec 9 09:09:04 CET 2021


The below might read as if it belongs on the Lazarus list.
But this is not about Lazarus.

This is about a general design idea (pro and con), and the possibilities 
the language provides.
The example(s) just happen to be from Lazarus.

On 09/12/2021 07:59, Sven Barth via fpc-devel wrote:
>
> For interfaces you can use IInterface/IUnknown though that will work 
> only for COM interfaces. For raw interfaces there is no solution 
> currently.
>
> In my opinion you should rethink your code structure however. I don't 
> know right now what would be better, but as it is now it feels bad.
>

Well, ok, lets go fishing for ideas.
No rush, this is a loooong time think, no idea when I will really get to it.

Lazarus has a debugger frontend (currently more or less hardcode in the 
IDE), and several backends (gdb/lldb/fpdebug/....)

The currently provided "interface" (for implementing a backend, that the 
IDE can talk to) is just code taken from when we had only one backend.
However it is some elements, I like to keep. For different data elements 
(stack,watches,locals) a Monitor/Supplier relation exists.

The backend is the supplier. The frontend the monitor. One think they 
all have in common. They have a reference to each other.
For reasons outside this quest, the design should support multiple 
Montiors, hence "Add/RemoveMonitor"

The WatchesSupplier takes one or more WatchesMonitor. The WatchesMonitor 
has one WatcheSupplier.
On top of maintaining the relation, there will then be watches specific 
methods.

So far so good.
https://gitlab.com/freepascal.org/fpc/source/-/issues/39459#note_758496897
represents this idea.

Using interfaces also seems a good idea. It does put the least 
restrictions on both sides.
Especially each side can still choose it's own base classes.

-------
One more consideration. New methods could be added later. Then all 
classes implementing the interface must implement them.
It would be nice, if a default could be automatically supplied. 
(if/where such a default exists, e.g. CanFeature = false)

Actually that is possible too. generics
type TWatchesSupplierDef<_Base> = generic class(_Base, IWatchesSupplier) 
... end; // having virtual methods for any method of the interface.

That still fulfils the initial requirements. Any implementer of the 
interface can just mix it into their class structure

------
Now that still works. the problem starts when you want to split the 
Inteface into a general base, and specifics for the watches/stack/locals.

At that point, the generic type restrictions no longer work.

Why splitting it? I could just repeat the 2 methods in the base? 
Couldn't I?
But, maintaining the list of monitors could be completely implemented in 
a generic (which later can be included in a monitor/supplier on a 
optional base).

So, if I do not want to duplicate that code, then I need such a baseclass.

Currently that means giving up on some of the param-type-restrictions.

---------------------
Anyway that is the current background of what I am looking into.
> In my opinion you should rethink your code structure however. I don't 
> know right now what would be better, but as it is now it feels bad. 

Any better idea?


Btw, if that works, I have a feeling this could replace the LCL 
interfaces run-time created classes. Afaik it fulfils all the 
requirements that lead to the current situation.
- Being an interface
- having a default implementation
- allowing to mix default classes and specific classes into a new 
inheritance structure.





More information about the fpc-devel mailing list