The other day I commented on how the IIS 7 URL Rewriter can be a neat way to transition your legacy ASP.NET Web Forms URL’s consisting of querystrings to a more RESTful, searchengine-friendly syntax. Actually, this can either be 1) a more transitory solution until you move to the new ASP.NET 4 Web Forms Routing or ASP.NET MVC, or 2) a permanent solution if you have a legacy application that you don’t plan to upgrade but want the cleaner routing.
After about 15 minutes of playing with the URL Rewriter I was pretty amazed at how quickly and easily one can clean up the inbound at outbound URL’s using it.
I created a page on my localhost that displayed products for a particular category for an e-commerce website and accepted the category as a querystring parameter as such:
http://localhost/products.aspx?category=bikinis
I wanted to map this URL for both inbound and outbound links to something cleaner, like:
http://localhost/category/bikinis
My thought was that this would be a fair amount of work, but in reality the IIS 7 URL Rewriter makes this a breeze.
Once you have installed the IIS 7 URL Rewriter you have the ability to add a rule, and in this specific case, a User-friendly URL, that is located under the header, Inbound and Outbound Rules.
Now this is where it gets slick. One enters the original URL and then chooses a more User-friendly URL from a dropdown and lets the URL Rewriter handle the rest. If, of course, you want more control you can pick another rule, but this worked perfectly for what I had in mind.
After you save the rule, your inbound routes will work correctly for any category as such:
http://localhost/category/tshirts
http://localhost/category/hats
Also, all links to this page within the website will automagically be converted from the old querystring URL to the more searchengine-friendly URL on your behalf, no work required. Very, very slick.
If you could benefit from more searchengine-friendly URL’s, the IIS 7 URL Rewriter is worth a look. I was pretty impressed with what I could do in just 15 minutes. After a bit more understanding, I’ll definitely be showing it off at a future Sarasota Web Developer Group Meeting.
David Hayden
Rob Eisenberg’s MIX 2010 talk, “Build Your Own MVVM Framework” was terrific. If you feel modestly comfortable with MVVM, run over and get the video and the code.
Rob may be best known for his Caliburn WPF/Silverlight Presentation Development Framework. That’s a hefty body of work and if the word “framework” sends an unpleasant shiver down your spine … relax yourself.
The “framework” demonstrated at MIX is roughly 500 lines (says Rob … I haven’t checked yet <grin/>). It’s based on Caliburn but stripped to essentials that Rob covered in an easy-to-follow, leisurely, one hour code-walk.
Highlights:
All that in one hour.
The “co-routine” trick alone is worth your time. You almost get F# “bang” syntax in C#.
It could get more complicated in your app … and you’d have Caliburn. But it might not … and you’d be living large with dead-simple, DRY code.
One of the best sessions ever.
If only we could teach Rob to emote. The guy is passionate on the subject but you might miss it behind that mono-tone voice of his. A Jim Carrey he is not. You want entertainment? Look elsewhere. You want substance … tune in.
He got a big ovation, by-the-by, so it ain’t just me who liked it.
Towards the end of a post I wrote just over a year ago I suggested that I wasn't really bothered about test names anymore because I could learn what I wanted from reading the test body.
Recently, however, I've come across several tests that I wrote previously which were testing the wrong thing and had such generic test names that it wasn't obvious that it was happening.
The tests in question were around code which partially clones an object but doesn't copy some fields for various reasons.
Instead of documenting these reasons I had written tests with names like this:
[Test] public void ShouldCloneFooCorrectly() { }
[Test] public void ShouldSetupFooCorrectly() { }
When we realised that the code wasn't working correctly, which didn't happen until QA testing, these test names were really useless because they didn't express the intent of what we were trying to test at all.
Damian and i spent some time writing more fine grained tests which described why the code was written the way it was.
We also changed the name of the test fixture to be more descriptive as well:
[TestFixture] public class WhenCloningFooTests { [Test] public void ShouldNotCloneIdBecauseWeWantANewOneAssignedInTheDatabase() { } [Test] public void ShouldNotCopyCompletedFlagBecauseWeWantTheFooCompletionJobToPickItUp() { }
It seems to me that these new tests names are more useful as specifications of the system behaviour although we didn't go as far as you can with some frameworks where you can create base classes and separate methods to describe the different parts of a test.
Despite that I think naming tests in this way can be quite useful so I'm going to try and write more of my tests like this.
Of course it's still possible to test the wrong thing even if you are using more expressive names but I think it will make it less likely.
I’ve long admired Josh Smith’s work. He’s one of the best explainers on the web and he – together with Karl Shifflett and Andrew Smith - gave us Mole, the superb WPF Visual Studio debugger visualizer.
I heard recently that he’d published an e-book on Model-View-ViewModel (MVVM). I met him for the first time at the Microsoft MVP Summit last week and he graciously handed me a printed copy. I devoured it on the plane home and spent the next day playing with the code and preparing this review.
It’s called “Advanced MVVM” and you can buy a printed copy for $20 or get it for $15 on the Kindle. The companion code is freely available at AdvancedMvvm.com .
$15 bucks for a 52 page “book”? It’s more of an extended essay to be honest … an essay with code. After spending some pleasurable hours with both book and code I thought “where do you get that kind of entertainment / self-reflection for $15?” I have a surfeit of 600 page sleepers lounging on my bookshelf at home; paid more then $50 for each and hardly cracked them. Should we pay by the pound? So I’m over it. I don’t mind paying for the hours Josh poured in and the fun I got out. Set your expectations appropriately and you’ll feel fine.
---- 19 March 2010 Note ---
Ok, it’s been a month or so since I wrote this. Life happens while you’re making plans. I intended to be among the first to comment on it. I’m late to that party (although I have deliberately NOT looked at what others may have said) so I’m not sure if it’s still timely. I also shared it with Josh last week to see if I had missed something and get his feedback, particularly in light of my critical remarks.
He encouraged me to publish it even at this late date. I hope he’ll repost here some of his responses to the points I raised.
----------------------------------
MVVM has spooked a lot of developers. There’s more than a whiff of astronaut architecture about it. There have to be at least 20 MVVM frameworks and no end of contentious arguments to confound and distress you. No wonder so many are put off.
In fact MVVM is fundamentally a simple idea. It starts with the realization that your application is an intractable mess in part because you dumped all of your UI logic into the code-behind … with the help of Microsoft tools. You discover the wisdom of pulling much of that logic out into a companion class (and some helpers) leaving the view class to concentrate on looking pretty and capturing user gestures. The view and its companion must talk; you can structure their conversation according to a variety of familiar patterns. Model-View-ViewModel is one such pattern.
The predominance of automated binding is the hallmark of MVVM. You bind a View’s textbox to a string-providing property of the ViewModel so that a user’s changes in the textbox flow to the property and so that programmatic changes to the ViewModel property flow back to the textbox. You bind View events (e.g., button click) to event handlers in the ViewModel enabling user gestures to be conveyed to the ViewModel.
You could write your own bindings by hand, pushing and pulling data and events with custom code. That’s a lot of work. The XAML-based client technologies (WPF and Silverlight) provide a binding framework that requires little to no custom coding. In most cases you can “connect the dots” declaratively and it just works.
Now the View concentrates on appearance and the ViewModel feeds the view. This separation is both clarifying and liberating. You can start looking at that ViewModel to figure out what it should do and how it should do it without also worrying about the visuals. The subsequent examination of ViewModel’s more limited responsibilities sets you on a more sustainable course. At least this has been my experience … and that of the hundreds (thousands?) of other developers who’ve adopted this pattern.
Now you’ll note that I said it “sets you on course”; I did not say it delivers you to the promised land. There are details to work out. If the View looks to the ViewModel for data, where does the ViewModel get that data? Are we talking about data values alone or the business rules that surround that data, rules about data validity, integrity, security, and persistence?
Many of us draw a circle around these concerns and call that circle “the Model”, the third element in the MVVM triad. Our guiding intuition is this: “the persistent data are definitely in the model and if the rules about data are true for this and every possible UI, the rules belong in the model as well.”
If the last name is required, it is required everywhere; that’s a model rule. If gold customers can select from several thank-you gifts, that sounds like UI logic to me … and belongs in the ViewModel. The specifics have to be worked out.
At this point the discussion risks slipping into theory and theater. We could run to the white board, scribble madly, and count angels on pins without writing a line of code. I love doing that.
Josh has taken another direction which is likely to be both more popular and more effective. He briefly presents his take on MVVM in clear, accessible prose … and then makes it tangible with an extended exploration of a meaty sample application. I’ve read plenty of pattern papers; I don’t remember any that were so thorough … and entertaining … in their examples.
For style and substance this is a remarkable achievement. I truly hope that Josh’s book is widely read because I think it has a better chance of helping WPF and Silverlight developers feel comfortable about MVVM than anything else I’ve seen.
I’m a little worried that some will fear the word “Advanced” in the title. The term “MVVM” is forbidding enough and many folks are still looking for the introduction. I think this book is the introduction they really need.
In what sense is it “advanced”? It’s far from the last word on the subject. It won’t settle any arguments (least of all mine). But it does rise above the introductory level in two important respects.
First, it considers the implications of multiple, cooperating MVVM instances. Most MVVM articles present a single MVVM-triad: a single View and its companion ViewModel and Model.
No application needs a single MVVM triad. If you have a one-screen application, don’t use MVVM; it’s overkill. MVVM is for multi-screen applications consisting of multiple MVVM triads which spring to life somehow and somehow interoperate.
Second, as I noted earlier, Josh doesn’t just talk about the pattern. Most of the pages describe the accompanying game, BubbleBurst, which is implemented in MVVM style. Instead of paeans to principles and their wondrous benefits, you see MVVM in action, warts and all.
BubbleBurst is “advanced” enough to both introduce MVVM and reveal important implementation challenges of multi-MVVM applications. Yet it’s simple enough to be easily understood in the pages of a book or in a few hours spent trolling the code. It’s also fun to play.
I’m about to begin my critical remarks. Before I do, I want to reemphasize my enthusiasm for what Josh has accomplished. This book is a wonderful place to begin your MVVM journey and I found it to be an enjoyable and insightful read. So, hell-yes, I’m recommending it.
On the other hand, it would be a shame if developers stopped their education here. Important elements of the story are missing and many recommendations are seriously misguided in my view. Readers should take Josh seriously but, once they are comfortable with the pattern, they should become aware of starkly contrasting perspectives as well.
Four vital topics are neither covered nor illustrated in the code:
Josh asks “What is the point of having ViewModels?” First among his reasons: “the ability to easily write unit and integration tests for the functionality of the user interface without having to get into the messy world of writing tests for live UIs.”
That’s the last we hear of testing. There is not a single test in the code base. If testing is as important as he says, I’d expect a thorough treatment starting with building a test regimen and showing, by example, how to write good tests. Instead, we get lip service.
I don’t think testability is the only value of MVVM. I couldn’t recommend it for this reason alone. MVVM is a significant architectural investment that introduces complexity. I wouldn’t incur that complexity cost merely to make my UI testable. I’d look for a less onerous route. Fortunately, I think it has other benefits such as clean separation of concerns, improved readability, and easier debugging (try break-pointing XAML!).
But testability is both a motivation for and a by-product of MVVM style and it should have been covered thoroughly in an “advanced” treatise on MVVM.
Moreover, the design would have benefitted greatly from attempts to test it. Many lines of view code-behind are both untestable and harder to follow than they should be. I see early signs of the spaghetti code that afflicts more complex and mature applications … a drum I’ll beat furiously later in this review.
At almost 300 lines, the BubbleMatrixViewModel begs to be tested both for quality and to reveal the expectations latent in its 20+ public and internal members.
The pattern is called Model-View-ViewModel. Josh’s Model is nowhere to be found. Model and ViewModel are combined and it’s not clear to me how one would disambiguate them.
The absence of Model isn’t blatantly obvious in a simple game like BubbleBurst. The game doesn’t to retrieve or save objects to a persistent store. We aren’t expecting much in the way of business model logic either; there’s nothing of interest to validate or secure. So the lack of a model is not a deep fault of this particular application. Indeed, it’s a convenient way to concentrate our attention on the central issues for most students of MVVM:
Nonetheless, we can’t pretend to provide a comprehensive guide to MVVP without talking about the Model and how it interacts with ViewModel and (to a lesser extent) View. A business application will demand a clear delineation of responsibilities and equally clear communication paths.
I’m not letting BubbleBurst off the hook either. I felt on several occasions that some ViewModels were heavier and more complicated than they should be because an inchoate game model was not independently defined.
I appreciate that Dependency Injection frightens many developers. You can discover MVVM without learning about Dependency Injection. Josh can kind of get away without it as long as he doesn’t test his ViewModels and doesn’t have to think about the services required to manage a persistent model.
But I feel you can’t call this “Advanced MVVM” … or even “Intermediate MVVM” … without introducing DI at some point. In Josh’s application, every View and every ViewModel class is known to and instantiated by some other View or ViewModel class. That won’t fly in real-world applications which have Views and ViewModels that are ignorant of each other.
The constructor of the BubbleMatrixViewModel instantiates three concrete bubble components: BubblesTaskManager, BubbleFactory, and BubbleGroup (twice) before making heavy use of them. That’s a lot of dependencies that would make this ViewModel brittle and especially difficult to test.
Taking hard dependencies means Josh can freely assume that ViewModels will always have parameterless constructors and can always be instantiated in XAML, as he often does here. Someone new to MVVM might think this is the norm. It is not.
Josh himself alludes to DI as one of the avenues opened by the MVVM pattern: “[MVVM] means that you can use frameworks like MEF to dynamically compose your ViewModels, to easily support plug-in architectures …”. That’s the last we hear of MEF or dynamic VM composition.
Again, I think we can ignore DI in an introduction to MVVM; we cannot ignore it in an advanced lesson on MVVM.
All of Josh’s MVVM triads are statically determined. Their relationships to each other are fixed and well known.
I was surprised to see a ViewModel for one view hold a reference to a ViewModel of a subordinate view. That’s not how I do it; my general rule is that MVVM triads do not hold references to each other. I concede that the rule makes it difficult to organize cross-triad communication. Josh’s approach is simple and elegant … when available.
In real-world business applications, the MVVM triads often can’t know about each other. They are often defined in separate modules without mutual references. Views appear and disappear dynamically. Direct communication is frequently impossible.
That’s why so many so-called MVVM frameworks include some kind of messaging or Event Aggregation infrastructure. You don’t need them to understand MVVM triads in isolation. But you never see an application with a single MVVM triad and you rarely find an MVVM application with statically determined, session-permanent views. No “advanced” treatment of MVVM can neglect Event Aggregation.
Here’s an incendiary topic Josh leaves untouched.
I see two ways to ask this question:
The answer to both questions need not be the same. For example, you could decide to design the ViewModel first and let the View instantiate that VM at runtime. This is plausibly the approach advocated in BubbleBurst although Josh never talks about it.
Again, it’s important that readers new to MVVM learn that Josh’s way is not the only way.
In my experience there is a “dialog” between View and ViewModel design. The VM exists to serve a view even as it strives for independence from any particular concrete view. A VM is useless if there is no view that will work with it; clearly the VM developer must heed the imprecations of the View developer.
On the other hand, in business applications the application’s imperatives – what the view must do to satisfy business requirements – are the province of the programmer and are best articulated through the capabilities of the ViewModel.
Therein lies the necessary tension between View and ViewModel design. As a developer my allegiance is with the ViewModel (“the application should do something worthwhile”) but it would be silly to defend that allegiance at the expense of the View (“a good UX is essential to making an application easy to learn and to use”).
I’d have liked to see this tension at least acknowledged and perhaps explored.
Runtime construction is a question apart from the matter of who drives the design. WPF and Silverlight tooling push you toward “View First” construction in which the View instantiates the ViewModel. You’ll often see the View’s DataContext set by a ViewModel instantiated in the XAML as shown here:
<UserControl.DataContext> <viewModel:BubbleBurstViewModel /> </UserControl.DataContext>
Contrast this with the ViewModel first, code-based approach (not seen in BubbleBurst) in which the ViewModel is assigned to the View’s DataContext as follows:
view.DataContext = viewModel;
The View First approach assumes that the ViewModel can be created via a default, parameterless constructor. That’s fine for BubbleBurst but wholly unrealistic in business applications whose ViewModels have dependencies (e.g., on the domain model).
Neither WPF nor Silverlight XAML support the dependency injection mechanisms that many of us prefer. I wish Josh had talked about this and perhaps discussed the interesting attempts to use MEF dependency injection (via properties rather than constructor arguments)
I’m not trying to settle these questions. I am saying these questions could have been called out in an “advanced” book on MVVM patterns.
Do we allow or prohibit code-behind? That’s a fist-fight topic. Josh looks for a Goldilocks solution, suggesting the amount of code-behind is just right if confined to “logic scoped to the view”.
Such guidance is far too loose in my opinion. It’s not effective guidance at all.
We choose presentation separation patterns in part because we want to minimize testing of the view. We should test any custom logic we write – no matter how it is scoped. The poverty of our testing tools means that, in practice, we will not test the code in the view. Therefore, any code in the code-behind is suspect.
I am open to some code in the code-behind; the “InitializeComponent” method is inescapable. I’ll accept a minimum of “switch board” code in the code behind; direct wiring to a ViewModel member is ok in small doses.
I draw the line at decision logic. I smell a rat when I see a conditional statement of any kind. That’s where bugs breed. Conditional logic is code we should be testing.
I much prefer this rule: “No conditional logic in the code-behind”.
That’s unambiguous. We don’t have to wonder what “scope of the view” means. If there’s an “if” or a “switch” statement, something is wrong. You can detect a violation with automation or visual inspection. It’s a rule that’s easy to follow and pretty easy to abide by … when you know how.
What happens when you don’t follow this rule? You’re lured into the kind of dodgy code that … well we see in the innocent seeming BubbleMatrixView.xaml.cs.
In fact, far from being “best practices”, I’d say that the View code in BubbleBurst represents some of the worst practices.
Look at the HandleMatrixDimensionsAvailable method. This event handler is wired to a UI element in the BubbleBurstView. Unfortunately, the UI element happens to be in a different view, the BubbleMatrixView! One view’s code-behind is wired to members of another view; that’s the road to perdition. That would never pass my review.
I wanted to clean it up immediately. I tried to find the intention behind this practice. Usually I look to the name of a method to discover its purpose. Unfortunately the handler is named for the moment when it is called (“Matrix dimensions available”) rather than for what it does. That’s conventional naming for event handlers but not terribly informative. Unless a handler is brain-dead-simple, I have it delegate immediately to methods with meaningful names. The handler tells me when something happens; the inner method tells me what will be done.
Had Josh adopted my suggestion, he’d have realized that his handler has multiple responsibilities:
That’s too much work for code-behind in my book.
When we strive to apply the “no conditional logic in the code-behind” rule, we discover other design problems.
It appears that Undo logic is distributed between two ViewModels. One of them, the BubbleBurstViewModel, determines if undo is possible while the second, BubbleMatrixViewModel performs the undo. Probe further and we find that even the BubbleBurstViewModel test for undo-ability is delegated back to the BubbleMatrixViewModel. The ping-ponging among Views and ViewModels is confusing; it doesn’t smell right.
All the signs suggest the real action is in BubbleMatrixView and its ViewModel.
BubbleMatrixView.xaml is short and sweet.The code-behind in BubbleMatrixView.xaml.cs is another story. Five Region tags sound the alarm. You shouldn’t need region tags in code-behind. Here they barely disguise the complexity of 145 lines of code-behind. That can’t be right.
I was able to refactor the 53 lines dedicated to animating bubble tasks. Most of them went to a BubblesTaskPresenter class, a component Jeremy Miller calls the “MicroController”.
Every MVVM developer should become familiar with the “MicroController” approach.
A “MicroController” performs a narrow UI task on behalf of a view. We usually write one to encapsulate UI logic that is reused across multiple views. That’s not the case here; the application is too small.
We also write MicroControllers to encapsulate UI-specific functionality in a UI-agnostic wrapper. They make it easy for non-UI components, such as ViewModels, to invoke the UI-specific behavior we find in Views. That’s what we need here.
I noticed that the ViewModel holds a TaskManager which raises a PendingTasksAvailable event when there are bubble display tasks. This sets off a sequence of calls between View and ViewModel which collectively “process tasks” queued up by the ViewModel.
Josh’s original code forwarded the event to the View’s code-behind. That code-behind then extracted the VM’s TaskManager and called into it. 53 lines of code-behind are dedicated to this entire process.
After my revision, the view merely provides the ViewModel with a configured MicroController, here called a “BubblesTaskPresenter”:
_bubbleMatrix.BubblesTaskPresenter = new BubblesTaskPresenter(_bubbleCanvas);
This is what switchboard code should look like. I’d like to get rid of the instantiation but at least there is a bare minimum of logic and no conditionals.
The ViewModel receives the concrete presenter in the guise of a UI-agnostic interface, IBubblesTaskPresenter and wires itself to the presenter’s events.
public IBubblesTaskPresenter BubblesTaskPresenter { get { return _bubblesTaskPresenter;} set { _bubblesTaskPresenter = value; _bubblesTaskPresenter.Completed += delegate { ProcessTasks(); }; TaskManager.PendingTasksAvailable += delegate { ProcessTasks(); }; } }
private void ProcessTasks() { var task = TaskManager.GetPendingTask(); BubblesTaskPresenter.PresentTask(task); }
IBubblesTaskPresenter uses simple .NET types and looks like this:
/// <summary> /// Interface for a presenter of <see cref="BubblesTask"/> /// </summary> public interface IBubblesTaskPresenter { void PresentTask(BubblesTask task); event EventHandler Completed; }
Where did the 53 lines of code-behind go? Into the BubblesTaskPresenter.
What has been gained? Did I just hide the pea under another untestable cup called a “presenter”? Is this merely an academic exercise?
I don’t think so. True, the presenter is dependent upon WPF and upon BubbleCanvas in particular. But it could be tested with a faked canvas and a faked factory. Testing aside, it’s small and focused; it’s easy to see what it does and how it works. It won’t get lost amidst the other motions of the BubbleMatrixView. We might someday use it in another view that presented BubblesTasks.
The BubbleMatrixViewModel has grown a few lines but remains readable and testable; its imported IBubblesTaskPresenter is easy to fake.
The ViewModel no longer exposes the TaskManager. That’s a good thing because the TaskManager is pretty complex piece of machinery with a rich API. We don’t want the View or BubblesTaskPresenter to know about it.
And the View is 53 lines lighter, reducing the anxiety we might justifiably feel if we handed it over to a non-programming designer for styling.
Homework Assignment: if you’re playing along and are looking toward your own application design, you might want to linger over the BubblesTaskPresenter. It is specific to bubbles right now … which is appropriate in the absence of forces that would drive us to generalization.
But you can encapsulate storyboard animations in much this way to both determine state changes within the ViewModel and externalize the animations in “View-space” where they belong. Josh is spot-on when he insists on this separation. The MicroController “presenter” approach is one way to achieve that separation without polluting the code-behind.
Aside: my first presenter was more abstract and general purpose. My generalization was premature. Generalization made the code more complex than it needed to be in this application. I un-factored it to the current version that knows about BubbleCanvas and BubblesTaskStoryboardFactory.
After clearing out the 53 lines, I was able to focus on what’s left.
I was deeply troubled by the properties of BubbleMatrixView that are exposed to and consumed by the BubbleBurstView code-behind. That can’t be right. Views shouldn’t need custom properties.
If you have to expose a custom view member, you should do so through a view interface. We don’t want any code – View or ViewModel – depending upon a concrete view class. That’s asking for trouble and flies in the face of the testability which justifies MVVM.
It’s also completely unnecessary in this application. As noted earlier the event loop from inner BubbleMatrixView to outer BubbleBurstView leads back around to BubbleMatrixView’s ViewModel. We can cut all that nonsense out and simply update the BubbleMatrixViewModel directly in the code-behind … without any conditional logic.
I refactored as follows:
The BubbleMatrixView code-behind is now a trim 30 lines with no conditionals, down from 145 (80% reduction). Of the 30, exactly 5 of them do work.
My cleanup involved eliminating several null checks. They never did anything useful. First, the variables could not be null in practice. Second, even if they were (e.g., someone broke the xaml), the application would not have functioned anyway. I don’t think a blank screen is superior to an exception. The null checks were about as helpful as empty catch blocks.
BubbleBurstView’s code-behind had one remaining “if” and some other code that I felt didn’t belong there.
Key monitoring logic contained an “if” statement. At first it seemed like key monitoring was a candidate for another MicroController. But there is only one key to handle, the key for Undo. That wasn’t worth the overhead of another MicroController component. Instead I decided to enrich the BubbleBurstViewModel with an Undo method whose signature is:
public bool TryUndo(bool shouldTry) // returns True if undid
The code-behind calculates whether the key presses amount to an undo request. The call is:
e.Handled |= _bubbleBurst.TryUndo(isUndoKey);
I don’t like the isUndoKey calculation but I’ll leave it for another day.
My final bug-a-boo is the LoadBubbleViewResources method which instantiates a ResourceDictionary and plugs it into the application-level resources.
I expected this to be loaded by the App.xaml itself but I suspect Josh wants to simulate the notion that independent assemblies have their own resources. While the “Bubble.View” assembly is not independent – the App.xaml has access to it through its host assembly’s references –, I’ll play along.
In any case, the view’s code-behind shouldn’t know the details of ResourceDictionary construction and App.Resources update. Time for a MicroController: “BubbleViewResourceLoader” which we can invoke from within the code-behind’s constructor for now. It still stinks but it stinks less.
The code-behind now stands at 41 lines, down from the original 86; only 9 of them do work.
I’m a restless complainer. I’ve got a few more bones to pick having nothing to do with MVVM.
Page numbers! You may have noticed that my citations lacked page numbers. That’s because there aren’t any in the printed document I’m reading.
The abundance of Region tags annoys me. Hey, I use them too, especially in pedagogical code where I want to unveil new ideas didactically in the course of a presentation.
I appreciate that they seem to organize the code into nice buckets: “constructors”, “methods”, “fields”. But lately I’ve come to believe that they’re more of a code smell.
If the class is short – as it should be – they interfere with my ability to read and grasp the class at a glance. If the class is long, they suggest that my class implements too many distinct concerns and I’m struggling – vainly – to keep them organized. These concerns would be better delegated to supporting classes. I suspect that automated testing would make this defect more obvious.
I’m not thrilled with the data triggers. Data triggers are not available to Silverlight programmers probably for good reason. The Visual State Manager is the preferred choice for both WPF and Silverlight.
A particularly egregious data trigger can be found in BubbleBurstView.xaml where the GameOverView is collapsed when the BubbleBurstViewModel’s GameOverViewModel is null. Could there be a more obscure way to signal that a modal dialog should be hidden? I suspect a bound IsGameOver property would be both simpler and more obvious.
Josh’s original source is at AdvancedMvvm.com . I’ve temporarily posted my refactored version on my site. I’m not promising it will stay there- this is Josh’s code and I’ll do whatever he wants me to do with it (including burn it) – but it’s there now and I’ll let you know if I move it.
I have high hopes for the conversation Josh has started with this book.
I see it as one place to begin your study of MVVM rather than as the definitive work on the subject. Some of the practices I find dubious and there are serious omissions.
But I gave it this much attention because it deserves it. It’s a fine piece of writing, a carefully considered example, and a push in the right direction. Josh speaks to a broad audience with an authentic voice they understand and respect. He has my respect as well.
It’s well worth the $15 bucks on the Kindle.
Enjoy!
p.s.: Cross-posted to my other blog, "Never In Doubt"
At the start of the year, I finished a 5 part series on ASP.NET performance - focusing on largely generic ways to improve website performance rather than specific ASP.NET performance tricks. The series focused on a number of topics, including merging and shrinking files, using modules to remove unecessary headers and setting caching headers, enabling cache busting and automatically generating cache busted referneces in css, as well as an introduction to nginx.
Yesterday I managed to put a number of those things together into a framework which I hope will make it easier for developer to leverage these best practices. The project is called Metsys.WebOp, and you can download it from github. It comes with a sample application, which not only shows how to use the framework, but also has all the documentation you'll hopefully need.
The first part of the framework is a console application which is meant to be run as part of your build process. This is driven by a text file which supports 4 commands - merging files together, shrinking them, generating cache busting hashes and pre-zipping files. Here's what the sample app's command file looks like:
#combine JS files combine: js\all.js: js\jquery.js, js\jquery.rollover.js, js\web.js #combine css files combine: css\merged.css: css\reset.css, css\main.css #shrink the generated files shrink: js\all.js, css\merged.css #generate cache-busting resource hashes busting: hashes.dat #pre-zip our files zip: js\all.js, css\merged.css
The next part is meant to be used from within a MVC application (it wouldn't take too much effort for someone to make it work with WebForms) - first by allowing you to configure the runtime component, and then by providing extension methods to HtmlHelper. Essentially this gives you 4 methods, Html.IncludeJs, Html.IncludeCss, Html.Image and Html.ImageOver. You can also toggle debug mode, which'll make all of this transparent during development (nothing worse than dealing with merged and shrank files in development).
Html.IncludeJs
Html.IncludeCss
Html.Image
Html.ImageOver
The last part are a couple HttpModule which make everthing possible. The Zip module will returned the pre-zipped files (generated by the build process) should the browser accept zip files. The WebOp module will remove unecessary headers and add caching headers to js, css and images - only really practical if you are also using the cache busting featuers.
You can download the project from http://github.com/kseg/Metsys.WebOp.
You might also be interested in checking out the mscd project, which does a lot of the same stuff, but is probably more mature.
We’ve covered a bit of ground in this series on the Reactive Extensions for JavaScript, covering the basics, jQuery integration, blocking to asynchronous and further composition. One way I’ve found to really get your hands dirty using this library is to take examples from other libraries and translate them into using our library of choice. In this case, I’m taking examples written in the Flapjax language, and translating them into the Reactive Extensions for JavaScript and jQuery.
Before we get started, let’s get caught up to where we are today:
Some of the comments made during my initial introduction to the Reactive Extensions for JavaScript mentioned the Flapjax language and whether I had heard of it. I had indeed, having translated some of the samples from the language to the Reactive Extensions for JavaScript with some assistance with jQuery. Today, we’ll step through a simple drag and drop scenario.
For those unfamiliar with Flapjax, it’s a programming language built on top of JavaScript which deals with event-driven reactive design, much like RxJS. By reading the APIs, you can very much see a Haskell influence in not only the design, but the naming and even down to the notation they use to describe the functions. Not to mention of course that the actual compiler for Flapjax is written in Haskell. Interestingly enough, Erik Meijer hosted an Expert-to-Expert on Channel9 with one of the Flapjax creators, Shriram Krishnamurthi.
Before we move onto the actual drag and drop scenario, let’s look at the most basic example, tracking the mouse movement. In Flapjax, you could write some inline code which gets compiled to native JavaScript such as the following:
<p>The mouse coordinates are < {! mouseLeftB(document) !}, {! mouseTopB(document) !} > </p>
Then, when compiled with Flapjax, will produce real JavaScript like the following which allows us to track the mouse movement:
<p> The mouse coordinates are < <script lang="text/javascript" type=""> function fxcode0() { compilerInsertDomB(mouseLeftB(compilerUnbehavior(document)), "flapjaxsuid0"); } fxcode.push(fxcode0) </script><!-- --><span id="flapjaxsuid0"> </span> , <script lang="text/javascript" type=""> function fxcode1() { compilerInsertDomB(mouseTopB(compilerUnbehavior(document)), "flapjaxsuid1"); } fxcode.push(fxcode1) </script><!-- --><span id="flapjaxsuid1"> </span> > </p>
Not exactly the prettiest, yet quite effective on what it’s trying to do. What I’d rather do, however, is live in native JavaScript to make this happen instead of some of these more interesting abstractions. In some sense, I like tools that stay true to the language and focus on libraries such as jQuery, Moo Tools, etc, although I do find CoffeeScript oddly fascinating.
To back up my argument for a second with an example in native JavaScript, we could do similar using the Reactive Extensions for JavaScript and a little bit of jQuery. In this case, we’ll take the document’s mousemove event and in our Subscribe method call, we set the coords <span> element with our pageX and pageY values from the mousemove event.
$(document).ready(function() { var mouseMove = $(document) .ToObservable("mousemove") .Subscribe(function(event) { $("#coords").html(event.pageX + ", " + event.pageY); }); });
And then we get to our actual HTML which displays our initial values of 0, 0 inside a span before our mouse starts moving.
<div>The mouse coordinates are < <span id="coords">0, 0</span> ></div>
We could of course have tackled this in any number of ways with any number of frameworks, but it is interesting how they differ in tackling the same problem. Let’s take their example of dragging an object around the screen. You can check their code sample here.
Let’s double up our approach and create two <div> elements that we want to drag around the screen.
<div id="dragTarget1" style="background-color: #000000; border: 1px solid #666666; color: #ffffff; padding: 10px; position: absolute; font-family: sans-serif; cursor: move"> Drag Me! </div> <div id="dragTarget2" style="background-color: #0000FF; border: 1px solid #666666; color: #ffffff; padding: 10px; position: absolute; font-family: sans-serif; cursor: move; left: 150px"> Drag Me Too! </div>
Now, let’s do something interesting with it. We’ll create a function called drag which takes a jQuery element and we’ll return the different between our image offset and the position of the mouse. Let’s first define the function and get our mouse up and mouse move events bound.
function drag(dragTarget) { var mouseUp = dragTarget .ToObservable("mouseup"); var mouseMove = dragTarget .ToObservable("mousemove");
Next, on our mouse down, we’ll need to calculate the difference between the mouse position and the offset of our drag target. We will return an object with a left and top properties calculated with the difference between the mouse position and the element’s offset.
var mouseDown = dragTarget .ToObservable("mousedown") .Select(function(event) { return { left : event.clientX - dragTarget.offset().left, top : event.clientY - dragTarget.offset().top }; });
Finally, we need to take our mouse down and bind it to our mouse down with the SelectMany method passing in our image offset. With our mouse move, we need to prevent the default action of the event from happening, which in this case is the text from being selected. We’ll then project the position of the mouse move and create a delta between that and the image offset coming from the mouse down along with returning our drag target for ease of access. And finally, we’ll do all of this until the mouse up event.
return mouseDown .SelectMany(function(imageOffset) { return mouseMove .Do(function(event) { event.preventDefault(); }) .Select(function(pos) { return { target : dragTarget, left : pos.clientX - imageOffset.left, top : pos.clientY - imageOffset.top }; }) .TakeUntil(mouseUp); });
Below is the drag function in its entirety.
function drag(dragTarget) { var mouseUp = dragTarget .ToObservable("mouseup"); var mouseMove = dragTarget .ToObservable("mousemove"); var mouseDown = dragTarget .ToObservable("mousedown") .Select(function(event) { return { left : event.clientX - dragTarget.offset().left, top : event.clientY - dragTarget.offset().top }; }); return mouseDown .SelectMany(function(imageOffset) { return mouseMove .Do(function(event) { event.preventDefault(); }) .Select(function(pos) { return { target : dragTarget, left : pos.clientX - imageOffset.left, top : pos.clientY - imageOffset.top }; }) .TakeUntil(mouseUp); }); }
Now to hook up the two <div> elements to the drag function and then set the top and left appropriately. To do this, we’ll create an Observer which takes the mouse position and sets the CSS property top and left accordingly. We’ll then call Subscribe on our two elements using the Observer.
$(document).ready(function() { var observer = Rx.Observer.Create( function(pos) { pos.target.css("left", pos.left); pos.target.css("top", pos.top); }); drag($("#dragTarget1")).Subscribe(observer); drag($("#dragTarget2")).Subscribe(observer); });
You can find the source in its entirety here.
Taking lessons from other frameworks gives us some good practice on how to do things with our current library and with the Reactive Extensions for JavaScript and some jQuery, we’re able to do some pretty interesting things such as this simple drag and drop example. That’s just one of the many things we can do with it that I’ll hopefully cover more in the near future. So, download it, and give the team feedback!
What can I say? I love JavaScript and very much looking forward to the upcoming JSConf 2010 here in Washington, DC where the Reactive Extensions for JavaScript will be shown in its full glory with Jeffrey Van Gogh (who you can now follow on Twitter). For too many times, we’ve looked for the abstractions over the natural language of the web (HTML, CSS and JavaScript) and created monstrosities instead of embracing the web for what it is. With libraries such as jQuery and indeed the Reactive Extensions for JavaScript gives us better tools for dealing with the troubled child that is DOM manipulation and especially events.
Another year, another DevTeach. A big thank you to everyone involved. To the organizers, Jean-Rene Roy and Maryse Dubois, thank you for continuing to support and encourage the Canadian developer community. To my fellow Tech Chairs, for helping select an awesome array of both local and international talent to present. To my fellow speakers, for giving some fantastic talks. To all the attendees, for their eager participation, helpful comments, and continued encouragement. To old friends and new whom I spent catching up with in the unofficial speakers lounge, at dinner, and around drinks. There is always something new and fun at DevTeach and this year was no exception. Here are the slides decks and code for those interested:
Convention-over-Configuration in a Web World (pptx | code)
Convention-over-Configuration in an Agile World (pptx | code)
Agile Development with IoC and ORM (pptx | code)
If anyone has any questions, comments, or issues with the slidedecks or code, don’t hestitate to leave me a comment.
I've been reading Neal Ford's series of articles on Evolutionary architecture and emergent design and in the one about 'Investigating architecture and design' he discusses Essential and accidental complexity which I've previously read about in Neal's book, 'The Productive Programmer'.
Neal defines these terms like so:
Essential complexity is the core of the problem we have to solve, and it consists of the parts of the software that are legitimately difficult problems. Most software problems contain some complexity.
Accidental complexity is all the stuff that doesn’t necessarily relate directly to the solution, but that we have to deal with anyway.
I find it interesting to consider where the line is for when something becomes essential complexity and when it's accidental complexity although Neal suggests that there's a spectrum between these two definitions upon which a piece of complexity sit.
I recently read 37 signals book 'Getting real' and one of the things that really stood out for me was the idea of keeping an application simple and writing less software wherever possible.
I'm intrigued as to where this would fit in with respect to essential and accidental complexity because quite often we end up implementing features which aren't part of the application's core value but do add some value yet become way more complicated than anyone would have originally imagined.
Quite often these won't be the first features played in a release because they're not considered top priority and therefore when they are played the amount of analysis done on their potential impact is often less and as we implement these features they end up pervading across the application and increasing its overall complexity.
Another thing that often happens is that we start developing these features, complicating the code base as we go, before the business eventually decides that it's not worth the time that it's taking.
By this time the complexity has spread across the code and it's quite difficult to get rid of it cleanly.
What typically seems to happen is that some of it will just end up staying around in the code base pretty much unused and confusing people who come across it and don't understand what it's being used for.
If we were coming from the angle of Domain Driven Design then we might say that any complexity in the core domain of our application is essential and we should expect that complexity to exist.
On the other hand perhaps we should be more strict about what complexity is actually essential and try and ensure that only complexity around the absolutely vital features is allowed and look to compromise on simpler solutions for features which play a more supporting role.
If we were to follow a definition along these lines then I think we would recognise that there is actually quite a lot of accidental complexity in our applications because although some complex features do contribute to the solution it probably causes more pain than the value that it adds.
The take away for me is that we should be aware that this type of accidental complexity can creep into our applications and make sure that the business knows the trade offs we are making by implementing these types of features.
It's my turn next to talk and try to field questions on the new Ignite your Coding podcast tomorrow. It's a little bit different format where you can join the NetMeeting and jump right into the conversation. I'm going to be talking about the whole "Essence vs. Ceremony" discussion and all the ways we can pack more punch with less code. I want to talk about the newer convention based programming techniques that are popping up everywhere in the newer open source projects in .Net, building and using DSL's in the wild, and techniques for "DRY-ing" up your .Net code. I hope you'll tune it, because I'm a vastly better speaker when I'm getting a lot of questions and even backtalk;-)
The long awaited day has come as the Reactive Extensions for JavaScript have been released on DevLabs in conjunction with the talk given by Erik Meijer at Mix 2010. Jeff Van Gogh, one of the principal developers on this project has more details and a detailed look at the sample application of “Time Flies Like an Arrow”. I’d like to also give a detailed explanation of another sample application, the Bing Maps and Twitter mashup.
One of the demos I’ve created is a mashup of Bing Maps and Twitter so that if the tweet has geolocation information attached that I’d display it on a map in near real time. What that means is that at a specified interval, we query the Twitter search API for something such as FourSquare, which has a higher probability of having some geolocation information attached and then display those results. So, how could we do this? Let’s walk through the example step by step.
First, we need to focus on the Bing Maps AJAX API which gives us the two main features we’re looking for, displaying a map and putting pushpins on it with some detailed information. In order to make use of it, we’ll need to link the Bing Maps AJAX library such as the following:
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"> </script>
Next, we’ll need a place to put our map, so, let’s create a simple <div> to host it.
<body> <div id="veMap" style="position:relative; width: 1000px; height: 600px;"></div> </body>
And then we’ll need our global map object that we can manipulate.
<script type="text/javascript"> var map = null; // More code goes here
Once we’ve defined that, we need a way to show the pushpin on the page. For this I’ll use the tweet ID for the overall pushpin ID, and I’ll take the date, latitude, longitude, their user icon URL, the user name and the text. From there, I’ll create a pushpin in that exact spot with the associated data. I have a try/catch block here where if I’ve seen that tweet before, the Bing Maps API doesn’t allow me to have multiple pushpins with the same ID, so I just ignore the failure.
function addPushPin( id, date, latitude, longitude, imageUrl, text, details) { try { var pinPoint = new VELatLong( latitude, longitude, 0, VEAltitudeMode.RelativeToGround); var detailText = date + "-" + details var pin = new VEPushpin(id, pinPoint, imageUrl, text, detailText); map.AddPushpin(pin); } catch(err) { // Seen it, don't worry } }
Moving onto the Twitter aspect of this, we’ll need a way to query Twitter using the Search API. In this case, we’ll once again use the XmlHttpRequest method with our URL which contains our text and a total request of 100 records per page.
function searchTwitter(text) { var url = "http://search.twitter.com/search.json?rpp=100&q=" + encodeURIComponent(text); return Rx.Observable.XmlHttpRequest(url); }
Once the page loads, we need to load the map, so in my document’s ready function, I initialize the VEMap with the ID of my <div>, load the map and set my zoom level to a nice globe shot.
$(document).ready(function() { map = new VEMap("veMap"); map.LoadMap(); map.SetZoomLevel(2);
Now we get to the interesting part. How do we reload the data every so often without running into the Twitter API limit? We can use the Interval method which we can set a due time before it invokes the action again. In this case, our action is going to be searching for FourSquare which returns an IObservable<IObservable<JSONData>> in C# parlance which we need to flatten and take the first one, so we’ll need the Switch method to do that.
Rx.Observable .Interval(10000) .Select(function() { return searchTwitter("foursquare"); }) .Switch()
Realizing that we’re dealing with JSON data, we need to safely parse it and in this case, I’m using the JSON2 library to do that. We’ll then take the JSON array and split it apart and turn each record into an observable with the SelectMany method. And since we’re only interested in those with geolocation, I check if they have any with my Where method.
.Select(function(result) { return JSON.parse(result.responseText); }) .SelectMany(function(data) { return data.results.toObservable(); }) .Where(function(data) { return data.geo != null; })
Finally, we can subscribe to the resulting observable. Our subscribing action is going to be adding a push pin with the JSON data as well as handle any potential errors.
.Subscribe( function(data) { var lat = data.geo.coordinates[0]; var lon = data.geo.coordinates[1]; addPushPin( data.id, data.created_at, lat, lon, data.profile_image_url, data.from_user, data.text); }, function(error) { alert(error); });
The code in its entirety can be found here. And below is the result of our code where we see the icons of the Twitter users who mention FourSquare after we leave it running for just a few short minutes…
We could take this example further to expire the pushpins over time, but I think overall, it’s a great example of asynchronous programming in JavaScript and how you can integrate it into your APIs.
Through the use of the Reactive Extensions for JavaScript, we’re able to mash two APIs together through AJAX and refresh them at a certain interval, keeping a near real-time feel to it. That’s just one of the many things we can do with it that I’ll hopefully cover more in the near future. So, download it, and give the team feedback!
We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS) from the basic information, creating observers and observables, jQuery integration, composing asynchronous methods with callbacks and in the last post, turned blocking calls into asynchronous calls. Now that we have some more fundamental building blocks, let’s see what else we can do with it. Before moving to FlapJax examples, I want to revisit the Microsoft Translator to take a piece of text and translate into all languages except the currently detected.
Also, if you’re at Mix this year, you’ll notice that Erik Meijer is giving a talk on the Reactive Extensions for JavaScript. I highly recommend that you go to this session, especially if you’ve been interested in this series. Prepare for some pretty slick demos to show off the functionality of the library.
As I stated earlier, the goal of this post was to take our piece of text, detect the language and then translate it to all other languages other than the detected. We’ll make use of the detect, getLanguages and translate methods as we’ve talked about earlier, but with some slight changes. Since the time I wrote these posts, the Microsoft Translator has released a new API for us to call which gets away from the JavaScript library approach and to the URL based approach instead. You can read more about the APIs in their documentation. Let’s get started taking our old code and porting it to the new APIs. First, I’ll need the base URL and an AppID that you can apply for. And next, I’ll need to handle making an XmlHttpRequest, getting the value and then evaluating the response. Yes, I realize that eval might be used for malicious purposes, but in this case, this is simple text being returned.
var url = "http://api.microsofttranslator.com/V2/Ajax.svc/"; var appId = "someappid"; function getResponse(url) { return Rx.Observable.XmlHttpRequest(url) .Select(function(result) { return eval(result.responseText); }); }
Now we can turn our attention once again to the getLanguages function which gives us all of the language codes that are currently supported by the Translator. To do this, we build up a URL for our request, send it to the getResponse function, and then project each language array of our observable sequence to an observable sequence, in this case our resulting array turned into an observable, and flattens the resulting observable sequences into one observable sequence.
function getLanguages() { var serviceUrl = url + "GetLanguagesForTranslate?appId=" + appId; return getResponse(serviceUrl) .SelectMany(function(result) { return result.toObservable(); }); }
Our detect follows the same pattern of building up a URL and gets the response from the XmlHttpRequest as an observable sequence.
function detect(text) { var serviceUrl = url + "Detect?AppId=" + appId + "&text=" + encodeURIComponent(text); return getResponse(serviceUrl); }
And translate follows the very same pattern as well.
function translate(text, from, to) { var serviceUrl = url + "Translate?appId=" + appId + "&from=" + from + "&to=" + to + "&text=" + encodeURIComponent(text); return getResponse(serviceUrl); }
We’ll start first at creating a subscription for the translation button to listen for clicks:
$("#translateCommand") .ToObservable("click") .Subscribe(function(event) { // More stuff here });
Inside of the Subscribe method, we need to clear out the last results as well as get the value of the text to be translated.
$("#translatedText").empty(); var textTotranslate = $("#translateText").val();
Next, we need to add more code to do the actual translation. What we’re going to do is first detect the text and before we get to combining this with another function.
var translator = detect(textTotranslate)
I’m going to need to take the detected language and then translate it into all the other languages. In order to do that, I need to use the SelectMany method which lets you project our detected text to another observable sequence, which in this case will be the languages.
.SelectMany(function(detectedLanguage) { // Code goes here });
Once we get to the languages, we want to filter out the language that equals our detected language, and then once again, project our language to the translate method observable sequence.
return getLanguages() .Where(function(language) { return language != detectedLanguage; })
I’ll take the result of the translated text and then project to return an object with a translated property with our translated text, and the associated language property.
.SelectMany(function(language) { return translate(translatedText, detectedLanguage, language) .Select(function(translatedText) { return { translated : translatedText, language : language }; });
All together, the code to take the piece of text, detect its language, and translate it into all other supported languages looks like the following.
var translator = detect(textTotranslate) .SelectMany(function(detectedLanguage) { return getLanguages() .Where(function(language) { return language != detectedLanguage; }) .SelectMany(function(language) { return translate(translatedText, detectedLanguage, language) .Select(function(translatedText) { return { translated : translatedText, language : language }; }); }); });
Then we could subscribe to this observable sequence and for example, take a sentence “Do you know what time it is?” and translate it into 29 other languages.
What’s really interesting about this example is the true asynchronous behavior. If I press the button again with the same sentence, the order of their return is not always the same each and every time.
Through the use of the Reactive Extensions for JavaScript, we’ve been able to compose together asynchronous behavior of detecting a piece of text’s language, and translating it into 29 different languages all at once. This could apply to any number of scenarios where we need to compose together one asynchronous call after another, but only when certain things happen. And better yet, to use code in a fluent API style, you don’t have this logic scattered throughout all of your functions.
This of course is only scratching the surface of what capabilities this library has and there is much more yet left to cover. The question you’re probably asking now is where can I get it? Well, for that you’ll have to stay tuned to Erik Meijer and his Reactive Extensions for JavaScript session at Mix on Wednesday.
I've spent a bit of time working with Les recently and it's been quite interesting working out the best way for us to pair together as he's working as a front end developer on the team which means he's best utilised working on the CSS/JavaScript/HTML side of things.
Having said that there are often features which require both front end and backend collaboration and we've been trying to drive these features from the front end through to the backend rather than working on the backend code separately and then working with Les later on to hook it all up to the frontend.
As a result we've found that it seems to be most effective to prototype any backend code that we write while working together such that we just write enough code to allow us to see that everything is hooked up correctly.
Once we're happy that we've got that working correctly then we split up and work side by side, effectively parallel pairing as Vivek Vaid describes it.
At this stage I would focus on driving out the backend code properly with a more test driven approach and Les works on tidying things up from a front end perspective and ensuring that the feature's look and feel is consistent across browsers and doing any other front end related functionality.
The benefit that we've seen from doing this is that we're able to work together on the code where we get the most value from doing so and then split up to work on the other things where we wouldn't add as much value to each other in a pair programming situation.
Since we're working directly together at the beginning of a story we also get the benefit of iterating/talking through the potential approaches that we can take and I've often found that I take a better approach to solving a problem when working with a pair than when working alone.
The thing that we have to be careful about when doing this is ensuring that we're not treading on each other's toes because we are working around the same part of the code base and often on the same files.
This means that there is a bit of merging to do but as we're also sitting next to each other it hasn't proved to be too much of a problem. I think using a source control tool like Git or Mercurial with their merging capabilities would probably make this a non issue.
It seems to me that we're still getting the benefits of pair programming with this approach and I'm more convinced that this might be a useful approach in other situations as well.
Almost two years ago I blogged about Project White, an open source project available on CodePlex which provides an abstraction on top of the UI Automation library built into WPF and Silverlight.
Fast forwarding and there is a new project available called WiPFlash which allows you to drive WPF UI's for testing purposes created by Liz Keogh who is an agile\lean coach here in the UK. When I saw this framework, one of the first advantages such stood out was how clean the API is to work with but also how lightweight and focused the overal framework was.
This got me thinking... I've been presenting on how you can test ASP.net web applications using Ruby, most recently at QCon London which was an amazing experience. This got me thinking, if Ruby is a great language for testing web applications then surely the same applies to desktop applications. Thankfully, by using WiPFlash together with IronRuby you can have the same advantage!
One of the questions I'm commonly asked is why would you use Ruby when testing C# applications? For me, one of the major advantages of Ruby is it's readable natural language – this is perfect for tests. As Ruby is a dynamic language you can also adapt your tests and frameworks to fit your test domain more effectively. As a result, your tests become more readable and more maintainable which means they stand much better chance of supporting the development instead of hindering it. Given the amount of Ruby you need to learn to get started, there is very little overhead for a project as to get started you use a very focused subject and grow\learn, as such team members should be able to pick-up everything required in a hour or so. When combined with frameworks such as Cucumber you can create really powerful acceptance tests which can cover large parts of your application with very little implementation.
WiPFlash – Start application and find control
After downloading IronRuby (currently RC3) and WiPFlash, you can use the REPL (ir.exe) to interact with your WPF application. For example:
require 'lib\WiPFlash.dll' include WiPFlash include WiPFlash::Components a = ApplicationLauncher.new app = a.launch 'D:/SourceControl/wipflash/ExampleUIs/bin/Debug/ExampleUIs.exe'
The first line adds a reference to the assembly. We can now start interacting with the objects. The second\third line includes the namespaces so we can access the object without including the full namespace. Notice how we use the Ruby syntax of :: for navigating the namespace – IronRuby will take care of the translation for us.
The fourth line is where the action starts, we first create the ApplicationLauncher object, this is part of WiPFlash.dll and is used to launch the application which is what we do on the fifth line. We now have a running WPF application along with a reference to the app in the variable. The application is this example looks like this:
The next stage is to gain access the controls and start interacting with them as a user might. First, obtain the window where the controls are. This is very similar to how you would using C#.
window = app.find_window 'petShopWindow'
The next stage is to obtain a reference to the actual control. This is where C# and IronRuby go in a slight different direction. The C# API uses generics, with the syntax such as:
TextBox name = window.Find<TextBox>(“petNameInput”)
With IronRuby, we have a slightly different syntax, the most important part is the of() which defines the generic type:
name = window.method(:find).of(TextBox).call("petNameInput")
petNameInput refers to the WPF control name, which if you are unsure of, you can use applications like Snoop to find the name.
Once we have the control, we can set\get the text property.
name.Text = "Bob"
Fundamentally, we can now use the API in exactly the same way we could via C# - but why is that interesting?
Extending WiPFlash via IronRuby
But before we get into the interesting Cucumber + WiPFlash, we have a problem with the API and the generic syntax. Personally, I think it is too wordy with the impact facts being lost. Thankfully Ruby is a dynamic language, and we can extend the framework to meet our requirements resulting in a syntax of:
text = window.find_TextBox "petNameInput"
Amazingly, this is easy to achieve thanks to the special method_missing hook in Ruby. This method is called when a message is sent to an object which doesn't match a pre-defined method. This means you can to take action and is how ActiveRecord allows for a flexible query syntax.
The code below makes the syntax above possible. GetType takes in the method name we called, and returns the part relating to a WiP component. This is converted to a class name within get_class before being used within find_ui_element together with the args originally passed to the method. Simple, but effective.
class WiPFlash::Components::Container def get_type(name) name.to_s.split('_')[1] end def get_class(name) Kernel.const_get(name) end def find_ui_element(class_name, *args) self.method(:find).of(class_name).call(args[0][0].to_sym) end def method_missing(m, *args, &block) ui_type = get_type m ui_class = get_class ui_type find_ui_element(ui_class, args) endend
With our nice clean API allowing us to obtain controls via window.find_TextBox("petNameInput") we can start testing.
WiPFlash + Cucumber
With this in place, we can now plug everything together and use Cucumber together with IronRuby to test WPF applications. The complete example can be found at http://github.com/BenHall/wipflash_cucumber_driven_example
To install Cucumber, run the command (ir being the IronRuby interpreter):
ir -S gem install cucumber
For example, let's say we wanted to test the following:
Scenario: Saving a product by name only Given the application has started And I enter the name "Product 1" When I save the product Then "Product 1" should be available to purchase
Above is a cucumber scenario. Using the Given, When, Then (GWT) syntax we define the 'given' steps to setup our test context and data, 'when' to perform a particular action and 'then' to verify it worked successfully. The most important aspect is the language used. When defining your scenario, you should use business oriented language to describe the behaviour of the application instead of the actual implementation or UI. There are two (main) reasons for this, one is that you can use the scenarios as a communication base with customers and the business to form acceptance criteria about how the application should work. The second reason is that if your application's implementation changes you only need to change the implementation of the test instead of the wording and aim. This will save you a huge amount of effort during the project.
The implementation of the test is as follows. Each cucumber step relates to a ruby code block:
Given /^the application has started$/ do host = ApplicationLauncher.new @app = host.launch Dir.pwd + '/src/ExampleUIs/bin/Debug/ExampleUIs.exe' @main_window = @app.find_window 'petShopWindow' end Given /^I enter the name "([^\"]*)"$/ do |product_name| textbox = @main_window.find_TextBox "petNameInput" textbox.text = product_name end When /^I save the product$/ do button = @main_window.find_Button "petSaveButton" button.click sleep(1) end Then /^"([^\"]*)" should be available to purchase$/ do |product_name| combo = @main_window.find_ComboBox "basketInput" combo.Items.should include("Pet[#{product_name}]") end After do |scenario| @app.process.kill end
The main different to what we discussed previous is the 'After' step which is a hook within Cucumber called after the scenario has finished. This means we can kill the application launched in the first step and ensure we have a clean system with no left over processes.
To execute the tests you would run the command:
ir -S cucumber features
We can now test our WPF applications using Cucumber, taking advantage of the flexible nature and re-useable steps together with an appropriate language for driving acceptance tests.
Let's say you're a developer -- and you probably are if you're reading this. How do you know if you have a generally sunny, optimistic set of mind or a gloomy, pessimistic attitude? It's very simple. You know how you constantly look at 6 month old code and see a better way to rewrite the code? An optimist rewrites that code and says "damn, the new code is so much cleaner!" The pessimist rewrites the old code and says "damn, that old code sure was a mess."
And if you never find any thing wrong with your 6 month old code? You sir are either severely lacking in retrospection and/or you might very well be unconsciously incompetent.
In an interesting turn of events, I've been invited to blog here! Having followed CodeBetter for a number of years, I'm extremely honoured and excited to be sharing my thoughts, opinions and discussion points here.
My aim is to share my learning experience and journey on becoming a better software developer – or even a software craftsman with readers hopefully pointing me in the right direction when I go astray...
Before CodeBetter, I've been blogging at Blog.BenHall.me.uk. My plan is to keep this blog alive with personal items such as slides, upcoming presentations and topics unrelated to CodeBetter. Alongside my blog, I was the co-author of Testing ASP.net Web Applications, released last November covering various different issues associated with ASP.net from TDD to manual testing to load testing. Using this as a foundation, I'm planning to cover more topics related to the subject together with my current work at 7digital.com where I am a developer.
If you want to know what I'm up-to before (or even if) I write about it here, then follow me on Twitter and on GitHub.
About CodeBetter.ComCodeBetter.Com FAQOur Mission Advertisers should contact Brendan
Subscribe
Google Reader or Homepage del.icio.us CodeBetter.com Latest ItemsAdd to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online Subscribe with myFeedster Add to My AOL Furl CodeBetter.com Latest Items Subscribe in Rojo
Member Projects
Sarasota Web Design - David HaydenPatterns & Practices - David Hayden dotMath - Steve Hebert Structure Map - Jeremy D. Miller StoryTeller - Jeremy D. Miller The Code Wiki - Karl Seguin
Friends of CodeBetter.Com
Red-Gate Tools For SQL and .NETTelerik ComponentArt VistaDB JetBrains - ReSharper Beyond Compare .NET Memory ProfilerNDepend Ruby In Steel SlickEdit SmartInspect .NET Logging NGEDIT: ViEmu and Codekana LiteAccounting.Com DevExpressFixx NHibernate ProfilerAForge.NET UnfuddleBalsamiq Mockups Scrumy <-- NEW Friend!
Site Copyright © 2007 CodeBetter.Com Content Copyright Individual Bloggers