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
base.
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
day.
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
debug.
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
TValue
.
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!
As Markus commented, as one of the clean code principles: "Someone should be able to read the source code like a book and be able to figure out what it is doing without comments."
Feedback may be shared on
Google+.
Edit: I've added one more example, about logging via AOP.