Questions about Magritte

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Questions about Magritte

hernan.wilkinson
Hi,
 I been reading and using Magritte for a couple of days and it is impressive how fast a web app can be written with it.
 We are planing to use it in the development of a major app, but I have some concerns/questions that I would like to ask. Most of them are related with the coupling it generates between the model and the view using the descriptions. These are the questions:
(I wanted this mail to be short, but it turned out sort of long... sorry for that...)

1) Has anybody defined the descriptions in other class but the model class? It seems to me that defining the descriptions as class methods in the model class creates a coupling between the model and the view that I would like to avoid. Part of that coupling is because of some view's "attributes" like label, priority, beSorted, readOnly, etc. It also couples the model with Magritte, which avoids me to use the model in an environment without Magritte.
I was looking around and it seems possible, but the method #asComponent sends the message #description which finally creates the description container with all the collected descriptions. I could have my own implementation of #asComponent or have another object to do it, but I wanted to know if somebody already did it.
(btw, why #description and not #magritteDescription? it keeps my model objects from using the message #description for a business porpoise)

2) The description "descriptionCanton" of the tutorial, is another example of why I want to decouple descriptions from the model class. In the tutorial the cantons are hard coded in the method, but that is not possible in a "real" app. Cantons should be taken from another object, lets say the "Cantons" object. But if I keep the "descriptionCanton" in Address and use "Cantons" from there, I will be coupling Address with Cantons, which will prevent me from using Address in another context or with provinces or states instead of cantons. Does anybody has a suggestion for doing this?

3) To keep the objects that are created, the tutorial suggests to use a class variable, but that is an option that does not scale. For instance, what happens if I want to host the same app several times with different data? (we are planning to use GLASS) Using the tutorial classes, I would like to have an instance of MAPersonManager for one of our customers, another instance of MAPersonManager for other customer, and so on. Also, using a class variable keeps us from writing tests for that class because that variable is shared among all the objects (tests, the real app, etc). I think this is more a SeaSide question... 
Anyway, I would like to have something like this:
MAPersonManager for: self customer1  <-- this is one instance of person manager for one customer
MAPersonManager for: self customer2 <--- this is the other...
Is it possible? how?

3) I see that Magritte always needs an object to edit it. I mean, an instance of Address to edit an address, an instance of Person to edit a person, and so on. That means that the system could have invalid instances for some period of time. For example, a person without a last name is an invalid instance of Person, but to be able to edit a Person Magritte needs an instance of Person without a last name. Maybe some people will say "so what? what is the problem?". Well there are some problems with doing it this way, for example a programmer could write a program that reads people from an archive and forgets to check that the last name can not be empty. You could say that for writing that program the programmer should use Magritte's description also, but why? what is the meaning of label, priority, etc. in that case? But let's say the programmer uses Magritte's description to read from the file, what will prevent him to create a Person with out a last name from the workspace?
So, to avoid invalid instances we use a technique were valid instances are created from the beginning. For the Person example of the tutorial, I would have something like this:

Person class>>named: aFirstName and: aLastName ....

  self assertNotEmpty: aFirstName.
  self assertNotEmpty: aLastName.
  ....
  "Only if all the assertions are passed, the object is created"
  ^self new initilializeNamed: aFirstName and: aLastName ....

and if the object is not immutable, it will have a #syncronizeWith: message that takes a valid instance and changes its instance variables. For the person example:

Person>>syncronizeWith: aPerson

  firstName := aPerson firstName.
  lastName := aPerson lastName.
  .... "the same with all inst. var".

Doing so, the system ensure me that the person after being modified is valid because "aPerson" has to be valid to exist as an object.
There are many advantages of doing this:
a) There is no problem when an object is valid depending on the value of different instance variables because all the validations are done together before creating the object. (Dates are an example of this case, it is not enough to know its day number to see if it is valid, the month has to be known also)
b) Only valid instances exist in the image, no matter how I create them, from the UI, reading a file, using the workspace, etc. 
c) New programmers can not make mistakes using the current objects. If they create an object it has to be valid, if not, they will get a debugger.
d) Validations of the object are kept with the object, the validations are part of the object's definition and they are not spread in different places. (This is also different from Magritte, that suggests to define validations in the descriptions)

Of course we could agree or not that this is a good technique, but it proved to be good for me and the people I work with and I would like to continue using it.
Does anybody imagine how to do it with Magritte? or is it completely against its philosophy?

Well, these are the questions I have by now... sorry for the long mail.

Bye,
Hernan.




_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Questions about Magritte

Lukas Renggli
> 1) Has anybody defined the descriptions in other class but the model class?
> It seems to me that defining the descriptions as class methods in the model
> class creates a coupling between the model and the view that I would like to
> avoid. Part of that coupling is because of some view's "attributes" like
> label, priority, beSorted, readOnly, etc. It also couples the model with
> Magritte, which avoids me to use the model in an environment without
> Magritte.

Magritte is not the "View". Magritte is model as well, the meta-model.

If you would like to keep descriptions separate, that can be easily
done using extension methods. So one could imagine having the
descriptions in a separate package, other than the actual model.
Furthermore different other packages could modify these descriptions,
or add their own.

Foo class>>descriptionBar (in model package)
   ^ MAStringdescription new
         accessor: #bar;
         yourself

Foo class>>descrptionBarView: aDescription (adds the label in view package)
   ^ aDescription label: 'Bar'

Personally I keep the descriptions all in the model, unless there is a
good reason not to do so.

> I was looking around and it seems possible, but the method #asComponent
> sends the message #description which finally creates the description
> container with all the collected descriptions. I could have my own
> implementation of #asComponent or have another object to do it, but I wanted
> to know if somebody already did it.

You could override #description in your classes, or use
#asComponentOn: that can be used to use any description together with
any model to build a component.

> (btw, why #description and not #magritteDescription? it keeps my model
> objects from using the message #description for a business porpoise)

That concern comes up every couple of years. Probably it is because I
am not a native speaker and I never called one of my own business
properties #description. As you can see above, Magritte does not
depend on that name, if you do not like it you can use something else
with little additional code.

> 2) The description "descriptionCanton" of the tutorial, is another example
> of why I want to decouple descriptions from the model class. In the tutorial
> the cantons are hard coded in the method, but that is not possible in a
> "real" app. Cantons should be taken from another object, lets say the
> "Cantons" object. But if I keep the "descriptionCanton" in Address and use
> "Cantons" from there, I will be coupling Address with Cantons, which will
> prevent me from using Address in another context or with provinces or states
> instead of cantons. Does anybody has a suggestion for doing this?

See above and <http://www.lukas-renggli.ch/smalltalk/magritte/faq>.

> 3) To keep the objects that are created, the tutorial suggests to use a
> class variable, but that is an option that does not scale. For instance,
> what happens if I want to host the same app several times with different
> data? (we are planning to use GLASS) Using the tutorial classes, I would
> like to have an instance of MAPersonManager for one of our customers,
> another instance of MAPersonManager for other customer, and so on. Also,
> using a class variable keeps us from writing tests for that class because
> that variable is shared among all the objects (tests, the real app, etc). I
> think this is more a SeaSide question...

I would make the customers part of the model and store a
MACustomerManager in some "persistent root". Tests get their own
MACustomerManager instance.

> 3) I see that Magritte always needs an object to edit it. I mean, an
> instance of Address to edit an address, an instance of Person to edit a
> person, and so on.

No. Descriptions can always be used on any object, as long as the
object can handle them. MAMemento is such a power-object. It can
essentially handle any set of descriptions. It simply keeps a
dictionary from descriptions to their current values.

These mementos are used during edit operations. To Magritte a memento
object looks like the real object, but it can be edited and changed so
that it is temporarily in an invalid state without affecting the real
object and thus other concurrent users. Some memento subclasses can
even detect and merge conflicts. The real object is only changed when
all validation conditions are satisfied.

Keep the questions rolling.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Questions about Magritte

hernan.wilkinson
Hi Lukas!

On Tue, Apr 14, 2009 at 3:42 PM, Lukas Renggli <[hidden email]> wrote:
> 1) Has anybody defined the descriptions in other class but the model class?
> It seems to me that defining the descriptions as class methods in the model
> class creates a coupling between the model and the view that I would like to
> avoid. Part of that coupling is because of some view's "attributes" like
> label, priority, beSorted, readOnly, etc. It also couples the model with
> Magritte, which avoids me to use the model in an environment without
> Magritte.

Magritte is not the "View". Magritte is model as well, the meta-model.

I understand you point, but it is rare for me to see "label" and "priority" in the descriptions that are use only to create the view (at least that is what I saw so far...). That is what I meant by "coupling with the view".
 


If you would like to keep descriptions separate, that can be easily
done using extension methods. So one could imagine having the
descriptions in a separate package, other than the actual model.
Furthermore different other packages could modify these descriptions,
or add their own.

Foo class>>descriptionBar (in model package)
  ^ MAStringdescription new
        accessor: #bar;
        yourself

Foo class>>descrptionBarView: aDescription (adds the label in view package)
  ^ aDescription label: 'Bar'

Personally I keep the descriptions all in the model, unless there is a
good reason not to do so.

That's a good idea. I don't like extensions too much but it sounds reasonable for this case.
Anyway, I'm still thinking about using another object to have the descriptions... I'll let you know how it worked out
  

> 2) The description "descriptionCanton" of the tutorial, is another example
> of why I want to decouple descriptions from the model class. In the tutorial
> the cantons are hard coded in the method, but that is not possible in a
> "real" app. Cantons should be taken from another object, lets say the
> "Cantons" object. But if I keep the "descriptionCanton" in Address and use
> "Cantons" from there, I will be coupling Address with Cantons, which will
> prevent me from using Address in another context or with provinces or states
> instead of cantons. Does anybody has a suggestion for doing this?

See above and <http://www.lukas-renggli.ch/smalltalk/magritte/faq>.

But the block is still coupled with some implementation...
I was thinking about something more similar to a desktop app, where you create the view and then you set the objects you want to show. For example:

   addressView := AddressView new. 
   addressView cantons: self cantonsSubsystem contents.
   addressView open.
 


> 3) To keep the objects that are created, the tutorial suggests to use a
> class variable, but that is an option that does not scale. For instance,
> what happens if I want to host the same app several times with different
> data? (we are planning to use GLASS) Using the tutorial classes, I would
> like to have an instance of MAPersonManager for one of our customers,
> another instance of MAPersonManager for other customer, and so on. Also,
> using a class variable keeps us from writing tests for that class because
> that variable is shared among all the objects (tests, the real app, etc). I
> think this is more a SeaSide question...

I would make the customers part of the model and store a
MACustomerManager in some "persistent root". Tests get their own
MACustomerManager instance.

 I agree, but I don't see how to access the right customer manager from the seaside component...



> 3) I see that Magritte always needs an object to edit it. I mean, an
> instance of Address to edit an address, an instance of Person to edit a
> person, and so on.

No. Descriptions can always be used on any object, as long as the
object can handle them. MAMemento is such a power-object. It can
essentially handle any set of descriptions. It simply keeps a
dictionary from descriptions to their current values.

yes, I saw that, it is great!
 

These mementos are used during edit operations. To Magritte a memento
object looks like the real object, but it can be edited and changed so
that it is temporarily in an invalid state without affecting the real
object and thus other concurrent users. Some memento subclasses can
even detect and merge conflicts. The real object is only changed when
all validation conditions are satisfied.

yes, but if I want to validate the object creation and use the #syncronizeWith: idea I have to do something more I guess...  
We need also to keep the changes that are made to an object, so directly changing the object will not do it...


Keep the questions rolling.

Thanks for the answer! 

Bye,
Hernan 


Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki


_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki