Hiconic
is a technology that arose from consequent application of modeling, i.e. representing all kinds of things as data.
It offers a lot of convenience for common use-cases (e.g. serialization), makes writing generic components simpler and the normalization of treating everything as data leads to high code reusability.
It consists of multiple layers. On the lowest level it extends the language with a new entity type to contain data (as class contains code), on the highest level offers a modular (web)application framework, with many components and tools in between.
This document briefly explains what it is and tries to give insights into why it has value.
Links at the bottom provide more details on various aspects, including non-technical behind the scenes of why the company behind this tech failed.
Hiconic consists of:
The modular platform comes with a list of modules which provide common features like SQL persistence (via Hibernate), REST endpoint, GraphQL integration and more.
The core is by far the most important part of the stack.
The type system for modeling, consisting of entities and enums (and collections thereof), comes with its own reflection for easy generic handling. Based on the reflection come many tools for standard tasks, e.g.:
As for more advanced features:
Few examples to get an idea…
GenericEntity is a super-type of all entities.
public interface Person extends GenericEntity {
EntityType<Person> T = EntityTypes.T(Person.class);
String getFirstName();
void setFirstName(String firstName);
String getLastName();
void setLastName(String lastName);
Date getBirthDate();
void setBirthDate(Date birthDate);
}
Entity reflection (EntityType<>, Property) is much more convenient and faster than Java reflection (Class<>, Method).
// This code prints the entity's type and the name and value for each property
public void print(GenericEntity entity) {
EntityType<?> type = entity.entityType();
System.out.println("Type: " + type.getShortName());
for (Property p: type.getProperties()) {
String name = p.getName();
String value = p.get(entity);
System.out.println(name + ": " + value);
}
}
Assuming Icon is a custom metadata type defined on a type fur UI purposes.
public Icon getIcon(GenericEntity entity) {
return mdResolver.getMetaData()
.entity(entity)
.metaData(Icon.T)
.exclusive();
}
public boolean isMandatory(GenericEntity entity, String propertyName) {
return mdResolver.getMetaData()
.entity(entity)
.property(propertyName)
.is(Mantatory.T);
}
We call this Denotation Driven Service Architecture (DDSA) - API calls are made by evaluating request entities:
public String resolveLastWatchedMovieName(Person person) {
const request = ResolveLastWatchedMovieName.T.create();
request.setPerson(person);
Movie movie = request.eval(this.evaluator).get();
return movie.getName();
}
In JS/TS the property access looks very natural.
public async resolveLastWatchedMovieName(person: Person): Promise<string> {
const request = ResolveLastWatchedMovieName.create();
request.person = person;
const movie = await request.EvalAndGet(this.evaluator);
return movie.name;
}
Many of the advantages are discussed elsewhere, so we just sum them up grouped:
While the tech is promising, there seem to be quite a few blockers that prevent developers from giving it a chance.
The web application framework is designed for a modular monolith, not microservices.
This should not be a big deal in practice, microservices are not a silver bullet and they often introduce more complexity than they solve, but it’s the current trend and you have to accept that.
Interestingly though, creating an alternative, microservices oriented framework would be quite easier without all kinds of features of our monolith.
Eclipse was a great, free, open source IDE when we started developing the technology, so once we realized we could use some IDE plugins, we went for it.
IntelliJ IDEA has gained a lot of “market share” since, with a lot of religious following for some reason. I’ve tried both and while IntelliJ was slightly better, the difference wasn’t that huge. Not to mention a big number of developers don’t even use many of its features. But hey, customer is always right. Though to be fair, many tools including GitHub Copilot are (still) not available for Eclipse, which should be a wake up call for the Eclipse community.
If we had the resources, we would definitely add support for IntelliJ, it doesn’t need much. Maybe future LLMs will make this much easier 🤞
While there is a great JavaScript library (with type declarations for TypeScript), the integration is a bit clumsy. Most notably there is no way to define a model (Entities) in JS. One has to create a model in Java and add it as a dependency to the JS/TS project.
This works fine for full stack developers, and makes sense for models shared between server and client, but there is a clear path towards having a pure Node.js implementation where this would have to be addressed.