Code that read and modify code, code that read codes and output XML

time to read 3 min | 499 words

If you can follow that sentence, congratulations.

I spend today dealing with an interesting problem. We have a set of commands that operates in response to a message from another system. This system is configured by an XML file. One of the parameters for configuration is which fields in the message should be sent.

I consider this an abomination unto Nuggan, but this is a key performance optimization technique. Otherwise the external system may spend as much as ten seconds just gathering the data for this message.

We started out using the simplest approach of just give us all the fields back. It doesn't work, the performance is just awful with this approach. But the other approach means that updating a command to use a new field (or stop using a field) is a process that can take up to 5 minutes.

This is insane. And all of that because it can't really handle a message with all the fields in a reasonable time frame. I am being overgenerous here, actually. Let me put it more clearly, the "message" is a row. The fields are the columns in the row. I have no idea what it is doing there, because a SELECT * FROM MyTable WHERE id = '[id]' returns instantly.

Nevertheless, we had a problem. We needed to go over ~127 existing commands and modify the configuration to make sure that only the fields that we are using will be included. To say that this is error prone and annoying isn't the least of it.

I decided that I would take care of this task. I know how other people would handle this. I am not subjecting them to several days of tedious code reading & XML editing.

The end result was a piece of code that used NRefactory to read the parse the code, looked for field access in the class, and then generated an attribute that marked the required fields.

[Required(Constants.customer.name, Constants.customer.email)]

Two things that were complex there were handling inheritance, we have some common functionality that we abstracted to a set of base classes, that was interesting to deal with. The second matter was making sure that this code would not just generate the attribute correctly, but would actually be able to edit the source code files with the information as well as be able to do it more than once.

This allows us to just put this in as a pre build step, and we are done. Accessing a field will cause it to be automatically registered as a required field.

The second part was another piece of code, this time it took the compiled assembly and used reflection to generate the required XML config.

We are back to one truth, maintainability cost is very low, and the only problem is that replacing the XML config takes about 5 minutes, so it is probably something that we will do rarely, and just use the "return all" during development.

One Source of Truth, remember.