Today, we are launching BESSER, our brand new low-code low-modeling open-source platform. This platform is the core artefact around which we will be building the develoment part of the project BESSER (Building bEtter Smart Software fastER) funded thanks to an FNR Pearl grant led by the Luxembourg Institute of Science and Technology with the participation of the Snt/University of Luxembourg. As an example, our bot framework will be soon integrated in the platform to enable the specification and generation of software systems with chatbot interfaces.
Key aspects of BESSER’s philosophy
The key elements that (will) make BESSER different from other low-code platforms are:
- It’s open source (and we already determined that there are almost no low-code open source tools), so no vendor lock-in and fully extensible
- Pragmatic approach: we take the best of the languages that we see but we feel free not to be fully compliant with them and deviate when we see there is an easier and more efficient way to do things.
- Low-modeling: we try to accelerate the modeling process. Mostly using AI techniques to facilitate the fast creation of good models. An example is our image to UML importer but expect many more novelties in this area
- Python based (with a little bit of Jinja and a spice of ANTLR) : Each programming language has its own trade-offs. But while many of the “classic” modeling frameworks are Java-based (looking at you my dear Eclipse) we decided to go with Python to offer a better integration with all the machine learning / AI libraries available in the Python ecosystem.
- Targeting the development of smart systems. Any new software system is already a smart software system. Meaning that it embeds some type of AI component in the front-end (e.g. chatbots) or the back-end (e.g. recommender systems). We need a low-code platform that supports the modeling and generation of AI-enhanced systems.
BESSER in a nutshell
You can read the full details in our documentation but, as depicted in the image at the top of this post, the architecture of BESSER is the only “traditional” part.
At the core, we have models created with B-UML. B-UML (short for BESSER’s Universal Modeling Language) is the base language of the BESSER low-code platform. This language is heavily inspired by UML but doesn’t aim to be fully compliant with it. It doesn’t aim to be “unified” but “universal”. Meaning that it is (will be) composed by a set of sublanguages modelers can opt to “activate” for a given project depending on their modeling needs. Right now, B-UML supports mostly static models (kind of class diagrams) but soon will add state machines (already available in the bot framework) and some other more original sublanguages (stay tuned!).
You can write the models directly in Python (instantiating the B-UML classes) but you can also import them from a picture or from PlantUML. In both cases, you can get directly the model object (from which to navigate the model elements) or the Python code recreating that model (so that you can modify the calls to create the model elements before executing them).
1 2 3 4 | # Library class definition Library_name: Property = Property(name="name", property_type=str_type, visibility="public") Library_address: Property = Property(name="address", property_type=str_type, visibility="public") Library: Class = Class(name="Library", attributes={Library_name, Library_address}) |
Based on those models, you can build your own code-generators. We offer a few examples, but you can, of course, built your own. Everything is Python so you’re free to build the generator using technique you want but we are happy following a template-based approach with Jinja as templating language. And ChatGPT knows Jinja quite well so it can help you to build your own code generator templates 😉
1 2 3 4 5 6 | {# Excerpt of the Django model template generator #} class {{ class_obj.name }}({{ inheritance | default('models.Model', true) }}): {% for attr in class_obj.attributes %} {{ attr.name }} = {{ django_fields.get_field(attr.type.name, attr.properties) }} {%- endfor %} {% for association in class_obj.associations %} |
In the roadmap
The BESSER platform is the development leg of the BESSER project so the roadmap will be fully aligned with the overall goals of BESSER, i.e. helping companies building better smart software faster.
In the short term, I can already advance you that we will very soon integrate full OCL support. Those that know me, already know that I believe in the need to precisely define the systems we need to build. And for that, graphical models are not enough and we need a language to specify all the business rules. So, we will have his soon in BESSER.
Then, as for (theoretically) any other open source software, the future direction of the lowcode platform will also depend on the interest and requests of the people. It doesn’t make sense to build something nobody wants :-).
Make sure you let us know what you think, what you want to see in BESSER and don’t forget to star and watch our project on GitHub to be alerted of all our future releases!
So let us kno
FNR Pearl Chair. Head of the Software Engineering RDI Unit at LIST. Affiliate Professor at University of Luxembourg. More about me.
I’m wondering if your concept of BinaryAssociation as a pair of mutually inverse reference properties excludes the possibility of uni-directional binary associations, which are given by a single reference property?
Well you can define the navigability of the association ends to define it as a unidirectional association. Then, the code generator takes this into account to make sure in the generated code only the attribute in the proper class is added. Is this what you were asking or I misunderstood your question?
I think you are following the UML conventions of allowing to define an association between classes A and B independendly of their attributes, while in OOP such an association is already defined/given by a reference attribute A::attr1 : B (having B as its range).
It seems that BESSER also allows defining a reference attribute like so:
# Author attributes definition
author_name: Property = Property(name=”name”, property_type=t_str)
publishes: Property = Property(name=”publishes”,
property_type=book, multiplicity=Multiplicity(0, “*”))
# Author class definition
author: Class = Class (name=”Author”, attributes={author_name, publishes})
Now, without an explicit additional definition of a BinaryAssociation, your model would not have any association, despite the fact that the reference attribute essentially defines one, right?
I like to think I follow “Antoni’s Olivé” school 🙂
In that school, indeed, attribute whose type is another class should be modeled as associations and all associations are (conceptually) bidirectional.
Navigability is part of the design process, together with the fact that the associations end up being implemented as attributes.
In the language, we do support these attributes but I would personally use them as more of part of a refinement process.
There are several frequent cases of attribute constraints (such as interval constraints for numeric/date attributes and pattern constraints for string attributes), for which you don’t want having to write OCL constraint definitions.
Are you going to support defining these constraints together with defining an attribute ?
Not in the short term. At least not before I get the OCL part going. You’re right that we could use “simple” patterns to cover a large number of common OCL constraints (I think there was a paper on that but I can’t find it) but again, it’s a matter of priorities. Obviously, if at some point you have a student interested in giving it a go, happy to assist.