Let’s give modeling a chance.
The purpose of this document about Hiconic is to show:
NOTE: For the sake of brevity we only show a small subset of the platform’s perks.
Let’s set the stage by a few (bold) claims about various aspects of current SW development:
To illustrate these points, let’s consider the following question:
What is the simplest way to create a backend application?
Such an app is quite basic - it defines a set of requests a client can make (API), and for each request sends back a response.
The developer thus has to do 3 things:
Let’s see how simple implementing a backend application is with Hiconic.
We’ll go with a single request - Greet
- with a parameter called name
, which responds Hello
to the person with given name (e.g. Hello John
).
NOTE: We show a simplified, less technically correct example, compared to a real implementation (see tutorial). It is to avoid technical details, irrelevant at this level, in favor of paradigm clarity.
Our way to define an API is to model the requests, i.e. create an entity type for each request.
entity Greet extends ServiceRequest {
String name
String eval()
}
This is a straight forward (Java) code, packaged as a module:
public class GreetProcessor implements ServiceProcessor<Greet> {
public String process(Greet request) {
return "Hello " + request.name;
}
}
NOTE: We also need to binds this processor to the Greet
request, which is straight forward but let’s ignore that syntax for now.
Let’s say we want to deploy our service as a web application accessible over REST.
In our world, an application is just a shell, which defines the platform (e.g. Reflex, our microservices platform) and a list of modules. So we do just that:
Aaaand that’s it, so easy!
We can now build the app, deploy it, access via example.com/api/greet?name=World
and get "Hello World"
back.
Let’s see what we did (or didn’t have to do), and how have we addressed the aspects we mentioned at the beginning:
We have modeled our API so to call a service a request instance needs to be created and evaluated. This has many advantages, e.g.:
We have NOT, however, bothered the backend developer with mapping the request to the URL. The mapping is automatic, based on request name and its properties - convention over configuration.
As for agility, we also didn’t define the response’s format (e.g. JSON). For us, what matters is the modeled return type (i.e. structure of the data), not the way it’s serialized. It is up to client to describe what format they want, JSON is just default.
NOTE: Yes, our service returned just text, but it is JSON - see the quotes around the text.
Portability is achieved by packaging our service as a module, independent of where it will be deployed and how it will be accessed. We went with a REST based web application, but it could be:
Our platform is built for modeling with lots of tools and features. We treat models as an extension of the language, entities as separate types (besides classes and interfaces) with their own reflection. This makes any kind of domain-independent task easy to implement with elegant and efficient code (e.g. serializing as JSON or auto-mapping URL parameters).