Where's the API? Where's the code?

These are common questions levelled at NetKernel and the systems developing using NetKernel. They reveal a mismatch of expectations which is caused by a fundamental difference in the structure of software using the Resource Oriented Computing (ROC) abstraction upon which NetKernel is based.

In the closing remarks of a previous post I mentioned that ROC liberates systems from being implemented in a single language by virtue of the fact that the ROC middleware acts as an integration platform for different programming languages and technologies. In this post I want to delve into this a bit deeper to explore some of the implications as well as answering the questions posed in the title.

Let us first look at software platforms such as the Java Virtual Machine (JVM) and the .Net Common Language Runtime (CLR). They also provide a mechanism to execute code from multiple programming languages. They compile them down into a common bytecode. They provide services such as memory management, security and an underlying operating system abstraction. They abstract away pointers and only allow access to the system through trusted API’s. At first glance there is a similarity to ROC middleware but fundamentally at the low-level they are still executing arbitrary imperative code as an amorphous whole communicating without any intervention by a kernel or other intermediary.

Let’s just be clear that at the physical level NetKernel is an application running upon a Java Virtual Machine. But don’t let that detract from it’s form, what it does primarily is to instantiate the alternate reality of the ROC abstraction. The ROC abstraction plays host to resource address spaces embodied by software components (endpoints) which communicate via asynchronous requests-response pairs. Each endpoint acts as a black box, it is free to execute whatever code it desires (within the limits it’s sandbox) though they are constrained to using the Context API to communicate outside their box. This API is common to across all endpoints though each endpoint has it’s own instance for each handled request. It is this Context API that gives the endpoint its place in the world. It is this API which enables the handling of incoming requests and the issuing of responses for those requests. It also enables the creation and issuing of sub-requests and receipt of their responses. This is the only fundamental API that NetKernel has - for those familiar with the details of NetKernel this API is called NKF - the NetKernel Foundation API.

It is quite possible to develop and deploy endpoints which execute code against the Context API. Practically speaking any programming language which can be compiled down to JVM bytecode can be used to implement endpoints, this includes Java, Groovy, Ruby and Clojure. Whilst this is very useful it is not the be all and end all of endpoints. Because endpoints are treated as black-boxes there is a pattern called Language Runtime which allows the creation of endpoints to embody any implementable programming language or domain specific language (DSL).

The Language Runtime is a pattern which consists of an language runtime endpoint which embodies a particular programming language, a program representation, and a program compiler endpoint. If necessary for a particular implementation, the program compiler is responsible for converting the human editable representation of the program into a machine optimized representation. The language runtime will then execute the program. Typically language runtimes are stateless, when they receive a request they execute the program in isolation working with any supplied input arguments and possibly issuing sub-requests for resources they need to work with. Upon completion they return a response. NetKernel has language runtimes for many common programming languages such as Javascript, XSLT, Beanshell (interpreted Java).

There is broad spectrum of capability in the types of programming language that can be modelled in this way. In some examples of language runtimes the program can degenerate into what might look more like a configuration document. However in this case the endpoint might be better considered as a configurable transform or data source depending upon it’s intent. But what this does show is that code and configuration are one and the same thing. I think that is pretty interesting. It shows that with sufficiently specialized endpoints a system can be composed by mere configuration. It is this which provides the answer to the “Where’s the code?” question that I have seen asked many times when systems developed leverage the rich library of endpoints supplied with NetKernel.