[squeak-dev] Re: Controller|release and View|model:controller: methods

David T. Lewis lewis at mail.msen.com
Sun Jul 8 20:06:11 UTC 2012


There is also a really excellent MVC image prepared by Sungjin Chun that
was recently discussed on the list. You can find it here:
  http://nxt-web.googlecode.com/files/ST80-MVC.zip

I would suggest that you grab a copy of this and look at it for reference.
Try running that image, then open a few browsers and a workspace. In the
workspace you can try doing "inspect it" on each of these three code
snippets in order to start getting an idea of where the dependents are:

  "find all controllers and inspect their dependents"
  Smalltalk garbageCollect.
  Controller allSubInstances collect: [:e | e dependents].

  "find all models and inspect their dependents"
  Smalltalk garbageCollect.
  Model allSubInstances collect: [:e | e dependents].

  "find all views and inspect their dependents"
  Smalltalk garbageCollect.
  View allSubInstances collect: [:e | e dependents].

I'm not sure that there is actually any dependency between views and
controllers at all, so the Controller>>release method may be misleading
in that regard (Andreas explained why the method is there). On the
other hand, views will register themselves as dependents of a model,
and one model can have many dependent views. You can see this happening
in the View>>model:controller: method that you quoted, where the view
(i.e. self in this method) checks to see if it already has a model
(model ~~ nil & (model ~~ aModel)) and if so removes itself as a dependent
of that model (model removeDependent: self). It then adds itself as a
dependent of a new model (aModel addDependent: self). But as far as
I know, controllers do not normally have any dependents at all, so
the Controller>>release method very likely does nothing at all most
of the time.

Dave


On Sun, Jul 08, 2012 at 12:31:08PM -0700, Andreas.Raab wrote:
> Hi Peter -
> 
> Your observations are correct. First, IIRC the reason for
> Controller>>release is to aid the garbage collector. In some early versions
> of Smalltalk, the GCs weren't capable of detecting cycles so having the view
> point to the controller, and the controller point to the view would not
> allow any of them to be GCed, thus the need to call Controller>>release.
> 
> As to View>>model:controller: and its interaction with Controller>>release,
> I think your observation and cure are both entirely correct. Since you are
> doing a reimplementation I would probably just stay away from
> Controller>>release alltogether. There should not be a need to ever call
> this, all modern systems have GCs that can cope with this problem. But if
> you want to keep release, checking for being the current controller should
> work just fine.
> 
> It might also be worthwhile to check out VisualWorks NC (another heir to
> ST80 with a more modern incarnation of an MVC framework) to see if
> Controller>>release is still present there and if so, what it actually does
> :-)
> 
> Cheers,
>   - Andreas
> 
> 
> Peter Michaux wrote
> > 
> > Hi,
> > 
> > My first time posting here. Hopefully I've found the right list for my
> > question.
> > 
> > I've created a JavaScript MVC framework for browser applications. The
> > popular JavaScript "MVC frameworks" are not really MVC so I decided to
> > build one that actually is. (https://github.com/petermichaux/maria)
> > Although I'm not a Smalltalk programmer, I've used the Squeak View and
> > Controller classes as my primary implementation inspiration. There are
> > many places in my JavaScript code that are line-by-line ports from
> > Squeak. I've found that the few times I've experimented and deviated
> > from the principles of the Squeak View class, I've usually ended up in
> > hot water and reverted.
> > 
> > I've been considering one deviation for a long time in my versions of
> > the Controller|release and View|model:controller: methods because I
> > just cannot grasp the motivation for why the Squeak code works as it
> > does. The Squeak code for Controller|release is
> > 
> >     release
> >         "Breaks the cycle between the receiver and its view. It is
> >         usually not necessary to send release provided the receiver's
> >         view has been properly released independently."
> > 
> >         model := nil.
> >         view ~~ nil
> >             ifTrue:
> >                 [view controller: nil.
> >                 view := nil]
> > 
> > and the View|model:controller: method
> > 
> >     model: aModel controller: aController
> >         "Set the receiver's model to aModel, add the receiver to
> >         aModel's list of dependents, and set the receiver's controller
> >         to aController. Subsequent changes to aModel (see Model|change)
> >         will result in View|update: messages being sent to the
> >         receiver. #NoControllerAllowed for the value of aController
> >         indicates that no default controller is available; nil for the
> >         value of aController indicates that the default controller is
> >         to be used when needed. If aController is neither
> >         #NoControllerAllowed nor nil, its view is set to the receiver
> >         and its model is set to aModel."
> > 
> >         model ~~ nil & (model ~~ aModel)
> >             ifTrue: [model removeDependent: self].
> >         aModel ~~ nil & (aModel ~~ model)
> >             ifTrue: [aModel addDependent: self].
> >         model := aModel.
> >         aController ~~ nil
> >             ifTrue:
> >                 [aController view: self.
> >                 aController model: aModel].
> >         controller := aController
> > 
> > By the nature of the strategy pattern, controller objects are intended
> > to be swapped in and out of view objects to modify the behavior of a
> > view. The problem that I see is that when changing the controller of a
> > view, the View|model:controller: method does not nil the view of the
> > previous controller which is being replaced. This means that several
> > controller objects can exist pointing to the same view (but the view
> > will only point to one controller.) If the release message is sent to
> > a controller that is not the view's current controller, then the view
> > still looses it current controller!
> > 
> > I'm not very good at writing Smalltalk but to illustrate the point,
> > I'll give it a try...
> > 
> >     alphaController := Controller new.
> >     betaController := Controller new.
> >     view := View new.
> >     view setController alphaController.
> >     view setController betaController.
> >     alphaController release.
> > 
> > That last line will actually remove betaController from view which
> > seems like bad behaviour to me.
> > 
> > One solution is to modify View|model:controller: to nil the previous
> > controller's view. Another solution would be to modify
> > Controller|release so that the controller checks that it is the view's
> > current controller before the line "view controller: nil." Both of
> > these could be done together.
> > 
> > I'm very curious to know why the Squeak Controller|release and
> > View|model:controller: methods seem to leave this seemingly trouble
> > spot open. Thanks for any thoughts you can share on this issue.
> > 
> > Peter
> > 
> 
> 
> --
> View this message in context: http://forum.world.st/Controller-release-and-View-model-controller-methods-tp4639127p4639147.html
> Sent from the Squeak - Dev mailing list archive at Nabble.com.


More information about the Squeak-dev mailing list