6

I have been working on a project that deals with, let me simplify, Schools and Students.

The general requirement is that certain Students could be assigned to certain Schools to work an internship.

But the Schools are not only Schools per se, those can be Hospitals, Prisons, Nursing Homes, etc..

Since I'm using an ORM and Entity classes, my first idea was to use Inheritance mapping, like, to have a parent class InternshipProvider with particular child classes...

However, another requirement is that this should be done so that any User in future can add the new instance of InternshipProvider by using a form AND at the same time to be able to add some specific properties. Sometimes to the class, and sometimes only to particular instance.

Per each instance, the InternshipProvider may have or not, a set of specific properties, which could be available on a form as text fields or choice options, or a subform, etc..

So I kinda solved it like this: There is the InternshipProvider class, among standard properties it has a long text property as well. And inside of that text property (field) are JSON key-value pairs, describing those specific fields and values stored.

There is also a "monster", custom form generator feature, that handles this fairly OK. Each InternshipProvider instance has a specific custom form assigned to it for future editing.

There are two reasons for these requirements:

  1. They want to eliminate a need for hiring a software developer in future.
  2. The domain IS complex and unpredictable.

Do you have a better idea? Is there some concept that covers this? Some design pattern or the likes? What would you say to the Client?

Thank you

4 Answers4

13

I've no idea why Hospitals, Prisons, Nursing Homes, etc need their own classes. Nothing here makes me think they do. Why aren't these simply different instances of InternshipProvider?

Not everything with a name needs to be a class. You need polymorphism if a Hospital needs the same method to have a different implementation than a Prison. Otherwise, these classes are pointless.

The only "unpredictable" thing I can see here is what the next InternshipProvider will be called. Show me some behavior that needs to be different based on which InternshipProvider and I'll rethink this.

candied_orange
  • 119,268
5

The pattern you are looking for is called EAV or Entity Attribute Value.

In this pattern you would set up a table with a row for each attribute and another table with values for each entity x attribute combination.

Values are stored as strings, but you can define meta data in the attribute table to tell the system how to parse the string, e.g. as a date or integer. If you don't have metadata, it makes validation difficult and sorting will come out wrong.

EAV isn't always the best in terms of performance, but it will perform much better than a giant JSON string, especially if you need to sort or filter based on these attributes.

John Wu
  • 26,955
3

I would go for a Dictionary of 'Custom Fields'

public class InternshipProvider 
{
    public string Id {get;set;}
    public Dictionary<string,string> CustomFields {get;set;}
}

mapped to the following table structure

TABLE InternshipProvider
    varchar Id ('myguid')

TABLE CustomFields 
    varchar Id
    varchar ParentId ('myguid')
    varchar ParentType ('InternshipProvider')
    varchar Value
    varchar TypeToCastTo?

You can expand this to other types that require custom fields.

Then for querying you can do something along the lines of...

InternshipProviderList.Where(i=>i.CustomFields[keytosearch] == valuetosearchfor)

or some dynamic sql fun

Now obviously the more complex you make your acceptable query logic, the more complicated it becomes to write the query.

You can see how you might insert different functions for different comparators and then maybe loop over multiple clauses, maybe work out how to handle AND vs OR, brackets, dealing with nulls etc. At some point (quite soon) you require programmers to write the query.

I have found that its usually easier just to hire a programmer to add the new logic you require as it comes up than try to write a generic system that can handle everything AND do it in a way that is simple enough that your users don't have to be trained in the meta-programming language of the system.

Not sure I would tell the client that though, maybe mention the risk, but give them what they want.

Ewan
  • 83,178
2

There is no reason for convoluted solutions like saving JSON. You have a table where each row is an internship providers. Then you have a table with internship provider properties, where each row describes a property associated with an internship provider through foreign key.

And if a property in turn have options which are associated with a specific internship provider, you just further create a table with options, with a foreign key to the internship provider property.

It is easy to create a form which adds a row to a table.

JacquesB
  • 61,955
  • 21
  • 135
  • 189