Feeds:
Posts
Comments

Archive for June, 2007

Fran’s Bouma has an interesting post about the importance of documentation.  I mostly agree with him.  We developers generally hate to write documentation, and Agile processes lead us to believe that we don’t need to.  Our code is the documentation.

Well, I’ve used enough frameworks, OpenSource libraries and worked on enough unrelated large, pre-existing products that I can say with certainty that this is simply not true.  Code is not documentation, nor is it enough "information" to get you by.  The amount of time required to become familiar enough with a large code base to be able to just find your way around, let alone to correctly implement something inside of it, is simply huge.  I think most of us have been there in our careers.  You’re on a new project or using some new library, and the source code is all you have.  You get assigned your first defect to work on and "become familiar with the code".  You have absolutely no idea where to begin to look for the cause of the defect, and have a directory full of thousands of files with millions of lines of code.

Since we’ve all been there, we all fall back to the same patterns to "solve" our dilemma.  Out comes grep or some equivalent utility and we search for keywords we *think* will help us to find the area of the code in which to start looking.  If you’re monumentally lucky, this will locate a minimum of hits and you can start trying to decipher the code.  Usually, though, you have to refine your search numerous times, and sometimes you’ll even have to resort in asking someone else where to look, because you simply can’t find anything unique to search on, and reading a million lines of code is obviously out of the question.

So, you eventually find where to look.  If the code is well designed and maintained, you can probably figure things out with little effort at this point.  But we all know the reality is that the code has likely grown organically and is now "spaghetti" that you have to pick apart.  Always a difficult task, but worse when you’re new to the code base.

Well, you pick it apart and fix your first defect.  Congratulations, that just took you a factor of 10 times the amount of time it should have.  But, that’s to be expected, because you’re new to the code.  So, on to the next defect.  Rinse and repeat for a month or two.

Whew.  Now you’re "acclimated" to the code base.  You can find your way around fine, so everything’s OK now, right?  Nope.  Now you’re given more difficult defects to work on, and since you’ve got nothing but the code to rely on for "documentation" you have to take what you see in the code literally.  The problem is, the code is specific, but not necessarily literal.  There’s all kinds of information "between the lines" of the code.  The "why" that Fran’s talked about.  So, you change an algorithm in ignorance and cause a meltdown in the code.  Or you "copy" a pattern from one place in the code (and no, I do not mean you copy and paste code blindly and/or fail to refactor to properly reuse code), just to discover that there’s details you don’t understand that applied only to that specific place in the original code.

No, code is simply a set of instructions.  It’s not documentation.  Documentation is designed to be consumed by humans, code is designed to be consumed by a computer.  Documentation has things code does not, nor can it.  Like a table of contents, a forward, an overview, an index, and figures and diagrams that convey a lot of conceptual information at a glance.  Documentation is understandable by team members who aren’t developers, such as QA, sales and business analysts.

I can consume a large technical manual in a matter of hours.  Personally, I read Petzold’s latest book on WPF in roughly 2 hours, cover to cover, and retained most of the information contained in the book.  What’s not retained is readily re-discoverable through the table of contents, index and other structural concepts found in documentation that’s not found in code.  In contrast, I’m lucky if I can read through a dozen source files in an entire work day with any real "depth of knowledge" on what I read.  That’s not because I’m not experienced in reading code, though I will admit there are people who seem to be better at "spelunking code" than I am.  It’s because code doesn’t convey concepts, it conveys procedures.  Code isn’t structured for human consumption, it’s structured for machine execution.

Technorati Tags: ,
Advertisements

Read Full Post »

ModelView and Commands

I believe very strongly in using the Model-View-ViewModel (be sure to search the blog site and read all the related articles) design pattern when programming in WPF.  You want your UI to be as "dumb" as possible.  There’s two reasons for this.  First, we’re moving towards a world where designers will be creating our UIs, so you need to find ways to remove the programming from the UI design entirely.  The designer should be able to use Blend or some other design tool to first mock-up the layout, and then databind the UI to objects provided by the programmer.  If you put logic in the UI directly, it complicates the process for the designer.  Even the idea of letting the developer modify the codebehind after the view has been mocked up isn’t enough, since this still makes it difficult for the designer to make large changes to the UI later (such as replacing a ListBox with a Combobox or other such design changes).  Databinding and Commands actually allow the designer to tie controls to data and actions with no regard to the logic involved.

The other reason is for testing.  Testing UIs is non-trivial at best.  UI test automation software relies on simulating a user via "robot" scripts.  If you’ve ever done this, you know that writing these scripts is non-trivial.  Worse, they break with every minor UI change.  This makes doing automated UI testing extremely difficult at best.  However, by not putting real program logic in the UI code at all, it makes testing the full functionality of your application as easy as testing can be.  A little human testing of the actual UI will then suffice.

So, after that long diatribe, let’s get to the heart of what I wanted to blog about.  I’ve been working on that MtG Binder application, and actually have an application running now that does everything that Gatherer does.  Lots of design work needs to be done on it yet, since the current UI is functional but not pretty.  There’s also a lot of features that go beyond Gatherer that I plan to add.  In other words, lots of work yet to do.  But I’ve learned a lot about WPF development by undertaking this endeavor.

One of the things I strived to do with this application is to use the M-V-VM pattern.  That’s a good thing, since it allowed me to hack together a working "prototype" that’s "functional but not pretty", while allowing me to easily turn it into something "elegant" with out having to touch the code.  The key to this pattern, to my mind, is the VM.  Anyone who’s done UI work before is familiar with MVC and it’s variants, such as Document-View from MFC.  So there’s nothing to learn about proper data modeling, and not much to learn about proper view construction.  What’s new with WPF (and yes, I know it’s not new to Mac developers and other folks) is how databinding and Commands allow you to really put all of the user interaction logic inside the ViewModel instead of in your View.  Even if you consider the ViewModel to just be the Controller from MVC (I don’t think that’s accurate, but you can make the argument), with older technologies you still had to put a lot of logic in the View.  Not anymore.  Data, data conversions, data manipulations, and basically anything involving data can now be put into a ViewModel and trivially bound to UI controls.  This means complex control interactions, such as changing data displays in a panel based on the item selected in a listbox no longer needs any event logic at all.  For more complex user interactions, you can use Commands to abstract away the action coupling from the actual action.  A Command that submits data can be bound to the action taken from clicking a button, or to the action of losing focus on a control, all with no event handling logic needing to be coded.

My first attempt to do this, however, fell a little flat.  I put the Command definition on the ViewModel, where it belongs.  But when it came to implementing the CommandBindings for the command, I ran into problems.  The various command delegates should logically be defined in the ViewModel as well, but I found that the XAML didn’t like wiring it this way (maybe it can do it and I didn’t persist in figuring out what the issue was long enough, but I wanted to get things done and not spelunk into code through Reflector).  I knew John Gossman discussed doing this, so I inspected his example code.  To be honest, I didn’t totally like what he’d done.  He abstracted out commands into a CommandModel with virtual methods you could override for the delegates on the CommandBinding.  But the actions taken by the commands is almost certainly going to require knowledge of the ViewModel.  I didn’t want to create objects with this kind of coupling, especially when the functionality seemed to belong on the ViewModel not on a CommandModel.  So, I hacked his code to turn it "inside out".  Here’s what I wound up with.

public class CommandModel
{
    RoutedCommand command;
    ExecutedRoutedEventHandler executedHandler;
    CanExecuteRoutedEventHandler canExecuteHandler;

    public CommandModel(ExecutedRoutedEventHandler executedHandler)
    {
        command = new RoutedCommand();
        this.executedHandler = executedHandler;
    }

    public CommandModel(ExecutedRoutedEventHandler executedHandler,
        CanExecuteRoutedEventHandler canExecuteHandler)
    {
        command = new RoutedCommand();
        this.executedHandler = executedHandler;
        this.canExecuteHandler = canExecuteHandler;
    }

    public RoutedCommand Command
    {
        get { return command; }
    }

    virtual public void OnQueryEnabled(object sender, CanExecuteRoutedEventArgs e)
    {
        if (canExecuteHandler != null)
        {
            canExecuteHandler(sender, e);
        }
        else
        {
            e.CanExecute = true;
            e.Handled = true;
        }
    }

    virtual public void OnExecute(object sender, ExecutedRoutedEventArgs e)
    {
        executedHandler(sender, e);
    }
}

This allows me to create the CommandModel within the ViewModel and tie it to event handlers within the ViewModel itself.  I you want to use it in the way illustrated by Mr. Gossman, you still can, but I prefer the functionality to be in the ViewModel.

The only thing I’m left with that still feels a bit kludgy to me is the CreateCommandBinding class with the attached property used to wire up the actual CommandBinding through our CommandModel.  But it works, so I’ll live with it until I find a more elegant (to my eye) solution.

Technorati Tags:

Read Full Post »

This isn’t anything new.  It’s a couple of old screen casts that show using IronPython to learn WPF.  If you haven’t seen them, you should.  IronPython turns out to be a great way to "play" with WPF, which is useful even when you’re no longer a newbie.  It’s a shorter development cycle to test out concepts in script and then implement in your language of choice, then it is to go through the edit/compile/test cycle.

The main reason for this post, is so that I have a convenient place to find these resources again.

http://mattgriffith.net/Permalink.aspx?guid=0b9de84a-d84e-484c-b06f-8ff75ab70b9f

http://mattgriffith.net/PermaLink.aspx?guid=a1cb7215-2719-4c38-8ce3-ba7408aa69aa

 

Technorati Tags: ,

Read Full Post »

I’ve used many UI frameworks.  Some of them have built in layout capabilities, and others don’t.  Obviously, building a complex UI, especially one that requires the capability to be resized, is much easier to do in a framework that has layout facilities.  Unfortunately, even the frameworks that I’ve used that have very rich layout "managers", it often turns out that creating layouts is still a difficult task.  And I’m not referring to the complexities of design here.  No, I’m talking about actually making your layout match your design through code!

All of that was just introduction to this post, which is a rant about my current trials and tribulations using WPF.  But don’t take this wrong.  This isn’t an attempt to bash WPF, because as I said in the first paragraph, I’ve found every framework I’ve ever used to be lacking.

The trouble is that, though layout managers follow strict and rigid rules for how child controls are positioned and sized, there are two things that make using them difficult.  First, the actual rules used aren’t always well documented.  Interactions from nested layout managers can cause scenarios that just aren’t discussed in the documentation, which generally tries to give a high level description of how layout occurs, rather than explaining the algorithm in detail.  Except for corner cases, though, this issue is one that experience with the framework can overcome rather quickly.

The bigger issue is that often the layout algorithms are simply incomprehensible.  They don’t behave the way you’d expect them to, which makes becoming familiar with the undocumented behavior difficult at best.  In some cases, it seems just impossible to figure out, and you’re left with "hacking" the layout to get it to behave, at least close to how you want it to behave, for specific scenarios.  These hacks, however, don’t lend themselves to repeated use in similar but different layout scenarios.

Here’s a great example, and one that I’m struggling with in real code, and actually what brought on this rant.  Let’s start with a simple layout.  Imagine we have some data we want to present, and just for illustrative purposes we’ll say it’s data about books we have in stock for resell.  There’s lots of data, but what we care about presenting is the title, the price and an excerpt or other lengthy text about the book.  I’m not going to be too specific here, and this is all just for illustrative purposes.  We want to place the title of the book on the first line, and also place the price on this line, but make it right aligned.  Then, on the next line we’ll place the excerpt, but we want it to wrap to multiple lines depending on the size of the page.

All of this sounds rather simple, and in fact it is rather trivial to do in WPF/XAML.  Here’s some example code with hard coded data to illustrate the layout.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Column="0" Text="Title Here"/>
      <TextBlock Grid.Column="1" Text="Price" TextAlignment="Right"/>
    </Grid>
    <TextBlock TextWrapping="Wrap"><![CDATA[
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed neque et tellus tincidunt interdum. Morbi diam eros, imperdiet at, volutpat et, vestibulum quis, sem. Curabitur eu tellus vel felis molestie malesuada. Pellentesque nec lacus. Aenean fringilla nonummy sapien. Morbi eu odio at turpis cursus tristique. Integer nec lectus sit amet turpis bibendum feugiat. Cras posuere condimentum sapien. Vivamus accumsan, lacus at bibendum vehicula, magna elit consectetuer diam, ac luctus elit diam non leo. Vestibulum lobortis augue nec nisl. Fusce viverra purus consequat lacus. Nullam elementum mattis tellus. In hac habitasse platea dictumst. Aliquam ac velit sit amet urna placerat fringilla. Fusce mattis arcu eget urna. Sed lacus. 
]]></TextBlock>
  </StackPanel>
</Page>

This works great, and out layout is easily resizable.  But we don’t have a single book, we have a collection of them.  So we want to do this inside a ListBox (or other such ItemsControl).  So, here’s the same layout, but placed in our ListBox (again, I’m hard coding things for simplicity, but you’d find the same results using styles/templates and bound data).

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <ListBox>
    <StackPanel>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="Title Here"/>
        <TextBlock Grid.Column="1" Text="Price" TextAlignment="Right"/>
      </Grid>
      <TextBlock TextWrapping="Wrap"><![CDATA[
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed neque et tellus tincidunt interdum. Morbi diam eros, imperdiet at, volutpat et, vestibulum quis, sem. Curabitur eu tellus vel felis molestie malesuada. Pellentesque nec lacus. Aenean fringilla nonummy sapien. Morbi eu odio at turpis cursus tristique. Integer nec lectus sit amet turpis bibendum feugiat. Cras posuere condimentum sapien. Vivamus accumsan, lacus at bibendum vehicula, magna elit consectetuer diam, ac luctus elit diam non leo. Vestibulum lobortis augue nec nisl. Fusce viverra purus consequat lacus. Nullam elementum mattis tellus. In hac habitasse platea dictumst. Aliquam ac velit sit amet urna placerat fringilla. Fusce mattis arcu eget urna. Sed lacus.
  ]]></TextBlock>
    </StackPanel>
  </ListBox>
</Page>

Oops.  When you run this you’ll find that, despite the fact we’ve used identical code for the layout of the data, our text excerpt now fails to wrap!  This behavior is definitely not intuitive, and it makes understanding the logic employed by the layout managers very difficult to learn.

Searching the web for explanation on this, or at least for a way to achieve what we want, I find posts like this one.  So, the prevailing "solution" is a hack that removes the horizontal scrollbar.  This works, but I call it a hack for a reason.  This only works in very specific circumstances.  Even in this specific case, it has problems.  Resizing the control to be too small can cause issues with the first line of data.  We really want to limit the width of the Grid to prevent having it sized too small to present the title and the price.  If it gets too small, we want the user to be able to scroll to see all of the data, but in order to do that we have to not disable the scrollbar, resulting in our first problem again!

I’ve tried other hacks, such as data binding the Width of the TextBlock to the ActualWidth of the ListBox.  This almost works, though there are some resizing artifacts caused by this.  In any event, that’s a fairly draconian solution to what seems to me to be simply a design flaw in WPF layout logic.  I obviously made the TextBlock wrap for a reason, and any panel that ignores that is, IMHO, broken.

So, now that my rant is over, are there any WPF experts that care to explain how this simple layout should be achieved?

Edit:  Here’s another great example of inconsistent layout behavior to illustrate my point.

 

Technorati Tags: ,

Read Full Post »