Ev(i|a)l code

It has been a while since i last saw someone eval code coming from a remote source. I thought that technique is considered evil across the board but i am wrong, many people like it. So i decided to join the cohort of people that preach the perilous use of it.

The context

I have been doing Demandware (Salesforce commerce cloud or SFCC now) for quite some time. They have this custom script built on top of JS called demandware script (.DS). Being a dynamic language, evaling is quite easy as you may guess and a lot of people are tricked into it.

So what was the use case?

In the context of SFCC, you do a lot of object exporting so that you integrate with 3rd party systems. Some integrations take variable count of fields and the customer is the one to decide which fields to export. So how can we give the customer the freedom to decide what to export without going through the hefty procedure of a code change? Eureka! Let them write a bit of a well documented code that we eval and that’s how we construct our exports. If they want an extra field exported, they write an extra line of code that calls some API (either ours or SFCC) that does the magic and the export is ready, brand new and shiny without a single minute of developer time wasted. Customer writing code is as flexible as we get.

La la land

I guess, you buy the flexibility argument until the future you (or someone else) has to deal with the consequences. So why all the grunt:

  • Even though the customer (or whoever that may be) has the flexibility to write code that you execute for her, chances are she will never do that but will come and ask how to do this and that. Say good buy to flexibility.
  • You stop being owner of your code. When someone starts writing code that you eval, you are pretty much opening an API. A vast API. Have you considered the consequences of opening pretty much your whole system as API? Chances are you haven’t. First, you have to be very careful what you eval. Second, say hi to legacy. Forever. You can’t just change code that is being used by external sources. Third, you have to keep a very detailed documentation of who uses your code and how so that you may asses the impact of every code change. The team should be very well aligned with that. And fourth and fifth etc. Not being owner of your code is not cool.
  • Your code stops being greppable and that is very evil. Your code should be absolutely greppable. I have had the unfortunate moment to delete a function that no one uses only to find out later that a ton of stuff is broken because this function is actually used by some external code.
  • Security. Won’t delve here, this is self explanatory.

Is there a valid use case of evaling? It is there for some reason, right?

Yes, of course. I think evaling has some valid use cases and here is my criteria:

  • You should do very simple operations with evaling. Really simple.
  • You should touch as little as you can from the underlying system.
  • You should verify what you eval. Might be a regex, might be something else but you should have a very strict criteria what you eval.

I have done it only once and that’s my use case:

I was doing an application where you could draw windows (like real world windows that you have in your homes) and calculate prices. All that was done client side in the browser in a canvas. So at the end, you have the picture of your window plus the javascript artefacts associated with it. For every window you had the perimeter, area and a bunch of other properties calculated (number of glass panes, area of glass panes etc). However, to come up with a price you should apply a formula. That’s where eval fitted. I gave the customer the possibility to write stuff like that in a text field that i evalled against the constructed window objects:

  • ┬áT + S * 20 (total price calculated by the system + 20 euro per sq. m.)
  • T * 1.2 (20% markup across the board of the total price)
  • T + S * 20 + P * 10 (total price + 20 euro per sq. m. + 10 euro per meter of the perimeter)
  • T + 50 (total price + 50 euro flat per item manufactured)
  • T + GN * 10 (total price + 10 euro per glass pane markup)

You get the point, every merchant does his own way of pricing and that varies a lot. However, all of the pricing formulas are very simple operations and use very limited API (area, perimeter and a couple of more properties of the window). Using a very limited API and doing only arithmetics, there is a very easy way to validate what gets evalled (like with a regex). There is also only one way to calculate area, perimeter and stuff like that in the context of geometrical shape, so you are not stuck with legacy. This code has no reason to change anyways.

TL;DR Don’t do it, unless you have a very concrete use case, open very limited API and can control what will get evalled.

Leave a Reply

Your email address will not be published. Required fields are marked *