dimanche 15 décembre 2019

Directed graph edge restrictions pattern

I have a directed graph (in JS/TS but that's a general programming patterns question) where each vertex is a child class of Shape and the children are the different shapes, e.g cycle, rectangle etc. I'm looking for a design pattern for the following problem:

Problem: Each vertex has its own rules regarding what it can be connected to or from, which are sometimes not simple

  1. some rules are easier to check from the target vertex class (e.g. cycles must have no incoming edges) and some others are easier to check from the source vertex class (a circle can have no outgoing edges)

  2. some rules are two way, e.g. a rectangle can be connected to / from circles, triangles. I can check this rule from the source vertex focus (In rectangle class method validateEdge, make sure target is not any of these) or from the target vertex focus (in classes circle and triangle, in the validateEdge method make sure source is not circle). I shouldn't be checking for the same rule multiple times.

  3. some rules take into account an attribute of one of the vertices, e.g. circles are only connectable to rectangles that are red etc. Thus I can't just have a map of key value pairs that capture the rules and the validation runs over the map to check if any applies.

Currently I have it implemented as the naive way; given an edge, check all the rules by conditioning on the type of source and destination, which is obviously ugly and unmaintainable.

My proposed solution The best thing I came up with is to have a method isConnectableTo(target) for each Shape. This restricts validating edges from the source vertex focus thus it avoids the problem of checking the same rule multiple times, one from the target vertex focus and one from the source. The problem is that it doesn't fully capture the first requirement and also I still need to condition on the target type before I check for which rules apply.

Any other solutions?

Thanks

Aucun commentaire:

Enregistrer un commentaire