Hi,
I am just started to learn and use Dolphin 4. If any1 can comment my small problem I will be grateful. I made following: subclass of ShellView where I override onPaintRequired: message with |canvas| canvas := aPaintEvent canvas. canvas pen: Pen black brush Brush grey, ellipse: (Rectangle origin: 0@0 extent 250@150); Above code is quite working no problem. So fahr so good. Now question - code "Pen black" is sending message black to object Pen. I have no idea why Pen is accepting message black and not for example message yellow. Pen class understands directly 10 methods ( like color, color: etc. ) but there is no "black" nor "yellow" message. I expect that in this case when class do not understands message its superclass will try to resolve the problem but I am unable to do it by myself. Please advice. |
Olek,
> I am just started to learn and use Dolphin 4. If any1 can comment my > small problem I will be grateful. I made following: Welcome, both to Smalltalk and this group. We're quite friendly here so we should be able to help.... > So fahr so good. Now question - code "Pen black" is sending message > black to object Pen. Yes. #black is being sent to the object Pen, but what _is_ the object Pen.in this case? If the code was ... x := Pen new. x black then you would be sending the message #black to an _Instance_ of Pen, an instantiated Pen object created for drawing. However, Pen black is sending the message #black to the _Class_ Pen (remember that in Smalltalk classes are Objects as well) and not an instance of Pen. > I have no idea why Pen is accepting message black > and not for example message yellow. > > Pen class understands directly 10 methods ( like color, color: etc. ) > but there is no "black" nor "yellow" message. Taking the above into account you have to look in the list of "class methods", methods implemented for the class itself and not instance of a class. In the ClassBrowser locate the Pen class and then click on the "Class" tab in the central view. The first method in the list should be #black. If you want to create a yellow pen then you will have to have something like the following (nb #black is a special System pen so we can't copy the code for that, use Pen>>blue as a template instead). yellowPen := Pen color: Color yellow You could use that inline so your full example would read (with corrected punctuation) |canvas| canvas := aPaintEvent canvas. canvas pen: (Pen color: Color yellow); brush Brush grey; ellipse: (Rectangle origin: 0@0 extent 250@150) An alternative would be to add a new _Class_ method to Pen (along the lines of #blue, #red etc) that answered a yellow Pen. Then your code would just use [..] canvas pe: Pen yellow; Any help? Ian |
Ian,
thank you so much for packed with information answer to my note. You made it so clear I really do not understand now why it was such a big problem for me. Shame on me. I am writing now program that should do something interesting on the chessboard. What worries me a lot is when I compaire my clumsy code with sexy one from the Dolphin I see one big difference. I tend to make very long methods ( like displaying whole chessboard using only one method ) I do not know if it is right thing to do in smalltalk, can you or anybody in this group just name objects they will make for the chessboard drawing? Any advice will help me. Olek |
Olek,
> I am writing now program that should do something interesting on the > chessboard. What worries me a lot is when I compaire my clumsy code > with sexy one from the Dolphin I see one big difference. I tend to > make very long methods ( like displaying whole chessboard using only > one method ) I do not know if it is right thing to do in smalltalk, > can you or anybody in this group just name objects they will make for > the chessboard drawing? Any advice will help me. OK. Bit of advice #1 is to try and get hold of a copy of "Smalltalk: Best practice patterns" by Kent Beck. There is a lot of useful stuff in there that can help with both the creation of Smalltalk code and the way to think about how you approach the writing of the code (patterns). I've attached a very simple package that contains 4 classes that implement the drawing of a draught board (called checkers in some foreign parts). I've kept it simple, there are a couple of things that I might not do in the same way for a "proper" application, but it might give some ideas. First, create the model. Always a good first step. In this case it will just be a class that represents the Draught board. It will have one instance variable, "board", which is a LookupTable containing one entry for each board position. The board axes are numbered 1 to 8 with 1@1 being at the top left. I've made it a subclass of Model simply to use it's behaviour of automatically evaluating #initialize when it is created. Model subclass: #DraughtBoard instanceVariableNames: 'board' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: '' Start with one method, #initialize, to set up the board. Before we do that though we have to set up the Draught class otherwise DraughtBoard>>initialize will give errors. The instance variable, "colour" will contain the colour for the draught. Object subclass: #Draught instanceVariableNames: 'colour' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: '' Now add the initialize method DraughtBoard>>initialize super initialize. board := LookupTable new. 1 to: 8 do: [:x | 1 to: 8 do: [:y | board at: x @ y put: nil]]. "Pieces" 1 to: 7 by: 2 do: [:x | board at: x @ 1 put: Draught white. board at: x + 1 @ 2 put: Draught white. board at: x @ 3 put: Draught white. board at: x + 1 @ 6 put: Draught black. board at: x @ 7 put: Draught black. board at: x + 1 @ 8 put: Draught black] This takes us back to your original post as you can see that Draught has two _class_ methods, #black and #white. We can define those now Draught class>>white ^super new setColour: Color black Draught class>>white ^super new setColour: Color white and add the _instance_ method that sets the variable for the new object Draught>>setColour: aColour colour := aColour Like all good models we can now try it without worring about any external responsibilities. Evaluate DraughtBoard new inspect in a workspace and you can look at the DraughtBoard and associated Draughts Ok. Leave the model for the moment and look at the Presenter/View (as we are creating a MVP triad). We need two more classes Presenter subclass: #DraughtBoardPresenter instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: '' View subclass: #DraughtBoardView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: '' Add one class method to DraughtBoardPresenter DraughtBoardPresenter class>>defaultModel ^DraughtBoard new This tells DraughtBoardPresenter that, unless it is told otherwise, it needs to create an new instance of DraughtBoard to use as it's model. The Presenter and View will both interact with this model, using it to get and set the board information. We also now need to execute a bit of code that tells the DraughtBoardPresenter what kind of View it needs. Copy the following into a workspace and evaluate it. DraughtBoardPresenter addView: DraughtBoardView asResource: 'Default view' Right, now if we evaluate DraughtBoardPresenter show we can see that the DraughtBoardPresenter now has acquired a model and a View of the required type. Drilling down into the View shows that it also has a Model. NB this is the _same_ instance of DraughtBoard as the Presenter. OK. The above just displays an empty View so let's try to fill it. Add the following to DraughtBoardView DraughtBoardView>>squareExtent ^40@40 This just tells the View that each square of the draught board is 40x40 pixels. Normally we would dynamically compute this as a proportion (1/8) of the views size, but it complicates things a bit too much for this simple demo. Now do the drawing DraughtBoardView>>onPaintRequired: aPaintEvent | canvas | canvas := aPaintEventCanvas. 1 to: 8 do: [:x | 1 to: 8 do: [:y | self model draw: x@y on: canvas within: ((x @ y - 1 * self squareExtent) extent: self squareExtent)]] This illustrates a guideline that is used quite often in Smalltalk "never do yourself what you can get someone else to do". In this case the View is just asking the DraughtBoard to draw each square on a canvas, within the rectangular area the view provides. The view doesn't know, or care, how the DraughtBoard does this, it just expects the board to do as it is told. NB For simplicity I've assumed that the view knows a draught board is 8x8, something else that might be a dangerous assumption in the real world. Aside - As a bit of practice is Smalltalk precedence try to work out what the last line does and how it does it , step by step. The above means that we now have to add a method to DraughtBoard DraughtBoard>>draw: aPoint on: aCanvas within: aRectangle "Draw the squares background" aCanvas fillRectangle: aRectangle brush: (Brush color: (self colourOfSquare: aPoint)). "Draw the draught, if needed" (self hasDraughtAt: aPoint) ifTrue: [ (self draughtAt: aPoint) drawOn: aCanvas within: aRectangle] This illustrates a couple of things. - We delegate the responsibility of drawing the draught to someone else, the draught itself ("never do yourself what you can get someone else to do") - We add extra methods (below) that do the little jobs like seeing if a specific square has a draught or not. We could do it inline but it makes thing easier if you create separate methods. This does seem like a pain at times but you will find that having methods that do one job, and _only_ one job, with an appropriate method name, make life easier in the long run. We need three methods for the above DraughtBoard>>draughtAt: aPoint ^board at: aPoint DraughtBoard>>hasDraughtAt: aPoint ^(self draughtAt: aPoint) notNil DraughtBoard>>colourOfSquare: aPoint ^(aPoint x odd & aPoint y odd) | (aPoint x even & aPoint y even) ifTrue: [Color red] ifFalse: [Color blue] One final method. A Draught is being asked to draw itself on a canvas so we need to tell it how. There's no one else to delegate it to, the buck stops here <g> Draught>>drawOn: aCanvas within: aRectangle aCanvas brush: (Brush color: colour); ellipse: (aRectangle insetBy: (aRectangle extent // 8)) And that's it. Evaluating the following should draw a nice Draught board with pieces DraughtBoardPresenter show That enough for now. I haven't gone into any details about how to enter all this using the Dolphin development environment, hopefully you have already worked that out for yourself. The attached package is, more or less, the same as the code above - typos excepted. Questions, from you or anybody else are welcomed as are pointers to errors or how it could be done differently [1] from other Dolphinites. Stage two, tomorrow if I can get round to it, will involve the picking up of draughts and moving them around. Ian [1] Excluding the use of Table Oriented Programming methods of course begin 666 draughts.pac M?"!P86-K86=E('P-"G!A8VMA9V4@.CT@4&%C:V%G92!N86UE.B G9')A=6=H M=',G+@T*<&%C:V%G92!P87A697)S:6]N.B P.PT*"6)A<VEC0V]M;65N=#H@ M)T1R875G:'1";V%R9%!R97-E;G1E<B!S:&]W)RX-"@T*<&%C:V%G92!B87-I M8U!A8VMA9V5697)S:6]N.B G)RX-"@T*(D%D9"!T:&4@<&%C:V%G92!S8W)I M<'1S(@T*#0HB061D('1H92!C;&%S<R!N86UE<RP@;&]O<V4@;65T:&]D(&YA M;65S+"!G;&]B86P@;F%M97,L(')E<V]U<F-E(&YA;65S(@T*<&%C:V%G92!C M;&%S<TYA;65S#0H)861D.B C1')A=6=H=#L-"@EA9&0Z("-$<F%U9VAT0F]A M<F0[#0H)861D.B C1')A=6=H=$)O87)D4')E<V5N=&5R.PT*"6%D9#H@(T1R M875G:'1";V%R9%9I97<[#0H)>6]U<G-E;&8N#0H-"G!A8VMA9V4@;65T:&]D M3F%M97,-"@EY;W5R<V5L9BX-"@T*<&%C:V%G92!G;&]B86Q.86UE<PT*"7EO M=7)S96QF+@T*#0IP86-K86=E(')E<V]U<F-E3F%M97,-"@EY;W5R<V5L9BX- M"@T*(D)I;F%R>2!';&]B86P@3F%M97,B#0IP86-K86=E(&)I;F%R>4=L;V)A M;$YA;65S.B H4V5T(&YE=PT*"7EO=7)S96QF*2X-"B)297-O=7)C92!.86UE M<R(-"G!A8VMA9V4@86QL4F5S;W5R8V5.86UE<SH@*%-E="!N97<-"@EA9&0Z M("-$<F%U9VAT0F]A<F10<F5S96YT97(@+3X@)T1E9F%U;'0@=FEE=R<[#0H) M>6]U<G-E;&8I+@T*#0HB061D('1H92!P<F5R97%U:7-I=&4@;F%M97,B#0IP M86-K86=E('-E=%!R97)E<75I<VET97,Z("A)9&5N=&ET>5-E="!N97<-"@EA M9&0Z("=$;VQP:&EN)SL-"@EY;W5R<V5L9BDN#0H-"G!A8VMA9V4A#0H-"B)# M;&%S<R!$969I;FET:6]N<R(A#0H-"D]B:F5C="!S=6)C;&%S<SH@(T1R875G M:'0-"@EI;G-T86YC959A<FEA8FQE3F%M97,Z("=C;VQO=7(G#0H)8VQA<W-6 M87)I86)L94YA;65S.B G)PT*"7!O;VQ$:6-T:6]N87)I97,Z("<G#0H)8VQA M<W-);G-T86YC959A<FEA8FQE3F%M97,Z("<G(0T*36]D96P@<W5B8VQA<W,Z M("-$<F%U9VAT0F]A<F0-"@EI;G-T86YC959A<FEA8FQE3F%M97,Z("=B;V%R M9"<-"@EC;&%S<U9A<FEA8FQE3F%M97,Z("<G#0H)<&]O;$1I8W1I;VYA<FEE M<SH@)R<-"@EC;&%S<TEN<W1A;F-E5F%R:6%B;&5.86UE<SH@)R<A#0I0<F5S M96YT97(@<W5B8VQA<W,Z("-$<F%U9VAT0F]A<F10<F5S96YT97(-"@EI;G-T M86YC959A<FEA8FQE3F%M97,Z("<G#0H)8VQA<W-687)I86)L94YA;65S.B G M)PT*"7!O;VQ$:6-T:6]N87)I97,Z("<G#0H)8VQA<W-);G-T86YC959A<FEA M8FQE3F%M97,Z("<G(0T*5FEE=R!S=6)C;&%S<SH@(T1R875G:'1";V%R9%9I M97<-"@EI;G-T86YC959A<FEA8FQE3F%M97,Z("<G#0H)8VQA<W-687)I86)L M94YA;65S.B G)PT*"7!O;VQ$:6-T:6]N87)I97,Z("<G#0H)8VQA<W-);G-T M86YC959A<FEA8FQE3F%M97,Z("<G(0T*(DQO;W-E($UE=&AO9',B(0T*#0HB M16YD(&]F('!A8VMA9V4@9&5F:6YI=&EO;B(A#0H-"@T*#0I$<F%U9VAT(&-O M;6UE;G0Z("<G(0T*#0I$<F%U9VAT(&=U:60Z("A'54E$(&9R;VU3=')I;F<Z M("=[-D9$0T4T.3 M-$%",2TT-44T+4$Y1#(M1$8Y-C5&04%%1C1%?2<I(0T* M#0HA1')A=6=H="!C871E9V]R:65S1F]R0VQA<W,A56YC;&%S<VEF:65D(2 A M#0HA1')A=6=H="!M971H;V1S1F]R(0T*#0ID<F%W3VXZ(&%#86YV87,@=VET M:&EN.B!A4F5C=&%N9VQE#0H)84-A;G9A<PT*"0EB<G5S:#H@*$)R=7-H(&-O M;&]R.B!C;VQO=7(I.PT*"0EE;&QI<'-E.B H85)E8W1A;F=L92!I;G-E=$)Y M.B H85)E8W1A;F=L92!E>'1E;G0@+R\@."DI#0H)"2$-"@T*<V5T0V]L;W5R M.B!A0V]L;W5R#0H)8V]L;W5R(#H](&%#;VQO=7(A("$-"B%$<F%U9VAT(&-A M=&5G;W)I97-&;W(Z("-D<F%W3VXZ=VET:&EN.B$J+75N8VQA<W-I9FEE9"%P M=6)L:6,A("$-"B%$<F%U9VAT(&-A=&5G;W)I97-&;W(Z("-S971#;VQO=7(Z M(2HM=6YC;&%S<VEF:65D(7!U8FQI8R$@(0T*#0HA1')A=6=H="!C;&%S<R!M M971H;V1S1F]R(0T*#0IB;&%C:PT*"5YS=7!E<B!N97<@<V5T0V]L;W5R.B!# M;VQO<B!B;&%C:R$-"@T*=VAI=&4-"@E><W5P97(@;F5W('-E=$-O;&]U<CH@ M0V]L;W(@=VAI=&4A("$-"B%$<F%U9VAT(&-L87-S(&-A=&5G;W)I97-&;W(Z M("-B;&%C:R$J+75N8VQA<W-I9FEE9"%P=6)L:6,A("$-"B%$<F%U9VAT(&-L M87-S(&-A=&5G;W)I97-&;W(Z("-W:&ET92$J+75N8VQA<W-I9FEE9"%P=6)L M:6,A("$-"@T*#0H-"D1R875G:'1";V%R9"!C;VUM96YT.B G)R$-"@T*1')A M=6=H=$)O87)D(&=U:60Z("A'54E$(&9R;VU3=')I;F<Z("=[1C=#0S(S-C@M M-D$S.2TT-4(Q+3E!-T8M,#=!044Q0S<T-#(S?2<I(0T*#0HA1')A=6=H=$)O M87)D(&-A=&5G;W)I97-&;W)#;&%S<R%5;F-L87-S:69I960A("$-"B%$<F%U M9VAT0F]A<F0@;65T:&]D<T9O<B$-"@T*8V]L;W5R3V93<75A<F4Z(&%0;VEN M= T*"5XH85!O:6YT('@@;V1D("8@85!O:6YT('D@;V1D*2!\("AA4&]I;G0@ M>"!E=F5N("8@85!O:6YT('D@979E;BD-"@D):694<G5E.B!;0V]L;W(@<F5D M70T*"0EI9D9A;'-E.B!;0V]L;W(@8FQU95TA#0H-"F1R875G:'1!=#H@85!O M:6YT#0H)7F)O87)D(&%T.B!A4&]I;G0A#0H-"F1R87<Z(&%0;VEN="!O;CH@ M84-A;G9A<R!W:71H:6XZ(&%296-T86YG;&4-"@DB1')A=R!T:&4@8F%C:V=R M;W5N9"(-"@EA0V%N=F%S( T*"0EF:6QL4F5C=&%N9VQE.B!A4F5C=&%N9VQE M#0H)"6)R=7-H.B H0G)U<V@@8V]L;W(Z("AS96QF(&-O;&]U<D]F4W%U87)E M.B!A4&]I;G0I*2X-"@T*"2)$<F%W('1H92!S<75A<F4B#0H)*'-E;&8@:&%S M1')A=6=H=$%T.B!A4&]I;G0I#0H)"6EF5')U93H@6PT*"0D)*'-E;&8@9')A M=6=H=$%T.B!A4&]I;G0I#0H)"0D)9')A=T]N.B!A0V%N=F%S#0H)"0D)=VET M:&EN.B!A4F5C=&%N9VQE72$-"@T*:&%S1')A=6=H=$%T.B!A4&]I;G0-"@E> M*'-E;&8@9')A=6=H=$%T.B!A4&]I;G0I(&YO=$YI;"$-"@T*:6YI=&EA;&EZ M90T*"7-U<&5R(&EN:71I86QI>F4N#0H-"@EB;V%R9" Z/2!,;V]K=7!486)L M92!N97<N#0H),2!T;SH@."!D;SH@6SIX('P-"@D),2!T;SH@."!D;SH@6SIY M('P-"@D)"6)O87)D(&%T.B!X($ @>2!P=70Z(&YI;%U=+@T*#0H)(E!I96-E M<R(-"@DQ('1O.B W(&)Y.B R(&1O.B!;.G@@? T*"0EB;V%R9"!A=#H@>"! M(#$@<'5T.B!$<F%U9VAT('=H:71E+@T*"0EB;V%R9"!A=#H@>" K(#$@0" R M('!U=#H@1')A=6=H="!W:&ET92X-"@D)8F]A<F0@870Z('@@0" S('!U=#H@ M1')A=6=H="!W:&ET92X-"@D)8F]A<F0@870Z('@@*R Q($ @-B!P=70Z($1R M875G:'0@8FQA8VLN#0H)"6)O87)D(&%T.B!X($ @-R!P=70Z($1R875G:'0@ M8FQA8VLN#0H)"6)O87)D(&%T.B!X("L@,2! (#@@<'5T.B!$<F%U9VAT(&)L M86-K70DA("$-"B%$<F%U9VAT0F]A<F0@8V%T96=O<FEE<T9O<CH@(V-O;&]U M<D]F4W%U87)E.B$J+75N8VQA<W-I9FEE9"%P=6)L:6,A("$-"B%$<F%U9VAT M0F]A<F0@8V%T96=O<FEE<T9O<CH@(V1R875G:'1!=#HA*BUU;F-L87-S:69I M960A<'5B;&EC(2 A#0HA1')A=6=H=$)O87)D(&-A=&5G;W)I97-&;W(Z("-D M<F%W.F]N.G=I=&AI;CHA*BUU;F-L87-S:69I960A<'5B;&EC(2 A#0HA1')A M=6=H=$)O87)D(&-A=&5G;W)I97-&;W(Z("-H87-$<F%U9VAT070Z(2HM=6YC M;&%S<VEF:65D(7!U8FQI8R$@(0T*(41R875G:'1";V%R9"!C871E9V]R:65S M1F]R.B C:6YI=&EA;&EZ92$J+75N8VQA<W-I9FEE9"%P=6)L:6,A("$-"@T* M#0H-"D1R875G:'1";V%R9%!R97-E;G1E<B!C;VUM96YT.B G1')A=6=H=$)O M87)D4')E<V5N=&5R(&%D9%9I97<Z($1R875G:'1";V%R9%9I97<@87-297-O M=7)C93H@)R=$969A=6QT('9I97<G)R<A#0H-"D1R875G:'1";V%R9%!R97-E M;G1E<B!G=6ED.B H1U5)1"!F<F]M4W1R:6YG.B G>T4R14)&1#!%+3%%0T,M M-#8U-2TY,S,V+3A%-44R,D4P0T)&0GTG*2$-"@T*(41R875G:'1";V%R9%!R M97-E;G1E<B!C871E9V]R:65S1F]R0VQA<W,A56YC;&%S<VEF:65D(2 A#0HA M1')A=6=H=$)O87)D4')E<V5N=&5R(&-L87-S(&UE=&AO9'-&;W(A#0H-"F1E M9F%U;'1-;V1E; T*"5Y$<F%U9VAT0F]A<F0@;F5W(2 A#0HA1')A=6=H=$)O M87)D4')E<V5N=&5R(&-L87-S(&-A=&5G;W)I97-&;W(Z("-D969A=6QT36]D M96PA*BUU;F-L87-S:69I960A<'5B;&EC(2 A#0H-"@T*#0I$<F%U9VAT0F]A M<F16:65W(&-O;6UE;G0Z("<G(0T*#0I$<F%U9VAT0F]A<F16:65W(&=U:60Z M("A'54E$(&9R;VU3=')I;F<Z("=[.$%#.#1&,3@M1C R,RTT-$5%+3DX-# M M,$8S.#@P-$4S.$-%?2<I(0T*#0HA1')A=6=H=$)O87)D5FEE=R!C871E9V]R M:65S1F]R0VQA<W,A56YC;&%S<VEF:65D(2 A#0HA1')A=6=H=$)O87)D5FEE M=R!M971H;V1S1F]R(0T*#0IO;E!A:6YT4F5Q=6ER960Z(&%086EN=$5V96YT M#0H)?"!C86YV87,@? T*"6-A;G9A<R Z/2!A4&%I;G1%=F5N="!C86YV87,N M#0H-"@DQ('1O.B X(&1O.B!;.G@@? T*"0DQ('1O.B X(&1O.B!;.GD@?" - M"@D)"7-E;&8@;6]D96P@#0H)"0D)9')A=SH@>"! ('D-"@D)"0EO;CH@8V%N M=F%S#0H)"0D)=VET:&EN.B H*'@@0"!Y("T@,2 J('-E;&8@<W%U87)E17AT M96YT*2!E>'1E;G0Z('-E;&8@<W%U87)E17AT96YT*5U=(0T*#0IS<75A<F5% M>'1E;G0-"@E>-#! -# A("$-"B%$<F%U9VAT0F]A<F16:65W(&-A=&5G;W)I M97-&;W(Z("-O;E!A:6YT4F5Q=6ER960Z(65V96YT(&AA;F1L:6YG(7!U8FQI M8R$@(0T*(41R875G:'1";V%R9%9I97<@8V%T96=O<FEE<T9O<CH@(W-Q=6%R M945X=&5N="$J+75N8VQA<W-I9FEE9"%P=6)L:6,A("$-"@T*( T*(D)I;F%R M>2!';&]B86QS(B$-"@T*(E)E<V]U<F-E<R(A#0H-"BA297-O=7)C94ED96YT M:69I97(@8VQA<W,Z($1R875G:'1";V%R9%!R97-E;G1E<B!N86UE.B G1&5F M875L="!V:65W)RD@87-S:6=N.B H3V)J96-T(&9R;VU":6YA<GE3=&]R94)Y M=&5S.@T**$)Y=&5!<G)A>2!F<F]M2&5X4W1R:6YG.B G,C$U,S4T-#(R,#,P M,C T-C R,$,P,# Q,# P,# P-38V.38U-S<U,C8U-S,V1C<U-S(V,S8U,# P M,# P,# P13 Q,C0P,#4S-30T,C4R-C4W,S9&-S4W,C8S-C4U,S4T-#(T,C<Y M-S0V-30Q-S(W,C8Q-SDT,38S-C,V-3<S-S,V1C<R-3 W,C9&-S@W.3 P,# P M,# P,S8P,# Y,# T,C<Y-S0V-30Q-S(W,C8Q-SDQ13 R,# P,#(Q-3,U-#0R M,C S,#(P-$4P.#!#,# P03 P,# P,#4S-30T,C4V-CDV-3<W-3 W,C9&-S@W M.3 P,# P,# P-$4P,C!$,# P,3 P,# P,#4S-30T,C0S-D,V,3<S-S,U,#<R M-D8W.#<Y,# P,# P,# S-C P,#8P,#4S-S0W,C8Y-D4V-S X,# P,# P-C0W M,C8Q-S4V-S8X-S0W,SDR,# P,# P,3 P,# P,# T-#<R-C$W-38W-C@W-#0R M-D8V,3<R-C0U-C8Y-C4W-S(V,# P-3 P-#$W,C<R-C$W.3!#,# P,# P,# P M,# P,# P,# P,# P,$,R,# P,# P,#(P,# P,# S-C P,$,P,#1#-C$W,C8W M-C4T.39%-S0V-38W-C4W,C T,# P,# P,# P,# P-#0P,3 P,# P,#8P,# P M,# P,# P,# P,# P,# P,# P,# P,# P,# P,#4P,# P,# P,# P,# P,# P M,# P,# P,# P,# P,# P,# P,# P,# V,#$P1C P-$0V-3<S-S,V,38W-C4U M,S8U-S$W-38U-D4V,S8U,# P,# P,# P13 R,3(P,#4S-30T,C0S-D8V0S9# M-C4V,S<T-CDV1C9%-3 W,C9&-S@W.3 P,# P,# P-T$P,# P,# P,# P,# P M,#DR,# P,# P,#<P,# P,# T-#9&-D,W,#8X-CDV13DR,# P,# P,3$P,# P M,# T1C<R-C0V-3<R-C4V-#0S-D8V0S9#-C4V,S<T-CDV1C9%0S(P,# P,# P M,3 P,# P,# V,#,P0C P-$0V-3<S-S,V,38W-C4U,S8U-D4V-# P,# P,# P M,$4P,3!%,# U,S4T-#(U,S<Y-D0V,C9&-D,U,#<R-D8W.#<Y,# P,# P,# Y M,C P,# P,#$P,# P,# P-C,W,C8U-C$W-#8U-#$W-#-!-C4W.#<T-C4V13<T M,T%#,C P,# P,# R,# P,# P,#8P,C U,# U,#9&-CDV13<T,# P,# P,# P M,3 P,# P,# Q,# P,# P1C(P,3 P,# P,# P,# P,$,Y,# P,# P0SDP,# P M,# V,# P,# P,# V,#$P1C P-3<T.31%-#0T1C4W-3 T0S0Q-#,T-31$-#4T M134T,# P,# P,# S-C P,#DP,#0R-SDW-#8U-#$W,C<R-C$W.3)#,# P,# P M,D,P,# P,# P,# P,# P,# P,# P,# P1D9&1D9&1D9&1D9&1D9&1D9&1D9& M1D9&1D9&1D9&1D8P,# P,# P,# P,# P,# P-C0P,# P,# V-# P,# P,#-! M,#$P,# P,# P,# P,# U,# Q,# P,$,R,# P,# P,# P,# P,#!&,C Q,# P M,# P,# P,# P0S$P,# P,#!#,3 P,# P,# P,# P,# P,3,P,# P,# T-C U M,#0P,# S,# P,# P-#DV,S9&-D4P,# P,# P,# P,# P,# P,3 P,# P,# P M13 R,3$P,#4S-30T,C4S-CDV138W-D,V-3<T-D8V134P-S(V1C<X-SDP,# P M,# P,#1%,#(P1# P,#$P,# P,# U,S4T-#(T,S9#-C$W,S<S-3 W,C9&-S@W M.3 P,# P,# P,S8P,# V,# U,S<T-S(V.39%-C<P-S P,# P,#0T-D8V0S<P M-C@V.39%,3(P,3 P,# Q.# P,# P,#0Y-D0V,38W-C4U,C8U-D,V,3<T-CDW M-C8U-#8V.39#-C4T0S9&-C,V,3<T-D8W,C!%,#$P13 P-3,U-#0R-3,W.39$ M-C(V1C9#-3 W,C9&-S@W.3 P,# P,# P,3(P,3 P,# P-S P,# P,#8S-S4W M,C<R-C4V13<T,3(P,3 P,# P.# P,# P,#4V-CDV-3<W,D4V.38S-D8P13 R M,48P,#4S-30T,C0U-S@W-#8U-S(V138Q-D,U,C8U-S,V1C<U-S(V,S8U-$,V M.38R-S(V,3<R-SDU,#<R-D8W.#<Y,# P,# P,# Q,C Q,# P,#$P,# P,# P M-C0V1C9#-S V.#8Y-D4V-#<R,S S,#,T,D4V-#9#-D,P,# P,# P,"<I*2$- #"@T* ` end |
In reply to this post by Olek
Olek <[hidden email]> wrote in message
news:[hidden email]... > I am writing now program that should do something interesting on the > chessboard. What worries me a lot is when I compaire my clumsy code > with sexy one from the Dolphin I see one big difference. I tend to > make very long methods ( like displaying whole chessboard using only > one method ) I do not know if it is right thing to do in smalltalk, > can you or anybody in this group just name objects they will make for > the chessboard drawing? Any advice will help me. There are many ways this could be done. I think you could even use the View Composer to make the board, that might simplify hit testing, etc... It depends how much control you want to have over the board. I don't think drawing a chess board would be too much for one method, if it was coded efficiently. However if you are talking about drawing the chess pieces in the same method then that is probably a bit too procedural. Each chess piece should probably be a different object (It will help your logic to have it distributed this way as well). Each piece object could draw themselves on the board. I just thought of an interesting way to draw a chessboard using intervals. I don't remember the parameters of a chess board off hand but this code can be easily changed (this will do an 11x11 board). I ran this in a workspace just to test. I am not sure if this is the best way to do this, it is just an idea. ====== shell := Shell show. shell view extent: 591@600. canvas := shell view canvas. horizStep := (shell view clientExtent // 11) x. vertStep := (shell view clientExtent // 11) y. horizInterval := Interval from: 1 to: 600 by: horizStep. vertInterval := Interval from: 1 to: 600 by: vertStep. mustFill := true. horizInterval do: [ :horizPos | mustFill := mustFill not. vertInterval do: [ :vertPos | mustFill := mustFill not. rect := (Rectangle origin: (horizPos @ vertPos) extent: (horizStep @ vertStep)). mustFill ifTrue: [canvas rectangle: rect] ifFalse: [canvas fillRectangle: rect brush: Brush black]]]. ======= Chris |
Chris,
I was quite happy with my piece of code but your one shocked me totally. I spent a lot of time experimenting till I started to understand what is going on. There is very clever step evaluation - clientExtent is a point in reality so you can for example divide it and still ask for x after such operation (I was always wondering what sense is in point arithmetical operations and now I have a perfect example), very nice really. I didn't now about Interval class at all. That's undocumented class in the Dolphin ( I understand Interval do not need any comment because is so basic, heh ). In reality I am still not good at collections but Inspecting objects works like a charm so I know now how nicely "do:" is working on Interval elements. To summarize thanks a lot for your note! P.S. I am quite confident now that method can be big if needed and it is OK in smalltalk. Olek |
Olek <[hidden email]> wrote in message
news:[hidden email]... ... > I didn't now about Interval class at all. That's undocumented class > in the Dolphin ( I understand Interval do not need any comment because > is so basic, heh ). In reality I am still not good at collections but ... I am glad that my comments were helpful. It is important to try to effectively use the base classes that Smalltalk has to offer. The rich base classes separate it from many other languages. If you happen to be bored one day I suggest just looking through all the classes, you may be amazed by what you find. I also suggest that you become familiar with Collections, they are one of the most powerful areas of Smalltalk. "do" is quite cool, but don't stop there, learn about collect, select, detect, reject, etc... Ian also had a very nice in-depth response to your previous message (you may not have seen it as it is only on 1 of the 3 news servers I use). If you do not see it I suggest that you read it on news.totallyobjects.com (it is there and it is a free server) or have Ian repost it. I think I like his approach better than my quick hack. > P.S. I am quite confident now that method can be big if needed and it > is OK in smalltalk. As far as method size I guess I am not as much of a zealot as some people. I think small methods are better than large methods in general. However I think things can also be over complicated if they are broken up too much. As with everything in life, it just depends on the context. I have been using Smalltalk for 7 years now, and I am still learning new things. I think that is what makes it so fun. ;) Chris |
Olek / Chris,
> Ian also had a very nice in-depth response to your previous message (you > may not have seen it as it is only on 1 of the 3 news servers I use). If > you do not see it I suggest that you read it on news.totallyobjects.com > (it is there and it is a free server) or have Ian repost it. I think that attaching the packaged code to the message caused it's disappearance from a number of servers (a growing number I would guess) that reject all incoming message with binary attachments. Understandable because of security restrictions and the 19GB (or something) daily load of binary newsgroup traffic floating around these days. If anyone didn't see it (it was one of those outpourings that seem to come over me occasionally, probably after I've drunk a cup of tea that was brewed too long) then mail me and I'll send a copy. > As far as method size I guess I am not as much of a zealot as some people. > I think small methods are better than large methods in general. However I > think things can also be over complicated if they are broken up too much. > As with everything in life, it just depends on the context. I try to keep method sizes down, a long method is a flag that some refactoring is probably needed, but I agree there are times when it can cause more trouble than it is worth. Another thing I try to do, but don't always succeed at, is to keep each method at the same abstraction level. Say that you want to open a file and parse the contents on a line by line basis. | fs | fs := FileStream read: 'aFile.txt'. [fs atEnd] whileFalse: [ | line | line := fs next. ( line beginsWith: 'Error') ifTrue: [Transcript print: line; cr]]. fs close OK, it's a silly example but you get the idea.... In a proper application I would probably split that into 3 levels 1) FileStream control parseFile | fs | fs := FileStream read: 'File.txt'. [self parseStream: fs] ensure: [fs close] 2) Stream contents control parseStream: aStream [aStream atEnd] whileFalse: [self parseLine: aStream next] 3) Parsing the text parseLine: aString (aString beginsWith: 'Error') ifTrue: [Transcript print: line; cr] To my mind splitting it up so that each method just does one things makes it more readable, as long as appropriate selectors are used of course. Some people think the opposite and find the constant swapping between methods a hindrance. Whatever.... > I have been using Smalltalk for 7 years now, and I am still learning new > things. I think that is what makes it so fun. ;) Yep, I couldn't agree more. I read those threads in comp.object and comp.lang.smalltalk where people moan about how much easier it is to understand/use C++ or whatever and shake my head in disbelief. If they only knew ... but some people just don't want to listen <g> Ian |
In reply to this post by Ian Bartholomew
Ian,
first of all I got your wonderful mail only because of Chris help. Chris pointed out that it may be I didnt get your mail because there was an attachment. I first didnt believe in that because on my polish news server are tons of groups with nacked girls and such kind of binary stuff. Why on earth I can not get small nice attachment in comp.lang.smalltalk.dolphin group? But Chris was right for some reason your e-mail didnt go through. Maybe we should change name from comp.lang.smalltalk.dolphin to something like: binaries.sex.nacked.dolphins. In such case we will avoid all attachments problems in the future :-) I used free news server news.totallyobjects.com and got everything no problem (like Chris suggested). I must say that I am deeply touched by all what was happening after my initial mail. I never expected something like that, rather was ready to be ignored in this news group. Usualy everybody is running after daily business and do not have much time to help others and even more write quite complicatted code. Now I have more smalltalk code to go through than I can handle in one go. ( Hmm, few days for sure or even more I think now ) This is something really wonderful. Now going back to your mail - >OK. Bit of advice #1 is to try and get hold of a copy of "Smalltalk: Best >practice patterns" by Kent Beck. There is a lot of useful stuff in there I ordered like you suggested Smalltalk Best Practice Patterns and also the The Art and Science of Smalltalk by Simon Lewis >I've attached a very simple package that contains 4 classes that implement >the drawing of a draught board (called checkers in some foreign parts). Wow, great 4 classes for one board, 4 times better then I did with my one class and one longish method. Lets check like it looks! Ahh class names are: Draught, DraughtBoard, DraughtBoardPresenter and DraughtBoardView Ouch! Thats for sure implementation of Model View Presenter something I do not undestand at all.( for me MVP sounds like horror heh). Maybe day come then I should try once again to attack this totally mystic topic ... I need time now, unfortunately I am very slow in reading smalltalk code. Will come back soon Once again Big Thank You! Olek |
In reply to this post by Ian Bartholomew
Ian,
I am still not ready to comment your Draughts code. Working hard to understand everything.It finished me yesterday and I am slowly recovering today. I need still some time. Maybe you can try in the mean time correct my basic understanding of MVP triad. I must say I still do not get the idea behind MVP so it is rather my basic non understanding of MVP. In general I imagine that MVP works like that: I construct my wonderful piece of smalltalk code called model ( for example its many megabytes long, super complicated code )thats do something really great like answers very important question (To be or not to be for example ). Answer object called answer, the result of all most complicated computations will hold just yes or no at the end. The only way to see this important answer is the use of development tool like inspector to inspect what is inside answer object, but if I like to distribute my program to non smalltalkers ( and make a lot of cash from it ) I need to present this answer in more readable and convinient for the enduser form. Because I am so smart i decided to use famous VP pair in addition to do all the dirty and complicated work of presenting the end result from my model. I wrote some additional megabytes of code and now my brand new VP part is nicely presenting the answer. VP code knows exactly where object answer resides ( in the model object of course ). It is possibile because model code was started by VP code. VP even knows when all computations that model makes are done and answer is ready ( because VP pair just waits till model finishes, VP just calls model and resumes operations after model is done ) In other words ( C++ words? ) it is like VP is calling model subroutine and continues execution after subroutine is finished. Everything looks fine, I can make big changes to the model code or add additional code to VP part and all the work can be done by two groups of programmers that do not know about each other. Everything will still work correctly as long as the interface between model and VP - the answer object will be the same. Going back to your Draughts program I see that you have done everything in one breathtaking go. First model and support class for the Draught next VP and then additional changes to the model and at the end to the Draught supporting class. Nice development circle from the start to the end and again to the start. But it looks to me like the DraughtBoard model is not totally separated from presenting functions of VP. Model has a drawing method. He still knows nothing about the view class but it will take active role in building the final board on the screen. Thats a surprise for me. Hmm, kind of tight cooperation. By analogy my "to be or not to be model" should then also actively support VP code, but I do not see how it can be done in my example. Why not move draw:on:within: method to VP and free model from any presentation responsibilities? P.S. What confuses me even more now is description of MVP in http://www.object-arts.com/Lib/EducationCentre4/htm/view.htm Where #trigger and #when:send:to: method is described as proper MVP method in Dolphin 4. That means MVP implementation in Dolphin 4 is different compared to Dolphin 2.x or 3.x or I am wrong? Olek |
Hi Olek,
Maybe you can try > in the mean time correct my basic understanding of MVP triad. I must > say I still do not get the idea > behind MVP so it is rather my basic non understanding of MVP. > > > P.S. > What confuses me even more now is description of MVP in > > http://www.object-arts.com/Lib/EducationCentre4/htm/view.htm > > Where #trigger and #when:send:to: method is described as proper MVP > method in Dolphin 4. > A couple of months ago we had a number of interesting threads around MPV, somebody tried to write a mini-library management application in MPV. Ian wrote a bit of excellent prosa that explained this #trigger issue very well. You can find this thread in the newsgroup archives on Ian's website (I think it was 3rd or 4th quarter 2000). Once you've cracked that, I would suggest to read the many articles about MPV on the Dolphin wiki. Good luck. Ted |
Ted,
>A couple of months ago we had a number of interesting threads around MPV, >somebody tried to write a mini-library management application in MPV. Ian >wrote a bit of excellent prosa that explained this #trigger issue very well. >You can find this thread in the newsgroup archives on Ian's website (I think >it was 3rd or 4th quarter 2000). Once you've cracked that, I would suggest >to read the many articles about MPV on the Dolphin wiki. > Thx a lot, I do not expected it is so deep topic, reading now "Twisting the triad" article by Andy and Blair. Very fascinating story Dolphin story. My micro problem is nothing compared to designers of Dolphin many months long struggle. Unfotunately they didnt have such nice group like that to ask for help <g>. Will check all archives from the end of 2000 Olek |
In reply to this post by Olek
Olek,
Sorry for the delay in replying. I wanted to make sure I had enough time to answer your points (hopefully) without rushing.. > I am still not ready to comment your Draughts code. Working hard to > understand everything.It finished me yesterday and I am slowly > recovering today. I need still some time. Maybe you can try > in the mean time correct my basic understanding of MVP triad. I must > say I still do not get the idea > behind MVP so it is rather my basic non understanding of MVP. It was probably a bit much for you're first taste of MVP but it seemed, at the time, that it might be useful to give an idea of how an application, or at least part of one, might be put together in Dolphin. In retrospect a slower approach might have been better. Other than MVP I was also trying to answer a bit more of your original question - showing how a Smalltalk app is put together from a number of associated classes and using small, focussed methods. > In general I imagine that MVP works like that: > > I construct my wonderful piece of smalltalk code called model ( for > example its many megabytes long, super complicated code )thats do > something really great like answers very important question (To be or > not to be for example ). Answer object called answer, the result of > all most complicated computations will hold just yes or no at the end. > The only way to see this important answer is the use of development > tool like inspector to inspect what is inside answer > object, but if I like to distribute my program to non smalltalkers ( > and make a lot of cash from it ) I need to present this answer in more > readable and convinient for the enduser form. Because I am so smart i > decided to use famous VP pair in addition to do all the dirty and > complicated work of presenting the end result from my model. > I wrote some additional megabytes of code and now my brand new VP part > is nicely presenting the answer. VP code knows exactly where object > answer resides ( in the model object of course ). It is possibile > because model code was started by VP code. VP even knows when all > computations that model makes are done and answer is ready ( because > VP pair just waits till model finishes, VP just calls model and > resumes operations after model is done ) In other words ( C++ words? ) > it is like VP is calling model subroutine and continues execution > after subroutine is finished. Hmmm. There is nothing obviously wrong with that paragraph but I feel it shows that you are missing a lot of the advantages of MVP. That's not a criticism, it's just that you have to use it for a bit, and get used _to_ it, to be able to appreciate how it helps. A couple of points that might bear stressing. An application doesn't just comprise of one, large MVP triad but a lot of smaller ones that work together. For example, an edit field in a date entry view is actually an MVP triad (aString (model), aTextEdit (View) and a TextPresenter) in it's own right. This triad is then linked into a "higher" composite MVP triad, a "DataEntry" for instance, which in turn is linked into an even higher level application (main Model, ShellView and Shell (Presenter)). There is a separation between a Model and the View/Presenter. A Model should work the same whether it has zero, one or multiple associated VP's. The last but one sentence should read - "VP just calls Model, Model informs any interested parties via a triggered event when it is done". The Model should not care if nobody is interested! > Everything looks fine, I can make big changes to the model code or add > additional code to VP part and all the work can be done by two groups > of programmers that do not know about each other. Everything will > still work correctly as long as the interface between model and VP - > the answer object will be the same. Yes. > Going back to your Draughts program I see that you have done > everything in one breathtaking go. First model and support class for > the Draught next VP and then additional changes to the model and at > the end to the Draught supporting class. Nice development circle from > the start to the end and again to the start. Not to mention one of the big advantages of Smalltalk, the ability to test every (well, almost every) step as you go. Something that ExtremeProgramming, with it's unit tests and refactoring, promotes. > But it looks to me like the DraughtBoard model is not totally > separated from presenting functions of VP. Model has a > drawing method. He still knows nothing about the view class but it > will take active role in building the final board > on the screen. Thats a surprise for me. Hmm, kind of tight > cooperation. By analogy my "to be or not to be model" > should then also actively support VP code, but I do not see how it can > be done in my example. Why not move draw:on:within: method to VP and > free model from any presentation responsibilities? OK. Good point. Say you have moved the drawing code from the Draught itself into the View. Then ... 1) The View has to know a bit more about the Draught. It has to know that the Draught implements methods that answer it's colour and whether it is a king or not. Draught itself has to implement the methods that expose these, supposedly internal, details. 2) The View will have to know how to draw any item that appears on the Board. Not too bad for Draughts, more difficult for Chess with the greater number of different pieces. 3) The View would have to be modified if you wanted to use the board for games other than Draughts. Reuse is something that plays (or should play) a big part in MVP 4) Say you wanted to print the board or draw it on a bitmap that could be sent over the Net. If the View implements the drawing you would have to implement a BoardPrinter and a BoardBitmap that also knew how to render Draughts. Putting the drawing code in the Draught means that you can just pass it an instance of a BitmapCanvas or a PrinterCanvas which the Draught can draw on using the same code as it used for the ViewCanvas. The bottom line is that because of the separation between Model and View there has to be some crossover and allowing the Model to know how to draw itself on a Canvas that is passed to it is better that giving the View knowledge of everything that it will have to display. > What confuses me even more now is description of MVP in > > http://www.object-arts.com/Lib/EducationCentre4/htm/view.htm > > Where #trigger and #when:send:to: method is described as proper MVP > method in Dolphin 4. > > That means MVP implementation in Dolphin 4 is different compared to > Dolphin 2.x or 3.x or I am wrong? I'm not quite sure how you read that into the page you mention.? However, Dolphin is still evolving and some things that worked one way in earlier versions now work in a slightly different, and invariably better, way in later versions. The basic premise - Models trigger events that interested parties can listen to - is the same in all versions. Hope that helps a bit Ian |
[hidden email] (Ian Bartholomew) wrote (abridged):
> An application doesn't just comprise of one, large MVP triad but a lot > of smaller ones that work together. For example, an edit field in > a date view is actually an MVP triad (aString (model), aTextEdit > (View) and a TextPresenter) in it's own right. This triad is > then linked into a "higher" composite MVP triad, a "DataEntry" > for instance, which in turn is linked into an even higher level > application (main Model, ShellView and Shell (Presenter)). And most of those objects are stock, off-the-shelf, reusable components. Olek wrote: Answer object called answer, the result of all most complicated computations will hold just yes or no at the end. MVP sounds like a lot of work just to display "Yes" or "No", but it's not so bad because most of the views, presenters, adaptors etc were already written for us by Object Arts. We just have to pick the ones we want and wire them together. Dave Harris, Nottingham, UK | "Weave a circle round him thrice, [hidden email] | And close your eyes with holy dread, | For he on honey dew hath fed http://www.bhresearch.co.uk/ | And drunk the milk of Paradise." |
In reply to this post by Ian Bartholomew
[hidden email] (Ian Bartholomew) wrote (abridged):
> The bottom line is that because of the separation between Model and > View there has to be some crossover and allowing the Model to know > how to draw itself on a Canvas that is passed to it is better > that giving the View knowledge of everything that it will have > to display. This is judgement call, though. Sometimes it is better to keep the model "pure". We can still get reusable rendering (and views) if we isolate the code that does that. Dave Harris, Nottingham, UK | "Weave a circle round him thrice, [hidden email] | And close your eyes with holy dread, | For he on honey dew hath fed http://www.bhresearch.co.uk/ | And drunk the milk of Paradise." |
In reply to this post by Ian Bartholomew
Ian,
>Sorry for the delay in replying. I wanted to make sure I had enough time to >answer your points (hopefully) without rushing.. I found your web page. Really impressive. >An application doesn't just comprise of one, large MVP triad but a lot of >smaller ones that work together. Oh, something clicked in my head. I still had wrong perception. My bad tendency to write everything in one method or do all UI with one big MVP instance .. In reality we have in smalltalk a big pool of smaller parts. Small parts are more useful because it is easy to reuse them and in the image there are hundreds of them. I can just make subclasses of model, presenter and view and cut development time significantly. > For example, an edit field in a date entry >view is actually an MVP triad (aString (model), aTextEdit (View) and a >TextPresenter) in it's own right. This triad is then linked into a "higher" >composite MVP triad, a "DataEntry" for instance, which in turn is linked >into an even higher level application (main Model, ShellView and Shell >(Presenter)). Yes I get it now. If for instance I will have an idea to write in circles I will just use aString-model and TextPresenter-presenter and will override part of aTextEdit-view and will have MVP triad for writing in circels that can be used as a part in another MVP. > Why not move draw:on:within: method to VP and >> free model from any presentation responsibilities? > >OK. Good point. > >Say you have moved the drawing code from the Draught itself into the View. >Then ... > >1) The View has to know a bit more about the Draught. It has to know that >the Draught implements methods that answer it's colour and whether it is a >king or not. Draught itself has to implement the methods that expose these, >supposedly internal, details. .... Hmm I think now it is much better when Draught knows how it looks ... If some day I will implement another game and will need Draught I will just reuse one class. Easy and clean solution. OK point taken. I was to strict and didnt understand fully the MVP method. Now I think it is working this way: M do not know about VP pair, but it is totaly valid if M will know that there probably is some VP. I mean by that that M can have some supporting VP methods and it is ok as long as they are very general and do not need any pointer to real VP pair. To follow MVP rules it will be enough if my model will know that there will be some VP pair so it can have some supporting VP code. From other side model will not care what kind of VP will be there. So in my programs it will be totally valid if I implement some presentation-view knowledge into model. Hmm maybe even foto of customer will be ok inside customer model and that will still be ok with MVP rules. > Models trigger events that interested >parties can listen to - is the same in all versions. > >Hope that helps a bit > Ian > Oh I am starting to understand what is going on. You was really of great help pointing out my blind spots. I will start now to play with MVP. Without your note, I would try to avoid MVP as long as it would be possibile. Hmm... and I think now it is not possibile in case of UI and Dolphin. Now I need to put theory into practice and write some code. Big Thank You! Olek |
In reply to this post by Dave Harris-3
Dave,
> >MVP sounds like a lot of work just to display "Yes" or "No", but it's not >so bad because most of the views, presenters, adaptors etc were already >written for us by Object Arts. We just have to pick the ones we want and >wire them together. I was of course exaggerating a little but in reality it was my call for help. I was very near the understanding but still blundering. Ian wonderfully pointed out what is wrong with my thinking and I instantly like by magic saw "the light". <g> Sentence " a lot of small pieces ..." was the key to Olek's mind Thank you for your answer, you are right of course Olek |
Free forum by Nabble | Edit this page |