DISCLAIMER: Work In Progress

Gennitor, is a novel automated code generation and reasoning system, potentially applicable to any programming language and technology, by modelling the essential questions and answers, based on Aristotelian Philosophy a.k.a. Aristotelianism.

1. Introduction

User interaction with business applications, either for small-businesses or enterprises, is always characterized by two fundamental operations, in which users must be able to:

  • (a) Enter and store data

  • (b) Request and restore data

Entered data are most commonly stored in a repository or used as inputs for calculations and queries. Retrieval of data is most commonly based on predefined or dynamically built criteria for a single entity or a collection of them.

Phenomenally, building a business application should be a simple operation then, but the reality does not agree. Building a business application serving its purpose as expected, can be a highly complex and time consuming operation. Complexity is related to multiple parameters, such as the expertise of the development team, the dedication of business stakeholders, communication between the parties, budget, technology constraints, time constraints, non-functional requirements for security, performance, SLAs etc.

1.1. Automatic Programming

One way to reduce complexity is Automatic Programming (or Automated Code Generation). Automatic Programming identifies a type of computer programming in which some mechanism generates a computer program, that otherwise human programmers would have to write themselves, to allow humans to write code at a higher abstraction level.

Although it is difficult to give a clear and concise definition of Automatic Programming, it is easier to describe its benefits, which can be summarized as follows:

  • Increased productivity & velocity

  • Consistency

  • High quality assurance

  • Effective code re-use

  • Focus on domain problem solving

Gennitor highly embraces the Domain Driven Design (DDD) approach and the Hexagonal Architecture (Ports & Adapters), meaning human programmers should focus on solving domain problems. Computer programmers, such as Gennitor, can generate the boiler-plate code required in the various layers.

1.2. Technologies

As far as the business application is concerned, the work presented here assumes a layered-architecture, with a well-defined API. Although Gennitor is agnostic of technologies and the preferred coding language used in the generated code, for the shake of the examples presented here, it is assumed that Java Spring for the back-end and latest Angular for the front-end are used. Gennitor itself is written in Java.

1.3. Synopsis

Gennitor is derived from the Greek word: γεννήτωρ, genitor or generator, the one who gives birth

2. Philosophical approach to Business Applications

The core of Gennitor is based on a series of "Whys". Posing the necessary "whys" is helpful for a better understanding of the goal and the path to reach it.

2.1. On Teleology

Every business application must be teleological, meaning it must serve a specific purpose or goal. Teleology or finality is a reason or explanation for something in function of its end, purpose or goal.

Teleology is derived from two Greek words: τέλος, telos (end, goal, purpose) and λόγος, logos (reason, explanation).

Breaking deep down a business application, it is decomposed into a set of building blocks called methods or functions. This holds true for any programming language object-oriented or not. Since every business application must be teleological and it is decomposed into a series of functions, by analogy, every function ought to be teleological, too.

Analogy, from Greek ἀναλογία, analogia (proportion), is a cognitive process of transferring information or meaning from a particular subject - the analog or source, to another - the target, or a linguistic expression corresponding to such a process.

Regarding functions, according to Google’s definition:

Function is an activity that is natural to or the purpose of a person or thing.

Since in programming we don’t have "natural" functions or "persons", but we do have "purpose of" "things", it is rational to claim that programming functions are indeed teleological, existing only to serve a purpose or goal for a thing.

For the sake of the context discussed here, "function" is meant to be "programming function" and the definition is rephrased to:

Function is an activity to or the purpose of a thing

The above definition suits better to the need of defining a "programming function", but it is still particularly vague, producing fundamental questions:

  • What kind of activity?

  • What kind of purpose?

  • What kind of thing?

In order to answer these questions, it is necessary to examine in more detail the "function" concept.

2.2. The Anatomy of a Function

A function in any programming language is characterized by:

  • a name,

  • optional inputs,

  • optional output and

  • a body.

A generic pseudocode describing a function could be:

Optional Output function-Name(Optional Inputs 1, ...., N) {
    function-Body
    Optional Return
}

Utilizing though, the definition of a programming function provided above, and more specifically by utilizing the terms "activity", "purpose" and "thing", the pseudocode can be rewritten as:

Optional Output purpose-Thing(Optional Inputs 1, ...., N) {
    activity
    Optional Return
}

Subsequently, a more complete definition of "function" including input and output would be:

Function is an activity to or the purpose of a thing, with optional inputs, optionally returning an output

At this point the definition of a function has begun to take a form, but still the reason of existence of this function is not clear. What is its purpose? What is its "Causality"?

2.3. The Aristotelian Theory of Causality

Aristotle introduced the "Theory of Causality", which defines the end, purpose, telos, or final "cause" as that for the sake of which a thing is done. 

The "Four Causes" are elements of an influential principle in Aristotelian thought whereby explanations of change or movement are classified into four fundamental types of answer to the question "why?".

We do not have knowledge of a thing until we have grasped its why, that is to say, its cause. Aristotle

Aristotle held that there were four kinds of answers to "Why" questions regarding the understanding of a "Thing". The Four Causes are:

  • Material Cause: "that out of which"

  • Efficient Cause: "the primary source of the change or rest"

  • Formal Cause: "the account of what-is-to-be"

  • Final Cause: "the end, that for the sake of which a thing is done"


The magic behind the Four Causes is that it can be applied to almost anything. At least anything that can be materialized. For example, why does Gennitor exist?

  • Material Cause: Java, Spring, Camel etc.

  • Efficient Cause: The Author

  • Formal Cause: The Idea of Automated Code Generation

  • Final Cause: Solve problems of productivity, velocity, consistency etc. when creating business applications

2.4. The Thing

What is a Thing? In principle, Anything.

Anything that makes sense to the business application. In order though, to distinguish Thing A from Thing B, it is necessary that a Thing has at minimum a Name.

For the shake of automatic programming, it would be particularly useful if similar Things can be grouped together. This can be achieved by introducing a Thing Type. Type is a keyword or description making sense to the business, which again can be anything.

Finally, a Thing is better understood if its fundamentals properties are known. Fundamental properties are the absolutely necessary properties required, in order to fully characterize it.

Thing example:

  • Name: "Client"

  • Type: "Company"

  • Properties: "Company Name, Company ID, etc."

2.5. The Function Revisited

Taking into account the (a) function definition provided earlier, (b) the Aristotelian Four Causes and (c) the Thing description, let’s try to analyze the following simple example of a function written in Java:

int add(int a, int b) {
    return a + b;
}

What is the Thing?

  • Thing Name: "i.e. The concept of adding two numbers"

  • Thing Type: "i.e. Simple Math Calculation"

  • Thing Properties: "First number, second number and result"


What is the Activity?

The body of the function, namely: "a + b"


Why this Function?

  • Material Cause: The Java code provided above (and it exists because Java exists and programmers are able to write code in Java)

  • Efficient Cause: The author (which is a programmer and knows how to write software code)

  • Formal Cause: The transformation of two numbers into one ()

  • Final Cause: The sum calculation of two numbers (to be used in an accounting application)


Based on the previous, the final definition of a function in the context of automatic programming, becomes:

Function is an activity expressing what has to be done (Formal Cause) written by a programmer (Efficient Cause) in a specific language (Material Cause) to or the purpose (Final Cause) of a Thing characterized by a Name, a Type and Properties provided as activity’s optional inputs and output.

3. The Final Cause and the API


api

In computer programming, an Application Programming Interface (API) is a set of subroutine definitions, communication protocols, and tools for building software.

In a well designed layered application, the API is a clean module composed of interfaces and Data Transfer Objects (DTOs), ideally, with no dependencies to any other modules. In a layered architecture, the API connects the frontend with the backend. High-level user requirements must be easily identified there. For example, if a requirement is to "Create Customers", the API (in Java code) could be:

public interface CustomerService {
    CreateCustomerResponse createCustomer(CreateCustomerRequest request);
}
public class CreateCustomerRequest {
    private String firstName;
    private String lastName;
    // Getters and setters omitted
}
public class CreateCustomerResponse {
    private String customerId;
    // Getters and setters omitted
}

From the code snippets above, it is easily deduced that:

The application should allow the creation of customers, provided the first and last names, and upon successful creation a unique customer ID must be automatically created and returned to the caller.

4. High level architecture

In a typical software team structure the key roles are:

  • Project Manager or Product Owner etc.

  • Analyst / Designer etc.

  • Architect or Implementation Manager etc.

  • Developer, Tester etc.


gennitor architecture

4.1. Project Manager: The Demiurge

The project manager usually acts as a buffer between the business requirements and the team, coordinating the members. Provides to the analyst / designer the raw data as requirements posed by the business. As soon as the analyst’s work is completed, the project manager requests from the architect to proceed with the implementation.

In the Platonic, Neopythagorean, Middle Platonic, and Neoplatonic schools of philosophy, the Demiurge is an artisan-like figure responsible for fashioning and maintaining the physical universe. The Gnostics adopted the term "demiurge".

4.2. Analyst / Designer: The Syllogist

The role of the Analyst / Designer is to define:

  • What has to be done a.k.a. The Final Cause

  • Deduce and formalize the details of what has to be done a.k.a The Formal Causes

Based on the previous example about creating a customer, it is clear that the Final Cause is to "CREATE" a Thing named "CUSTOMER".

In order to create a customer, we need a UI, UI input validation, calling backend by REST, processing the request and storing in a repository. All the previous steps are the Formal Causes, supporting the Final Cause.

It should be noted here, that the Formal Causes of UI, input validation, REST and storing are not concerned about any specific technology of methodology. They rely instead, on the abstract ideas of UI Input, Persistence etc.


Syllogism an instance of a form of reasoning in which a conclusion is drawn (whether validly or not) from two given or assumed propositions (premises), each of which shares a term with the conclusion, and shares a common or middle term not present in the conclusion (e.g., all dogs are animals; all animals have four legs; therefore all dogs have four legs ). Syllogist is the one who applies or is skilled in syllogistic reasoning.

4.3. Architect or Implementation Manager: The Mechanic

The architect or implementation manager is based on the outcomes of the analyst / designer and drives the developers to write code in specific coding languages, following pre-defined coding standards.

A Mechanic is a tradesman, craftsman, or technician who uses tools to build or repair machinery.

4.4. Gennitor Annotations

Gennitor is not intrusive. The only dependency needed in a Java application is Gennitor Annotations. By properly annotating the methods in the API, Gennitor can do its magic.

4.5. Engine

The Demiurge, Syllogist and Mechanic are the core modules in Gennitor’s engine. They cooperate with each other and the Four Causes, in order to automatically produce source code.

5. Models

6. The Syllogist

7. Showcase

COMING SOON