Domanda

I am looking into ways for implementing maker checker principle for various classes over our company repository. Basically the rules are as follows:

  • An entity is an object to be seen on a website (e.g. a blog post)
  • There is a creator of an entity with appropriate permissions/role (e.g. ROLE_POST_CREATOR) (in the original question context, maker)
  • There is an approver of an entity with appropriate permissions/role (e.g. ROLE_POST_APPROVER) and different than the maker of the post (in the original question context, checker)
  • The post has two statuses (DRAFTED and APPROVED) and only posts with APPROVED status are seen on the website

So far so good. Here's where it gets complicated:

  • Not only the post should be approved to be seen on the website, but also should it be approved to be removed from the website (deleted), or to be updated on the website. In other words, updating a post should not affect the post that is currently showing, only after the approval it should show the new version. Same goes for deleting (deleting a post is only a request to delete a post, only after the approval it should actually get deleted)

Modeling this -say in Java- is pretty straight forward:

class SampleClass {
    ...

    private User maker;

    private User checker;

    private Status status;
}

however persisting it into a database (especially an update) is not. Here are a couple of ideas that I could come up with:

  • For every entity, I could have two tables, say SAMPLE_CLASS and SAMPLE_CLASS_REQUESTS, basically, I would duplicate all fields from SAMPLE_CLASS to SAMPLE_CLASS_REQUESTS except for the updated field. Upon approval of _REQUESTS I would then delete it from that table and move the updated version into SAMPLE_CLASS.

This is a very feasible option, though it requires a new entity creation, say SampleClassRequest to be displayed to the checker users. This is quite a feasible option, except for creating a new table for every entity to implement maker checker is quite an overhead in a 100-something number of tables environment.

  • I could create new fields for SampleClass in SAMPLE_CLASS table that are to be updated. In this scenario, I should still generate SampleClassRequest but could escape from the overhead of generating a new table for every entity. However, this looks like a -very- bad database architecture.

How would you go for implementing it? Basically, I am looking for an example library that I could imitate the design, behaviour and architecture, or a (Java) library that already has this feature, or at least guidance/example methodology. Even a sample database design coming from a database administrator would help.

È stato utile?

Soluzione

I would model this with a state change request table. It would refer to the object and the kind of change (publish, delete, replace content). If the request is approved, the state change is executed.

Special consideration would be needed when multiple state change requests are in flight.

Altri suggerimenti

You have two issues to solve: a) keeping track of the latest-approved and latest submitted state and b) applying that behaviour to a large number of entities.

Lets go for a) first. I suggest you use time slices. This means that you store all versions of e.g. a blog-post in the same table. Each version gets a valid-from and valid-until column, nullable. The currently published version has a valid-from in the past and a null valid-until (or something like 9999-12-31 23:59:59). When a new version is approved, you set the valid-until of the previous version to NOW() and make the approved version such that it is now valid. Querying should be starightforward; some SQL dialects have very convenient semantics for this (T-SQL temporal tables, BETWEEN if your valid_until is not nullable).

Now for having hundreds of entities behave this way:

If all your entities are very similar, you'll probably get away with single table inheritance. If your entities vary a lot, especially with relationships that need to be consistent, i'd recommend duplicating all of the columns that you need across all the tables. Thats a lot on the database side, but with Hibernate's @MappedSuperclass it's really no duplication at all in java.

try this instead. I would use the additional status field and i'll create dropdown so that maker can select "submit" and approver can select"approve" so that the same update will be done on my database

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top