To be fair, our UI generation from RTTI was more a proof of concept.
It works on some existing projects, with a nice rendering and user experience.
But the auto-generated UI result has a fixed layout. To customize it, we had to include additional parameters, and introduce complexity in the generator.
Good old RAD, with a SOA backend, or a MVC/MVVM design approach, as we propose for web servers, would have been more productive.
We admit that some patterns like Aspect Oriented
Programing could easily add some behavior to an existing code
The most obvious example is to write some attributes in code and enable method execution logging.
Sounds like a magical way of writing code.
Just like with our UI generation trick, adding logging could be just as easy
as writing an attribute to the class. Magic! Feature implemented in 5 minutes.
Now you can take a coffee for the whole day - task was budgeted for a
But logging content is poor (only method name/parameters). So you start adding some attributes at the method level, to customize the log message. And you start polluting your class. And, sadly, at attribute level, you do not have access to all needed information (e.g. values or functions in other classes). So you add an explicit log method call within the method code. And find it convenient, finally.
In mORMot, you can have auto-generated logging (e.g. all SOA
interface calls, including input parameters and output values), in the log
system, or even in a log database (very convenient, in practice).
This uses RTTI, and is indeed magic. Just a parameter, in the settings file, and you obtain some additional tracking information. And you did not change the business logic!
But this automated logging is not enough. You should now have to write a lot of manual logging, even at business layer, to track real execution context.
But all this run-time injected behavior make it harder to maintain and
By looking at the code, you could not guess what is really executed.
There is a lot of hidden mechanisms, which are not explicit any more.
When you start to put some business logic using such injection/reflection techniques, it eventually add complexity.
We have seen unexpected rebounds in Event-Sourcing architectures, using such hidden code injection to propagate events.
I've seen recently servers becoming unstable because of real-time logging issues: sending the log information remotely did create some kind of recursion, due to the remote sending logging itself its own process!
Maintainable code should always try to make the implicit explicit.
We would not make explicit all the low-level plumbing - otherwise we would code everything in assembler.
But we should better make all logical process explicit.
This is where DDD excels.
Using RTTI is a tricky business... which should be exceptional.
Relying on RTTI at runtime, for usual code, smells like a break of Liskov Substitution Principle (and the Open/Closed Principle).
Most of the time, code would be much cleaner when using proper OOP and
interface types definition, instead of relying on RTTI and
In mORMot, we achieve amazing results without the enhanced RTTI, as introducing in Delphi 10. If it is available, we would use it. But it is not, we would be able to find workarounds, even for compilation with FPC.
And it is not my own opinion.
In fact, Microsoft, in its newest orientation to "Native" compilation in .Net, does advice to avoid RTTI (ab)use.
Even at technical level, all this run-time "injection" and "inspection" stuff is not so trendy any more...
RTTI is great, but it may be abused.
There is good laziness, and unsafe laziness.
If you add cross-cutting features (like logging, or authorization) via RTTI - fine.
But if you put some business logic via code injection - beware.
This blog post just aims to state that, as always, RTTI use is a matter of balance: design principles should rule, not code magic!
Feedback may be shared on
Edit: I've added one more example, about logging via AOP.