2021/12/17/The Great Data-Class Restacking

From Woozle Writes Code
Jump to navigation Jump to search

Okay, it's finally time to do this. The strain from having the old data-classes kind of dangling off one side of the PortBank classes has been building for some weeks now, and I finally got to the point where it didn't make sense to keep trying to spackle over the gaps.

The existing class structure is in two parts. There's the old set of classes which goes back to before Ferreteria even had a name, and there's the newer set of classes around the PortBank class. The old classes still have a role to play, but a large chunk of their functionality needs to be moved into the Storage PortRow classes.

The Old Way

The database I/O classes consist of basically:

  • Database
  • Table
  • Rowset
  • Record

Applications would descend from Table and Record (and sometimes Rowset) to create app-specific functionality, which (obviously) had to be oriented around specific tables (or queries) in the database. (This tethering has not actually been a problem yet, although I imagine it eventually will be.) URIs then directed the application as to what Table was going to be the focus of the current activity, and generalized code would ask the Table to please display itself and do whatever else needed to be done based on other data in the URI (or in cookies, etc.)

What has been a problem -- and what led me to create the PortBank classes in the first place -- is the following:

  • Values in Records are kind of ambiguous as to whether they're in as-received (from the database) format or an internal format suitable for calculations. These two formats are identical often enough that it wasn't a problem at first.
  • Record fields do not know how to translate certain kinds of value into database-writable values; the app must write its own code anytime a field needs special treatment.
  • Record fields also do not have any standard way of managing screen I/O; this had to be hand-coded.

Those needs led to the creation of the PortRow classes, which handle translation to and from Storage and Display formats.

However, we're now left with a lot of specialized Table and Record descendants which do some of the work which should be in the PortRow, and a lot of tight dependency between the Database class and how the Records are loaded.

The New Way

It's time to simplify the data-storage I/O classes back down to utility-level functionality, knowing nothing about the fields they're reading or writing, and let the PortRow classes handle all of the app-specific and field-specific stuff (as they are increasingly doing already).

The most dramatic part of this is that instead of loading a Table from the URI and asking the Table to do stuff, we need to load the associated PortBank class and ask it to display its output. It can then do whatever it thinks needs to be done, which typically will involve loading a dataset and displaying it but could be something much less data-driven.

I expect this structure will offer a lot more flexibility in terms of how each feature (formerly Table) behaves. In theory, we could have a PortBank descendant that isn't closely tied to a specific Table; I need to make sure to set up the class-structure that way...

To-do list for now, then:

  • Change the URI-processing code so it uses a PortBank class instead of a Table class.
  • Move all remaining specialty Table/Rowset/Record code into appropriate PortRow classes.