4

For context, this project is a personal budget program I am working on while I try to learn to use MVC patterns effectively.

There is a SessionController that passes user commands to a MonthController. Each controller has a Parser that maps commands to controller methods.

Currently, the controller has a Month object as an attribute, and directly calls the model methods. It looks like this:

class MonthController(Controller):
    def __init__(self, budget, *args, **kwargs):
      Controller.__init__(self, *args, **kwargs) 
      self.month  = budget.get_current_month()

    def add_transaction(self, params):
      # get user data, do parameter validation here
      self.month.add_transaction(params)

Is this normal implementation of MVC? Are there pitfalls to letting the Control "own" a Model object I should look out for?

Also, I plan to have the SessionController "own" a number of Views. One of those views will also have a Month attribute (but only call read-only methods). I can't pin down why, but this feels wrong. Am I off track, or is this standard MVC?

g_sue
  • 49
  • 3

1 Answers1

5

Yes, this is quite common (python example, simple java example, java example using a list of models, and C++ example)

Why ? The controller must send commands to the model. So either it knows the model (i.e. it was injected at construction and stored for later reference) or there's a way to find the model on the fly. The later might however make the controller less flexible (for example, using a global reference or a singleton to find the model would mean that all controllers use the same model, unless additional complexity could circumvent this limitation).

A variant that you could consider is to use the command pattern. This could allow to enhance the design with the possibility for undo/redo.

Christophe
  • 74,672
  • 10
  • 115
  • 187
  • I would add that the controller should not own the view. It should use some kind of render('template_file.html', obj_to_render) function which returns HTML to the controller, which the controller sends back in the response. – jpotts18 Nov 23 '17 at 04:49
  • "or there's a way to find the model on the fly. The later would however make the controller less flexible" Why do yo say that? A model factory or some thing could be injected into the controller so it can ask that thing to find the right model. – Andy Aug 04 '18 at 16:20
  • @Andy the reasons are explained btw the brackets: if controller finds the model on the fly (global var or singleton) then all controllers would share the same model whereas Injecting the model at construction would allow to have an multi-model application. Of course, you could also inject an indirect info into the controller and ask on the fly for the model that matches this information. In this case you would indeed have the same flexibility: You are right; But conceptually speaking, that information would be a kind of reference to the model (i.e. via an additional level of indirection). – Christophe Aug 04 '18 at 18:38
  • Your premise that the controller must get the model via global variable or singleton is flawed. And a reference to a factory isn't the same as a reference to a model. – Andy Aug 04 '18 at 19:20
  • @Andy I'm not sure to understand how a factory (which creates individual objects) may address all the controller-model interaction needs. Could you explain your alternative with more details in a separate answer ? – Christophe Aug 04 '18 at 20:39
  • Ok, I guess i'm not being clear. Basically almost your entire second paragraph is wrong. How the controller gets the model instance is irrelevant to whether the controller can talk to the model; it can, but your claim that you either inject the model directly or you have to use a global var or singleton is incorrect. That's what I have an issue with, and its the bulk of your second paragraph – Andy Aug 05 '18 at 15:42
  • @Andy in the second paragraph I give examples ("e.g."); it doesn't aim to be exhaustive. I wanted to express that, if the controller has no reference to the model (be it a direct reference, or an indirect reference via some kind of additional information, using for example a repository) it is probably doomed to work with a single model, which would make it less flexible. But you'll understand that a single paragraph cannot summarise all the possible alternative architectures. Anyway, it is accessory to the answer. I'd still be interested in your alternative answer. – Christophe Aug 05 '18 at 16:02
  • I think your answer generally is fine, but the second paragraph reads as if the controller either gets the model injected or uses a global var. – Andy Aug 05 '18 at 16:32
  • @Andy ok, thanks for the exchange. I've edited the second para to make it less absolute, so to take into consideration your arguments. – Christophe Aug 05 '18 at 16:48