I am in the process of developing an application that allows users to write C# scripts. These scripts allow users to call selected methods and to access and manipulate data in a document. This works well, however, in the development version, scripts access the document's (internal) data structures directly. This means that if we were to change the internal data model/structure, there is a good chance that someone's script will no longer compile. We obviously want to prevent this breaking change from happening, but still want to allow the user to write sensible C# code (whilst not restricting how we develop our internal data model as a result). We therefore need to decouple our scripting API and its data structures from our internal methods and data structures.

We've a few ideas as to how we might allow the user to access a what is effectively a stable public version of the document's internal data*, but I wanted to throw the question out there to someone who might have some real experience of this problem. NB our internal document's data structure is quite complex and it could be quite difficult to wrap. We know we want to expose as little as possible in our public API, especially as once it's out there, it's out there for good.

Can anyone help?

  • How do scripting languages / APIs decouple their public API and data structures from their internal data structures?

  • Is there no real alternative to having to write a complex interaction layer?

    If we need to do this, what's a good approach or pattern for wrapping complex data structures that include nested objects, including collections? I've looked at the API facade pattern, which looks like it's trying to address these kinds of issues, but are there alternatives?

*One idea is to build a data facade that is kept stable across versions of our application. The facade exposes a set of facade data objects that are used in the script code. These maintain backwards compatibility and wrap access to our internal document's data model.

  • I should add that by 'document', I mean the in memory representation of the the application's data (that is persisted to XML when loaded / saved). I used the term document, because it's analagous to a in memory Word document, for example.
    – Max Palmer
    Jun 6, 2014 at 6:23
  • 1
    "scripts access the document's (internal) data structures directly." To me, you seem to be trying to solve effect, not cause of the problem.
    – Euphoric
    Jun 7, 2014 at 5:30
  • I wonder how, for example, the Microsoft Office API is exposed to clients. Presumably, the data structures and objects exposed in the API aren't the same data structures that are used internally. Or, perhaps they are and the office team have to be very careful not to break the API as the internal structure of office evolves?
    – Max Palmer
    Jun 9, 2014 at 10:17
  • Be careful of the inner-platform effect here. If your API is too powerful you might just end up recreating the API of your internal data structures.
    – Rufflewind
    Aug 6, 2014 at 2:13
  • The first thing that comes to mind is why database administrators create views - to expose to the clients while leaving the underlying tables subject to change. You've already considered this with your data facade approach and this should reinforce it.
    – Kevin
    Aug 6, 2014 at 4:54

2 Answers 2


The solution is to think very hard about the object model presented, and create one that is adaptable to future changes (extensible). Adding properties is not going to break anything. It is removing data types, renaming them, or removing properties, that will break existing clients. In these cases, you either have to keep all existing members for backward compatibility, or provide conversion scripts that automatically upgrade the user's scripts.

  • This is how our data model works at the moment. However, we want to retain the ability (on occasion) to move data in our data model to keep its evolution clean.
    – Max Palmer
    Jun 9, 2014 at 10:18
  • It seems no different from other projects that must provide an upward compatible API for an SDK or component. These all have the same problem. Having done this for a very long time now, I can only say that thinking about the API, using static code analysis tools, and reviews of the API, are ways to produce a long-lasting API. If it is easy to document, it is probably easy to use, but easy to use does not mean easy to extend. Jun 11, 2014 at 16:09

Without knowing your structure, I'm not certain this is exactly the right idea, but I'm going to explain what I am thinking and, with a little luck, it will lead you to the right idea.

I'm thinking you want a solution that is:

  1. Easy to do now
  2. Easy to transform if you redo the structure
  3. Somewhat familiar to your users
  4. Has tools available

So I was thinking of what tools we use to interchange and transform data, and the one that occurred to me was XML.

  1. Most languages have some sort of serialization to XML
  2. XML has transformation tools
  3. There are libraries already available to manipulate XML

So my plan would be to take your internal data and serialize it to XML. If you want to, you can use that for now as your public interface, or you can transform it to something simpler to make it easier for the next iteration of the internal storage (if you can think of something easier). You let the user iterate over it using common XML techniques, and when they are finished, you can take the resulting structure and transform and de-serialize it back to your structure. If you change structures, you just have to write a different transformation.

Of course, you don't have to use XML. There are possibly other structures that would be better for what you are doing. With any luck, however, this gets you started down the right path.

  • The only advantage I see of xml is, you don't have to write your own object model, and it has a built in diagnostic dump. But everything else about it seems bad... a good object model would be much easier to use. Jun 7, 2014 at 0:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.