Let's say you have a domain object and there is a DSL that acts upon the domain object. There are some constraints:
- The DSL is only allowed to access certain methods on the domain object
- If the DSL tries to access a method it's not allowed to, you can throw an exception
- You didn't write the DSL it's something like MVEL (or it is MVEL), so you can't modify it.
- You can wrap, modify, do what ever you want to the domain object before exposing it to the DSL.
- The DSL looks like "foo() > 1". Where the DSL will has an object and will call foo() on it.
How would you implement this?
One option which is pretty straight forward, use a facade and expose to the DSL only the specific methods in from your domain object. This is not too bad if there are 3-5 methods, but assume there are 20 methods, or even there are 10 objects each with 20 methods you want to expose to the DSL. A facade might not be a bad idea, but it does start to incur some maintenance cost. And developer annoyance.
Another option would be to use meta-data / annotations (I know, I know Metadata is for noobs but I'm a noob, so it's okay for me to use it). Instead of the facade you could annotate each method you expose to the DSL. Great it's easy to annotate methods, but how would you throw an exception if the DSL tried to do some bad stuff? This is where something like AOP / CGLib can come into play. You proxy your object with CGlib and intercept all method calls, if the method does not contain your annotation then you throw an exception. Take your proxied object and expose it to the DSL. Now the DSL has a proxied version of your domain object that won't let it call methods on it that it shouldn't. Problem solved.
The real question is which is better the facade or the metadata? I'm really not sure.
Any other tricky ideas?
No comments:
Post a Comment