-3

Given a collection of objects and an action id (there is a corresponding "action controller" class, which can be found with the id), what is the best way to organize mass action on the objects?

There are some twists though:

  • an action is already implemented for a single object,
  • action may need pre-checks. Those then warn the user, that the action in question can't be performed for certain objects
  • mass action algorithm is not just a single action applied to each object. It's optimized, and also has some extras, compared to single action, and also extra constraints on eligibility of objects upon which the action can be performed
  • mass action also has some metadata, which needs to be provided to UI even before pre-checks
  • thus, mass action class (a) gives metadata on which parameters are needed, varying from action to action (b) can make preliminary checks for a set of objects (c) can attempt to perform mass action and return the result (for UI)
  • it is desired to have single and mass action more or less in one place, so if it needs to be modified, only a single module or class needs to be changed

I am sure this situation is not unique, and the pattern for this probably already discovered in the wild. Current approach of having methods and mass-methods does the job, but is not quite elegant. Also providing metadata from the action class does not require collection of objects at all, so making it conditional when getting an instance of action controller does not feel good.

Note, that we abstract from what there is in the objects. Action on an object is not about calling some single method of an object. For simplicity, objects can be considered as just entities of just one type or even records.

Hoping for something more or less classic (for instance, not abrupt switch to CQRS).

Note 2. Action means domain-specific action at the backend.

Roman Susi
  • 1,763
  • 2
  • 12
  • 20
  • 1
    Does this answer your question? [Choosing the right Design Pattern](https://softwareengineering.stackexchange.com/questions/227868/choosing-the-right-design-pattern) – gnat Mar 23 '21 at 08:58
  • No, it does not. Is it off-topic nowadays to ask a question to help recognize design patterns here as I got whole 3 downvotes? – Roman Susi Mar 24 '21 at 05:20

1 Answers1

1

Depends on what you mean by Action.

If we are talking in terms of the UI, then the only way to make this harmonious is to treat a single action as the special case of the multi-action where n = 1.

The moment you say there is an optimised pathway for operation on a single item, its already a distinct and separate UI action. Its up to you if you make the same class responsible for both, or if you choose to co-house them in the same sub-directory. Both have benefits, both have cons.

But, mentioning that optimisation. What exactly are you optimising?

  • The path a user has to take to achieve a result?
  • or the way in which the operation itself is applied to one vs many instances?

If you are optimising the first way, then great both the n = many and n = 1 UI actions can be created in terms of the same fundamental operations. Even better there is a good architecture for handling this whatever the N is. Its called Pipes and Filters. The unix command line language excels at this, you can also find a good example in LINQ, among other libraries.

The idea is to create mini-programs that perform one action well, and then link them up using pipes to create whatever meta-behaviours you want. In your case the pre-checks are filters that look at an incoming input and decided to send it out to one, many, or no outputs. One output might be linked up to a process that performs the operation, another might be linked up to yet more checks, and another might be linked up to the UI to tell the user which ones could not be processed.

Now if instead you have the second approach where you have optimised operators and filters based on some nuance of the objects being processed, you will need a more powerful engine. Take a look at SQL, and the interpreters that decide how to translate the problem, into one of the myriad of ways to actually implement solve it.

You don't have to go full blown compiler, but in this case the correct action is situational based on not just what you are doing, but what you are doing it to (in both the individual and group senses of to). In the simple case a Finite State Automaton, in the more complex case a Push-down Finite state Automaton (an FSA with a stack) is what you are looking for. Each State (node) represents a question to ask about what is be processed, or what the requested action is. The transitions (edges) represent an answer to that question. Each stack push represents a new train of investigation that needs to be worked out before resuming the older train of consideration with new knowledge.

The types of each node can be generalised to handle many different inputs, and transitions can be customised based on the problems being handled.

Kain0_0
  • 15,888
  • 16
  • 37
  • Thanks. I've added note, that it's not UI action. As for implementation, Graph of transitions is actually there already: here only one edge is considered. The question is how to describe single-action-many-objects in OOPish way so that repetition is minimal. – Roman Susi Mar 24 '21 at 05:32