From: Nat P. <nat...@b1...> - 2003-06-25 08:48:34
|
Hi Tim. No I didn't add the inheritance stuff in there. It's all done by delegation as we agreed: * Classes that implement CompositeCallable contain multiple callable objects: CallSelection (what used to be called CallBag) and CallSequence. * The CallCollectionBuilder class contains the "sugar" methods for building decorator chains and adding them to a CompositeCallable. It builds a CompositeCallable by *delegation*, not inheritance. A CallCollectionBuilder receives a reference to the CompositeCallable to build at construction time. This makes it *easier* to test the sugar methods in isolation from the proxy methods It also allows the sugar methods to be easily reused elsewhere -- to build sequences for example (see below). * A Mock class is a CallCollectionBuilder that knows how to proxy calls for an interface and delegates those calls to its CompositeCallable. This separation of concerns allows the sugar methods to be reused elsewhere (as described above/below). Other changes of note: The CallCollectionBuilder class can build sequences or selections. When it does so, it returns a new CallCollectionBuilder for the new sequence/selection that has been added to the mock. See the example for how this is used. I've removed the ConstraintMatcher interface because it was unnecessary: it's behaviour could just as well have been implemented as a decorator. That also removed the dreadful createConstraintMatcher method that used instanceof to branch on the type of an Object parameter. The BaseCallCollection class is an implementation detail that follows an inverse of the 'Generation Gap' pattern [see Pattern Hatching by Vlissides]. It contains "template" builder methods that are overloaded in the CallCollectionClass for all the different combinations of primitive type. These overloads are generated automatically by the Boxer tool. Yes, you get a lot of them. However, Java's primitive type nonsense makes it hard to avoid that. Those are my first reactions to your comments. More to follow when I've read your suggestions in detail and had time to ponder upon them. Regards, Nat. _______________________ Dr. Nathaniel Pryce B13media Ltd. http://www.b13media.com +44 (0)7712 526 661 ----- Original Message ----- From: "Tim Mackinnon" <tim...@po...> To: "Nat Pryce" <nat...@b1...> Cc: "Steve Freeman" <st...@m3...> Sent: Wednesday, June 25, 2003 1:43 AM Subject: Had a quick peak at the dynamic stuff you did > Nat - I had a very quick peak at the dynamic experiment you have done... > > hmmmm - admitedly its only a quick peak but my first impressions make me a > bit nervous. Of course I can understand this is your wip so not ready for > prime time. > > You simply had to get in all of that inheritance stuff that I stopped you > trying to put in the time before... inheritance is bad man - dont do it!!! > Its a bitch to test. I don't understand why you need it - I guess Mock > extends CallCollectionBuilder so you can do the autogen thing (but I think > you've missed an important idea here - and having 50 zillion code > completions appear in your editor is not a good thing). But then why also > then inherit from BaseCallCollectionBuilder??? > > I would also comment that when doing such experiments its probably better to > try and do the smallest changes possible so that people can easily compare > your idea and understand it - code formatting changes and renames make it > difficult to trace your intent - its probably better to defer them if you > can (just put a propsal to rename as a ToDo) > > > I think we would be better actually changing the way we express calls in the > first: > > mock.ExpectAndReturn(new Call("DoSomething", "p1", "p2"), "Return Value"); > > (we could call Signature - Call and do sytax sugar like: > > Call.eq("name", "eq p1", "eqP2" etc.) > Call.any("name") > > You could also have the stuff you mentioned ages ago like > > Call.name("name").eq(p1).eq(p2) > Call.name("name").eq(p1).any().any() > > > This has the advantage that it will map to .net nicely as the Call object > can autobox the parameters and we can still have the return value at the end > so it maps to the method name ExpectAndReturn. > > I then think that doing CallMany (Call is short for CallOnce) is easy - you > just create that form in the first place > > mock.ExpectAndReturn(new CallAtLeastOnce("DoSomethihg","p1").... > > This leaves the door open to easily changing the expectation policy on a > method by method basis. > > MatchAndReturn could be eliminated with this approach but I would opt to > leave it as it really seems to have made people understand the distinction > between expecting and just doing something else. It also makes it easy to > have the expects override the matches (without needing any fancy sorting). > > Anyway my 2p - and I will probably investigate this on the C# side. > > Tim > > --- > Outgoing mail is certified Virus Free. > Checked by AVG anti-virus system (http://www.grisoft.com). > Version: 6.0.490 / Virus Database: 289 - Release Date: 16/06/2003 > |