5

My question is about the way to represent data models created at runtime.

To illustrate, let's say we would like to create a CMS-like app in which end-users may create custom forms. Those forms are themselves made of different field types (text, number, date...)

A form model could be represented this way (language agnostic) :

MyForm {
    Text name;
    DateTime date;
}

Once those form models are created, we can instantiate them to collect data. A form submission will be an instance of the form model.

What's important to understand here is that both form data and form model are "user-level" data. There's no such MyForm class defined in our application code since everything here is defined at runtime.

My question is : how, at developer-level, can we represent the form model data-structure ? I would like to be able to use the app's programming language to dynamically create classes that match our form models, but I do not consider a good practice do to so. On the other hand, I don't think it is smart either to recreate OOP at a higher level of abstraction ...

More generally, my question is : how to deal with different levels of data and models ? In my example there are clearly two levels : the application-level, with the Form class, and the user-level in which we define a precise type of form, which is also a data model but not on the same abstraction level.

9
  • What are your users actually manipulating? MyForm or some sort of UI over it? – VLAZ Jan 20 at 14:29
  • Both actually. The UI is here for convenience but the "real" data is MyFrom as it represent the data model the simplest way. – ibi0tux Jan 20 at 14:50
  • OK, let me rephrase then - if I was one of your customers, I'd have access to the CMS. Do I write code and directly interact with MyForm? Or is it the system which interacts with MyForm on my behalf? In the latter case, I do not and cannot interact with MyForm directly. – VLAZ Jan 20 at 15:09
  • Actually this is somehow what am I asking. MyForm { Text name; DateTime date; } is not code actually. It is just a representation of the form, I could have put an UML diagram instead. I am preciely wondering if MyForm should exist or not as a data model in the language is written in or if it is just an end-user-level abstraction. But, to answer your question, I want the end user to be able to define the forms in "programmatical" way, with something like JSON or custom code. Hope it is clearer. – ibi0tux Jan 20 at 15:18
  • 1
    Dividing an application into separate layers or contexts commonly involves writing a custom mapping at the boundary since nearly always some friction involved in trying to reconcile two different viewpoints of the same data. For example, an ORM generally needs a mapping between a SQL schema and an application's data access layer. Another example could be using the MVC pattern and mapping between data/entity models and ViewModels. It's often unavoidable to need additional custom code which translates between those different worlds. – Ben Cottrell Jan 20 at 17:34
1

For representing the data, you will usually need a meta model, a model of how your data shall look like, something like a database schema. The app will have to provide a schema designer component, there are tons of existing examples for this category of applications. The schema itself might be implemented using some data dictionary.

For an UI component which can manage data which confirms to the schema, the app could dynamically generate some tabular components from the schema. This might be extended with some visual meta data how the tables should be presented (like color, column widths, lots of visual attributes). Alternatively, you could allow the user to use some descriptive DSL like XAML to let the user design a more flexible UI, and add data binding capabilities.

There are several kind of frameworks / development environments which support these kinds of ideas (which are not really new, for example, have a look at 4GLs, RAD, or low code platforms ). But don't underestimate the effort if you want to create something like this on your own.

2
  • This is what my question is all about : how to deal both with meta-models that represent generic form concept and each different form's model which would each represent the structure of of the data that would be entered in these forms. And as you mention it we can also add additionnal abstraction layers with models that would add meta data, which means we need to combine form model with additionnal fields. – ibi0tux Jan 25 at 11:18
  • and each different form's model you don't deal with them because they don't exist. There's only one possible model, the meta-data model. Think in XML and XSD. Your meta-model is the XSD defining the elements available and their properties, constraints, features, etc. Then you have an undefined number of XML applying these rules. If were to map these XML to classes, you will still have only one model, no countless models (classes) for each XML possible. – Laiv Feb 3 at 9:58
1

I would like to be able to use the app's programming language to dynamically create classes that match our form models, but I do not consider a good practice do to so. On the other hand, I don't think it is smart either to recreate OOP at a higher level of abstraction ...

The idea isn't new. In Java, we have libraries addressed to create classes from scratch in runtime and once created they work as they had been in the classpath since the starting of the application. I find this kind of things amazing and I would definitively consider implementing solutions as the one suggested, but IMO, the cons outweigh the pros.

For the sake of the answer, I won't go deep into details but some of the cons I see are:

  • The impact on the memory
  • Sizing the memory requirements
  • Application behaviour predictability
  • Debugging and error solving
  • Hard to reason about
  • Hard to integrate with frameworks and libs
  • Goal deviation

I find the solution to be sophisticated but makes my life a bit harder. Developing this approach is not trivial and probably will deviate my attention to something different than solving the main problem: Making dynamic forms for my CRM.1

That said.

how, at developer-level, can we represent the form model data-structure?

Document <|--- Form <>----- Field

Documentand Form are logical models or metamodels, whatever you like more.

MyForm tho

  • is not a model per se
  • it is not a type
  • it's an instance of my logical model.
  • It's a Document. More precisely, a Form.
Document {
  MetaData meta
}

Form {
  Collection<Field> fields
}

Field {
   MetaData meta
   Object defaultValue
   Object value
}

Note: I have pictured Form as an aggregation of fields. It could also be a composition of fields. Or a mixup, why not?

Basically, there's only one model Document which "type" varies from instance to instance. Regardless of the composition, all the instances are Documents.

MetaData is important because it completes the definition of each node of the Documentat the document itself. For example, it has the name of the document, the target, method and validations of the form, the value range or the data source of the field, the placeholder, the default value, etc

While Document ensures the invariants for any instance of Document (meta is not null, has a name, etc), Form ensures the invariants for any instance of Form (MyForm has fields, has a name, has a target, has a method, etc).

Later, you can persist/map instances of the metamodel as you wish. As JSON, as an XML or as rows in any RDMS. It should be easy to integrate with your favourite ORM or mapper too, somethin I presume that is not going to be so simple with classes created and compiled in runtime.


1: A premise to me is that the complexity of a solution should proportional to the complexity of the problem is solving. If the problem was making a framework for many and different types of applications, I would consider creating classes in runtime. But it's not the case.

0

I can't see your point. MyForm and Form above are not equivalent. Form is much more generic and provides far less 1) type safety, 2) communication clarity. It is easy, for example, duplicate particular field N times as N different elements of the fields; or define duplicate name with contrary values, etc.

More then that, Array<FormField> fields does not free this code from being part of user-space. Mainly because at some point you gonna need name and date anyways, that's required by business. So you will either filter or somehow index that array to get necessary field and thus tight your code to the "user-space".

In addition to that, assuming Form is provided by some UI framework you are on, MyForm seems nothing but a GoF's Facade.

4
  • 1
    Sorry, maybe my question wasn't clear. What I meant is that the data end user will manipulate are MyForm instances. The user can create a form model just like MyForm is, but form models will be instanciated to create different forms. Data from those forms will be collected and stored (and this is why defining a data model for each form model is important), etc. The point is there is already a "data model" structure that exist (the classes), why couldn't I use the same mechanism to represent "end-user data models" too ? – ibi0tux Jan 20 at 14:04
  • @ibi0tux > a facade is an object that serves as a front-facing interface masking more complex underlying or structural code. That is exactly what you have described. – Sereja Bogolubov Jan 20 at 14:06
  • yes, but my problem is that thoses facades are in my case supposed to be created at runtime. – ibi0tux Jan 20 at 14:10
  • 2
    @ibi0tux than you question is quite misleading. You are asking about inheritance and the way compile-time known abstractions are related. I see no connection to dynamic/runtime here. Maybe you could rephrase your question and provide more specific illustrations of your particular problem? – Sereja Bogolubov Jan 20 at 14:13
0

First, object-orientation does not deal with data, only behavior. This is important, because it kind-of answers your question.

So, as far as I understand, your application deals with Forms. Those forms can be instantiated and be filled out. So would a MyForm behave differently? From the app's perspective no. It would still be instantiated, filled out, presented, etc.

If things behave the same way in OO, they are the same thing/type/class. Regardless of the data that's inside them.

How to deal with data? Answer: you don't. You deal with behavior.

How to handle multiple levels of abstraction? Partial answer: You only deal with those levels that would result in a different behavior.

Does that help?

4
  • I think I understand what you mean. But how to a make the distinction between "behavioral attributes" and "data structures". I think there's a sort of duality : MyForm can be seen as an instance of a Form class that defines the behavior of all forms ; and meantime MyForm defines a data structure that gather all fields specific to that kind of form and can be instanciated itself. It is clearly this duality that I don't know how to handle. – ibi0tux Jan 20 at 15:46
  • 1
    I agree that in some abstract sense MyForm could be seen as an instance of, or even subclass of Form. But as I said, if the Form already has the appropriate behavior to show any number of fields and let the users fill that out, there is nothing gained by statically defining MyForm. There would be no alternate behavior, therefore no need to create it. I understand you are worried about the Inner Platform Effect. But I don't think dynamic data structures are an OOP platform feature. – Robert Bräutigam Jan 20 at 19:14
  • Thank you, I didn't know the Inner Platform Effect was so called. Without a MyForm data structure, how the data coming from the filled forms will be represented ? It seems much more easier to access data with myFormInstance.getName() than iterating over all fields from a generic form structure, doing manuel type checking, etc. – ibi0tux Jan 21 at 7:21
  • Why would you have to write myFormInstance.getName()? I thought you are implementing the CMS system itself, the forms will be later defined by the users, right? You do not yet know that myForm will exist, and the users who do know about that don't get access to your code directly. So I think nobody actually writes myFormInstance.getName(), right? I mean the users might do it in their code, if they have code at all, but not in your code. – Robert Bräutigam Feb 3 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.