12 Mar 2016 - by 'Maurits van der Schee'
On c2.com I read a quote by Jeff Mantei on the OnReflection page:
I think of reflection as the ability to reason about the structures and processes of a programming system within the programming system itself. - Jeff Mantei
I was thinking of another definition saying:
Reflection is when the logic of an information system is based on the meta-information of that system.
But after giving it some serious thought I believe Jeff is much better. His quote is not only a very concise definition of reflection, but he is also not cheating by using the word "meta", as I did, which has a lot to do with reflection.
Reflection is also what php-crud-api is doing. It uses the SQL reflection schema (called "information_schema") to query the database about it's structure. Then it uses that data to perform a standardized set of API commands. These commands are known as "CRUD" command, since they consist of "Create", "Read", "Update" and "Delete". I recently added Swagger API specification output based on the same reflection so you can generate beautiful API documentation.
Web application routing is when an web request containing an web address (URL) is converted (routed) to a specific piece of code that is executed. You can make the router reflect the structure of the files on disk (like in MintyPHP). Another possibility is to reflect the public methods of your controller classes (like in maussoft-mvc). You can also base the routing on the structure of your database (like in php-crud-api). Note that not everybody uses (or even recommends) reflection for routing. A different approach is that the router looks up the address in a set of rules (called a router configuration) to find the code that is to be executed.
IMHO this is a bad idea and it is not about execution efficiency. I believe that the "mental costs" of a router configuration are quite high. Every time you are debugging a erroneous or non-behaving URL you have to find out which code is executed for that particular URL. That's why I strongly advice to avoid router configurations at all, regardless of whether it is applied through annotations or using a separate router configuration file.
On the other hand I do understand that frameworks support router configurations. They do this to facilitate porting legacy applications (with existing addresses) to this framework. By allowing you to add this indirection you get the opportunity to transparently restructure your application. Sounds great, but it should probably be avoided as the cost of complexity is often underestimated.
And when working on a green-field project you should IMHO always avoid router configurations and use one of the default routing (reflection based routing) systems described above. Even when you are dealing with porting a legacy application you may be able to overcome your limitations by simply redirecting the legacy addresses to the new consistent addressing scheme. After a few months (or years) you can turn of your redirection service as traffic to it will reduce as people start using the new addresses.
A serious administrative application can have up to hundred database tables. When you want to expose such a mature data structure via an API you may have to facilitate hundreds of different API calls. The challenge will be to keep the code base limited in size and consistent in performance and behavior. This is typically when you try to add an abstraction level to generalize your code.
An existing reflection structure may be a good candidate to facilitate this process. Other people have used this structure before you. Maybe even for the same purpose. The chances are good that you are able to solve your problems without much trouble. Reflection often feels like it 'fits', because you don't have to invent it yourself.
To conclude I'll summarize the 3 reasons I love reflection:
Let me know what you think about using reflection. Should it be recommended or avoided?
PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.