CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Get Your Func On

I've noticed that I have a 2 step pattern for learning new framework or language features. I'm guessing this is pretty typical for most people. First, I'll us the feature within framework classes or 3rd party ddls. Then I'll leverage it more directly within my own code. What's surprising to me is the length of time which occurs between step 1 and step 2.

Take generics for example. Back in the 1.x days, I wrote a ton of repetitive classes that inherited from CollectionBase. So when 2.0 came out, I immediately and aggressively started to use generic collections. However, it was quite some time later (a year?) until I wrote my own class that leveraged them directly. Today, I don't write a new generic class every day, but I do consider them an important part of my toolbox and kinda wonder what took me so long to take them up.

I have a feeling that many developers are in the same boat - it's easy to consume code that implements new features, but not so easy to grasp how to implement those same features ourselves.

As it turns out, the other day, I had another such ah-hah moment with the System.Func generic delegate. Like me, you've probably consumed it often, or at least one of its cousins: System.Action and System.Predicate. I thought I'd show how I used it, in hopes that it might open up some possibilities for you.

Ovewview

First though, a brief overview. The three delegates above are essentially shortcuts that save you from having to write your own common delegate. The most common one is probably Predicate<T>, which returns a boolean. Predicte<T> is used extensively by the List<T> and Array classes. The most obvious is the Exist method:

List<string> roles = user.Roles;
if (roles.Exists(delegate(string r) { return r == "admin";}))
{
   //do something
}

or the lambda version (which I much prefer)

if (role.Exists(r => r == "admin))
{
}

Func<T> is a lot like Predicate, but instead of returning a boolean it returns T. Also, Func<T> has multiple overloads that let you pass 0 to 4 input parameters into the delegate. Action<T> is like Func<T> except it doesn't return anything - it does an action.

Code Decoupling

So, how can you make use of these within your own code? Well, here's what I did. First, I'm a big proponent of caching, as well as a big fan of unit testing. However, the two don't easily go hand-in-hand because Microsoft doesn't provide an interface to their built-in cache, which leads to tight coupling (which of course makes it difficult to change caching implementation down the road, and impossible to unit test). The first thing to do is create your own interface, a simple start might look like:

public interface ICacheManager
{
   T Get<T>(string key);
   void Insert(string key, object value);
}

Next comes our first implementation:

public class InMemoryCacheManager : ICacheManager
{
    public T Get<T>(string key)
    {
        return (T) HttpRuntime.Cache.Get(key);
    }
    public void Insert(string key, object value)
    {
         HttpRuntime.Cache.Insert(key, value);
    }
}

Func Fights Repitition

So, what does all this have to do with System.Func? Well, the above code is used in a very repetitive manner: get the value from the cache, if it's null, load it from somewhere and put it back in the cache. For example:

public User GetUserFromId(int userId)
{
    ICacheManager cache = CacheFactory.GetInstance;
    string cacheKey = string.Format("User.by_id.{0}", userId);
    User user = cache.Get(cacheKey);
    if (user == null)
    {
       user = _dataStore.GetUserFromId(userId);
       cache.Insert(cacheKey, user);
    }
   return user;
}

After a year or so of writing code like this, I figured there must be a better way, which of course is where Func comes in. Ideally, we'd like to get the value, and provide our callback code all at once. So, let's change our interface:

public interface ICacheManager
{
   T Get<T>(string key, Func<T> callback);
   void Insert(string key, object value);
}

The second parameter is the delegate we'll want to execute if Get returns null. Of course our delegate will return the same type (T) as Get would - just like in the above case where we expect a User from both Get and our data store. Here's the actual implementation:

public T Get<T> (string key, Func<T> callback)
{
   T item = (T) HttpRuntime.Cache.Get(key);
   if (item == null)
   {
       item = callback();
       Insert(key, item);
   }
   return item;
}

How do we use the above code?

public User GetUserFromId(int userId)
{
   return CacheFactory.GetInstance.Get(string.Format("User.by_id.{0}", userId), 
                                                                () => _dataStore.GetUserFromId(userId));
}

I know the () => syntax might be intimidating (especially if you aren't familiar with lambdas), but all it is is a parameterless delegate.

Of course, this system can easily be expanded to add additional caching instructions (absolute/sliding expiries, dependencies and so on) via overloaded Get<T> and Insert members.

(I just noticed this example also highlights how to use generics within your own code too!)

Composite Application Guidance is Live

Before I go any further, we shipped! :-)

Links:

What's in the box

Here's an overview of what you'll find

image

At the core is the Stock Trader Reference Implementation.

RIScreenshots_small.png

This app is a composite application built in WPF. In it you'll find design patterns, concepts and techniques you can add to your arsenal.

Supporting the RI, you'll find a library which aids in implementing the patterns. The library is light, really light and that's deliberate. We harvested it out of the RI rather than building it first and throwing an app on top. We built it to work with your existing infrastructure rather than you having to build from scratch on top of it. We built it to work 100% with WPF rather than retrofitting WinForm concepts into a WPF world.

Around the RI, you'll find comprehensive documentation (see the diagram above) in which you'll see the major design concepts and patterns are for building composites such as the RI. You can use this knowledge to build your own implementations if you decide that ours is not right for you. You'll also learn how we've decided to implement those patterns and concepts and why. You'll see how to use the pieces separately, or put them together in a coherent fashion to form the baseline architecture you see below.

image

Finally you'll find a set of quickstarts and how-tos to help you get ramped up on the concepts.

A little history

If you'd have asked me 12 months ago, I would have said this day would have never come. Around that time we had just announced that we had no further plans to do anything in the CAB space. Instead our goal was to lead everyone toward a mythical creature called Acropolis. With Acropolis on the way it didn't make sense for us to continue. Then by some strange twist of fate, Acropolis was folded into future versions of the framework. This opened the door for us to address building Composite applications for WPF. Once we had the green light to go ahead, we had a tough decision to make, take CAB forward to WPF or start over. We chose to start over. 8 months later, we've incorporated tons of community feedback, built a new set of guidance specifically for building Composite applications in WPF. As it goes out the door, we're very happy we stuck to our guns on that decision.

The Team

We couldn't have done it alone. In addition to a fantastic, and extremely focused team including Brian Noyes from IDesign, Adam Calderon from Interknowlogy, Southworks and Infosys we had a large set of advisors. Across Microsoft, we had help from several product teams including WPF (Henry Hahn,Ivo Manlov,John Gossman,Mike Hillberg,Rob Relyea), UIFX (Brad Abrams and David Hill), DPE (Jaime Rodriguez, Karsten Junszewski, Jared Bienz, Mark Feinholz), and App Dev Consulting's Josh Twist. Combine this with an amazing committed group of partners (Infragistics), industry experts and advisors including David Platt,Jeremy Miller, Ohad Israeli,Oren Eini, Rob Eisenberg, Szymon Kobalczyk,Udi Dahan, and Ward Bell. This is just a sampling, the full list is below

Bil Simser, Brad Abrams (Microsoft Corporation), Chad Myers, David S Platt (Rolling Thunder Computing, Inc.), Derek Greer, Ian Ellison-Taylor (Microsoft Corporation), Ivo Manolov (Microsoft Corporation), Jamie Rodriguez (Microsoft Corporation), Jeremy D. Miller (Dovetail Software), Josh Twist (Microsoft Corporation), Matt Smith (AltiMotion Corporation), Mark Tucker (JDA Software Group, Inc.), Michael D. Brown (Software Engineering Professionals, Inc.), Michael Kenyon (IHS, Inc.), Michael Sparks (RDA Corp), Ohad Israeli (Hewlett-Packard), Oren Eini (aka Ayende Rahien), Peter Lindes (The Church of Jesus Christ of Latter-day Saints), Rob Eisenberg (Blue Spire Consulting, Inc.), Shanku Niyogi (Microsoft Corporation), Scott Bellware, Szymon Kobalczyk (InterKnowlogy), Udi Dahan (The Software Simplist), Varghese John (UBS), Ward Bell (IdeaBlade)

Final thoughts

For me, this has been an incredible journey. I've had the pleasure of working with the most talented individuals inside and outside of Microsoft than I have to date. It just doesn't get any better than this! Thank you to everyone who has made this possible!

As Soma likes to say Namaste!

RockNUG Meeting - 7/9/2008 - Functional C#

Next week I will be presenting a lightning talk at the next Rockville .NET Users Group (RockNUG) on Functional C#.  I've talked about this topic quite a bit recently on a couple of threads now:
In this talk I hope to cover some of the basics including:
  • Currying
  • Filter
  • Map
  • Option Types
  • Tuples
  • Folding and Unfolding
  • Recursion
  • Lazy Evaluation
  • And more...
I know it's quite aggressive for such a short timeframe, and I may cut some of them due to how many questions I get.  This will be a continuation of my talk at the NoVA Code Camp back in May.  At the end, I hope to post my code at least.  I haven't published my slides due to me not being exactly happy with them yet.  I'll post a wrapup afterwards.

Anyhow, here are the details:

Date/Time:
Wednesday, July 9, 2008 - 6:30-9:00 PM

Location:
Montgomery College, Rockville
Humanities Building - Room 103
Rockville, MD
Directions

Hope to see you there!

Holiday postcard, Turkish internet cafe's

Almost holiday. To get in the mood two holiday postcards shot last holiday in Bodrum, Turkey.

Colorfull as everything in Turkey. I didn't check inside, promised myself to stay off line for the entire holiday to read myself into deeper insight. The local ATM's did promise a smooth and fast net.

This is also an answer to a somewhat enigmatic Turkish comment on a picture of Charles Petzold. Where is the man ? Right here !

Enjoy your holidays !

Showing some support for LINQ to SQL

While I have finished my series on LINQ to SQL I wanted to talk about some of the reaction. In his summary post of 30 June Roger Jennings mentions his concerns that because the SQL Server Data Programmability group, who are bringing us Entity Framework v1, now owns LINQ to SQL we will not see the kind of development I asked for in my last post of my Architecting LINQ to SQL series. Indeed Matt Warren's comment in this post, that the provider model for LINQ to SQL was disabled before release is troubling for what it implies about internal politics over data access strategies in Redmond and might confirm concerns I had a long time ago.  Looking at the the Data Platform team's blogs and site, LINQ to SQL seems almost forgotten.

I would like to see MS give this product the support it deserves. I would like to see a commitment from the Data Platform team to stop its focus on talking LINQ to SQL down as a RAD tool and tallking up its advantages for use in the OO approaches to software development. For example  I would like to see the Data Platform team talking about LINQ to SQL's support for POCO strategies, lazy loading, etc. and pointing out to customers who request those features. There needs to be more acknowledgement that if you want them you should consider LINQ to SQL. Right now their only response is to repeat that those features will be in Version 2 of the EF. Well, an MS ORM supports those features today, you should point that out to your customers, and give advice on how to achieve it. As of now, in my opinion, LINQ to SQL is their best development tool for OO an approach to development and they need to reflect its strengths in the advice they give, not just focus on its weaknesses when compared to EF. 

Martin Fowler posted some time ago about different schools of software development. Perhaps one solution for the conflict over the future of these tools is for MS to accept that it has (at least) two audiences and build a product for the OO folks and one for the data-first folks. In that case LINQ to SQL would be a better start for the OO folks because it already contains so much of what they need, it may represent a better starting point for supporting them.

People feel sorry for the Entity Framework team for the criticism in the open letter. For my part I feel sympathy for the LINQ to SQL team, who fell foul of product strategy decisions with ObjectSpaces and seem to have done so again. Considering how well they understood the OO approaches we wanted, unlike the EF team, the team are unsung for their efforts. The Alt.Net community in particular should give them wider support for having, unlike the Entity Framework team, recognized the needs of those developers taking an OO approach to development. it does not give us everything, but credit where it is due.

Today, while I would not recommend using the Entity Framework I would recommend looking at LINQ to SQL. Everything needs evaluation for your own needs, but unlike EF, LINQ to SQL is a better contender for OO approaches today.

Sasha points out when looking at how LINQ to SQL is suprising people who had been misinformed as to what if offered and how we should use it, the noise in the blogsphere from Entity Framework supporters seems to have drowned out the value of LINQ to SQL as an ORM. Indeed I believe the Data Team's own pitching of LINQ to SQL as a RAD tool is an underestimates the product.

As a community, as people begin to realize the suprising power of LINQ to SQL, I would like to see us dispel many of the myths that seem to have grown up around that product. I would like to see us put pressure on the Data Platform team to provide the support for LINQ to SQL that we want going forward. Community reaction is everything and if the LINQ to SQL community remains silent in the face of the more vocal, but probably less numerous, EF community, we won't get the product we deserve.


Define Recursion - See Recursion

Lately, I've noticed a few blogs are doing the come back to basics post, such as Scott Hanselman's.  I think that's an effort that should be lauded, because many have a tendency to go off on pretty advanced topics, yet not provide enough for those just starting to get the full context.  So, with that, I'm going to dig into one piece of programming that should have been ingrained should you have been a CS major in college or at least took some courses.

Recursion

Recursion is one of those basic topics that come up time and time again as one of the core topics.  It's not as often talked about in the imperative and object oriented world, but in the functional programming world, it matters a whole bunch.  Not only to be able to describe what it is, but the benefits, and where you might be able to break your problem down into using it.

So, before we get too far, what exactly is it, and how do we get there?  Basically recursion is to allow a function to call itself repeatedly during the body of that function.  Most imperative languages from the C world use for loops, while loops and so on, so many times recursion isn't needed.  Functional languages such as F#, allow for recursion, but makes them a special designation to enforce its behaviors. 

When coming to a place such as Microsoft, understanding these concepts are key.  Chances are you may get asked some of these questions, because people like me, when walking through complex structures, use recursive algorithms.  It's a nice tool to have in the toolbox.

Let's first look at an example not using recursion, then move towards recursion.  First start off with a pretty obvious one in computing a factorial:

public static int Factorial(int n)
{
    int result = 1;

    for (int i = 1; i <= n; i++)
        result *= i;

    return result;
}

To me, that's pretty horridly imperative.  We can make the code much more concise through the use of recursion and not mutate state during the operation.  With the proper attention of course to decrementing the counter so that we don't get into infinite loops.  An important lesson to learn is to not recurse infinitely, but in a controlled manner towards termination through a technique called "Well Founded Recursion".  Let's rewrite this to a much more manageable way:

C#
public static int Factorial(int n)
{
    if (n <= 1) // Exit condition
        return 1;

    return n * Factorial(n - 1);
}

F#
let rec factorial n =
  if n <= 1 then 1 else n * factorial (n - 1)

The basic idea is to break down your problems into smaller instances of the same problem.  Sometimes, the last thing we do in this function is return the recursion of the function.  This is called "Tail Recursion".  Below is a simple example of tail recursion:

let rec last l =
  match l with
  | [] -> invalid_arg "l"
  | [head] -> head
  | head :: tail -> last tail

The above sample will ultimately give me the last item in a list since F# has pointers to the head of the list, we need to get the last one.  We'll get more into tail recursion in the next post, but I thought I'd introduce it now.  It's very important as well to know.

Let's take another example, this time walking a directory structure to lazily display all files in a directory.  Of course we can note that the Directory.GetFiles already has the capability of getting all files in all folders, but for this exercise, let's pretend it doesn't exist.  How might we do this?  Let's try the lazy approach the first time around through IEnumerable<string>.

C#
public static IEnumerable<string> GetFiles(string rootPath)
{
    foreach(var file in Directory.GetFiles(rootPath))
        yield return file;
    foreach (var directory in Directory.GetDirectories(rootPath))
        foreach (var file in GetFiles(directory))
            yield return file;
}

F#
let rec getFiles rootFolder =
    seq {
          for file in Directory.GetFiles(rootFolder) -> file
          for dir in Directory.GetDirectories(rootFolder) ->> getFiles dir
        }

What this allows me to do is recurse through a given directory hierarchy by first grabbing all the files and then going through a tail recursion through all the subdirectories.  The F# way is a bit more concise through the use of Sequence Workflows, which I'll get to at another time.  If you understand anything about F#, understanding workflows is by far one of the most important.

Mututal Recursion

Another interesting way to express recursion is to define them simultaneously by separating the definitions.  This allows the functions to play off each other and work towards a deterministic end.  The cannonical example of this is the odd/even sample.  Let's walk through that quickly in both C# and F#:

C#
public static bool IsEven(int number)
{
    if (number == 0)
        return true;
    else
        return IsOdd(number - 1);
}

public static bool IsOdd(int number)
{
    if (number == 0)
        return false;
    else
        return IsEven(number - 1);
}

F#
let rec even n = (n = 0) || odd(n - 1)
  and odd n = (n <> 0) && even(n - 1)

As you can see, I decrement the counter each time and call the complement function until I reach 0 and at that point, I can determine which one hits 0 and then it becomes apparent whether it is odd or even.  F# goes a bit further to simplify this so that I can declare those functions as a pair through the use of the and keyword.  Parsing of trees is particularly useful using mutual recursion.  But just as easily, we could have done the above sequence without using recursion at all such as this:

public static bool IsEven(int number)
{
    return number % 2 == 0;
}

public static bool IsOdd(int number)
{
    return !IsEven(number);
}

So, that's not really a good example.  instead, let's look at a Hofstadter Male-Female Sequences instead. 

The pair of sequences is defined by Female(0) = 1 and Male(0) = 0 and
Female(n) = n - Male(Female(n - 1)
Male(n) = n - Female(Male(n - 1)

This is defined as the same way as before, but we recursively call in the Male to the Female and back to the male, whereas it's the opposite in the FemaleSequence method.  This is just a simple implementation of the above algorithm in our C# and F# code respectively.

C#
public static int MaleSequence(int n)
{
    if (0 == n)
        return 0;

    return n - FemaleSequence(MaleSequence(n - 1));
}

public static int FemaleSequence(int n)
{
    if (0 == n)
        return 1;

    return n - MaleSequence(FemaleSequence(n - 1));
}

F#
let rec maleSequence n = if n = 0 then 0 else n - femaleSequence(maleSequence n - 1)
  and femaleSequence n = if n = 0 then 1 else n - maleSequence(femaleSequence n - 1)

There are more examples out there, but in the mean time, there's plenty more to cover with recursion.  Next, let's cover lists.

Walking Lists

Another thing we can do with recursion is the ability to walk lists.  Most people think of lists as an ordered collection with a beginning and an end, with one right after another.  How terribly imperative if you think that way...  When we think of lists in a recursive way, we think of a list to have an item, and the rest of the list, or just an empty list.  C# and the base class library does not have this of course defined in any meaningful way, so let's look at the F# version of a list.  

module List =
  val hd: 'a list -> 'a
  val tl: 'a list -> 'a list

What that tells us is that the head item is the first, and the tail is the rest.  Let's do a quick recursion to calculate the length of a list using some pattern matching:

let rec length l =
  match l with
  | [] -> 0
  | head :: tail -> 1 + length tail

What I'm doing is pattern matching against the list.  What the pattern matching allows me to do is short circuit if it's an empty list, else, I'm splitting the head and the tail, and adding one to the length of the tail call with the tail of the list.  Let's look at another to concat a list of lists into a single list:

let listOfList = [[1;2;3;];[4;5;6;];[7;8;9]]

let rec concatList l =
  match l with
  | [] -> []
  | head :: tail -> head @ concatList tail

There is much more to cover here and I'll do that in subsequent posts.

Why Recursion?

Now that we covered some of the basics, it's time to ask the question why.  Why is recursion important and why use it?  Well, to answer that lightly, in order to walk such things as trees, directories, and so on, it's an absolute essential.  But, let's consider just a general functional programming question of why use it.

It's often the case that when people first start out with programming in F#, they are often in the imperative and OO mindset still.  That's ok since F# allows for this, but there are better ways to accomplish in the functional mindset.  Many times, people will port over their C# code directly to F# with the mutable variables or reference cells and leave an ugly mess.  Some of that can be solved with recursion.  Let's take a pretty naive example:

C#
public static void CountDown(int n)
{
    while(n > 0)
    {
        DoOperation();
        WaitSome();
        n -= 1;
    }
}

When translated directly to F# looks like this:
let countDown n =
  let mutable localN = n
  while localN > 0 do
    DoOperation()
    WaitSome()
    localN <- localN - 1

What we've had to do is use reference cells so that we could change the value of n directly.  From there, we have to use special operators to change and alias the value of n.  Not the prettiest code.  Not only that, but there is mutation galore, and I have to do extra work when creating a local iterating variable.  instead, we should focus on recursion and look at the problem slightly differently.

let rec countDown n =
    match n with
    | 0 -> 0
    | _ ->
      DoOperation()
      WaitSome()
      countDown (n - 1)

What this allows me to do is get rid of the local mutables, but also helps me break my problems into smaller, more similar problems which can be recursed.  This allows for better code reuse and maintenance I think.

Wrapping It Up

I'd like to spend some more time with tail recursion as I think it's pretty important.  As well, I'll also talk about how you can do the same in C# as well (with a little work of course).  But in the mean time, I hope I've demonstrated the simple act of recursion, when to look for it, and how to exploit it.  Not all problems are ready for recursion, but when you find the right opportunities for them, it's quite powerful.

Composite Application Guidance - What is it?

In the development of the Composite Application Guidance one area that we have labored intensely was around documentation. Documentation was so high on our priority list, that we deliberately reduced the number of bells and whistles in order to allow us to properly document what we had. As part of this we put in a significant effort to provide overview level information. We heard a lot of feedback from customers on the need for us to provide much more of the "Why" rather than the "What". Our hope when you see the documentation is that you feel we have provided enough background to understand what the guidance is and what problems it is solving. We equally want you to understand why we did what we did, how it benefits you, and when you should consider discarding out particular implementation.

Below is our overview topic on the guidance pulled straight from out docs. (Forgive the crappy formatting, I tried :) )

 

The goal of this topic is to provide you with a high-level overview of the Microsoft patterns & practices Composite Application Guidance for WPF (Windows Presentation Foundation) and the development challenges it addresses.

This topic describes some of the problems you might encounter when building complex WPF client applications, how the Composite Application Guidance helps you to address those problems, and how the Composite Application Guidance compares to alternative approaches.

Application Development Challenges

Typically, developers of client applications face a number of challenges. Most enterprise applications are sufficiently complex that they require more than one developer, maybe even a large team of developers that includes user interface (UI) designers and localizers in addition to developers. It can be a significant challenge to decide how to design the application so that multiple developers or sub-teams can work effectively on different pieces of the application independently, yet ensuring that the pieces come together seamlessly when integrated into the application.

In addition, application requirements can change over time. New business opportunities and challenges may present themselves, new technologies may become available, or even ongoing customer feedback during the development cycle may significantly affect the requirements of the application. Therefore, it is important to build the application so that it is flexible and can be easily modified or extended over time. Designing for maintainability can be hard to accomplish. It requires an architecture that allows individual parts of the application to be independently developed and tested and that can be modified or updated later, in isolation, without affecting the rest of the application.

Designing and building applications in a monolithic style can lead to an application that is very difficult and inefficient to maintain. In this case, "monolithic" refers to an application in which the components are very tightly coupled and there is no clear separation between them. Typically, applications designed and built this way suffer from a number of problems that make the developer's life hard. It is difficult to add new features to the system or replace existing features, it is difficult to resolve bugs without breaking other portions of the system, and it is difficult to test and deploy. Also, it impacts the ability of developers and designers to work efficiently together.

The Composite Approach

An effective remedy for these challenges is to partition the application into a number of discrete, loosely coupled, semi-independent components that can then be easily integrated together into an application "shell" to form a coherent solution. Applications designed and built this way are named composite applications.

Composite applications provide many benefits, including the following:

·         They allow modules to be individually developed, tested, and deployed by different individuals or sub-teams, allows them to be modified or extended with new functionality more easily, thereby allowing the application to be more easily extended and maintained.

·         They provide a common shell composed of UI components contributed from various modules that interact in a loosely coupled fashion. This reduces the contention that arises from multiple developers adding new functionality to the UI, and it promotes a common look and feel.

·         They promote re-use and a clean separation of concerns between the application's horizontal capabilities, such as logging and authentication, and the vertical capabilities, such as business functionality that is specific to your application.

·         They help maintain a separation of roles by allowing different individuals or sub-teams to focus on a specific task or piece of functionality according to their focus or expertise. In particular, it provides a cleaner separation between the user interface and the business logic of the application—this means the UI designer can focus on creating a richer user experience.

 

Composite applications are highly suited to a range of client application scenarios. For example, a composite application is ideal for creating a rich end-user experience over a number of disparate back-end systems. Figure 1 shows an example of this type of a composite application.

image

Figure 1

Composite application with multiple back-end systems

In this type of application, the user can be presented with a rich and flexible user experience that provides a task-oriented focus over functionality that spans multiple back-end systems, services, and data stores, where each is represented by one or more dedicated modules. The clean separation between the application logic and the user interface allows the application to provide a consistent and differentiated look and feel across all constituent modules.

Additionally, a composite application can be useful when there are independently evolving components in the UI that heavily integrate with each other and that are often maintained by separate teams. Figure 2 shows a screen shot of this type of application. Each of the areas highlighted represent independent components that are composed into the UI.

image

Figure 2

Stock Trader Reference Implementation composite application

In this case, the composite allows the application's user interface to be dynamic composed. This delivers a flexible user experience. For example, it can allow new functionality to be dynamically added to the application at run time, which enables rich end-user customization and extensibility.

Architectural Goals and Principles

The following table shows the architectural principles that have been prioritized by the Composite Application Guidance team's customer advisory board. These principles determine how guidance is developed and what the focus areas are.

Quality

Definition

Subsetability

This is the ability to adopt a portion of the Composite Application Library. You can choose only certain capabilities, incrementally adopt capabilities, and enable or disable features.

Learnability

This is the ability to quickly learn how to build WPF composite applications using the Composite Application Library. With small digestible and independent capabilities, you get started faster.

Extensibility

This is the ability to enhance, extend, or replace pieces of the framework without requiring you to redesign the framework or your application.

Compatibility

This means you can adopt the Composite Application Library for an existing application and you can use it with other existing infrastructure. Core services are swappable.

Simplicity

This means the Composite Application Library is designed in a minimalist way to reduce the amount of complexity. The Composite Application Library has just enough simplicity to get the job done.

Testability

The reference implementation in the Composite Application Guidance provides an implementation for Separated Presentation patterns. These patterns allow UI logic to be tested.

Performance

The Composite Application Library minimizes overhead while the application is running.

Scalability

The application can scale to support increased load.

Upgradeability

Existing WPF applications can be upgraded to use the Composite Application Library.

Adoption Experience

The Composite Application Guidance has an explicit goal to provide a good adoption experience. To deliver on this goal, the Composite Application Guidance provides the following:

·         You can "opt in" and "opt out" of the Composite Application Library capabilities. For example, you can consume the only services you need.

·         You can incrementally add the Composite Application Library capabilities to your existing WPF applications.

·         It is non-invasive because of the following:

       It limits the Composite Application Library footprint in the code.

       It limits reliance on custom Composite Application Library attributes. You can integrate existing libraries with the Composite Application Library through a design that favors composition over inheritance (this avoids forcing you to inherit from the classes in the Composite Application Library).

 

Concerns Not Addressed by the Composite Application Guidance

Please note that the Composite Application Guidance does not directly address the following:

·         Occasional connectivity

·         Messaging infrastructure, including the following:

       Client/server communication

       Asynchronous communication

       Encryption

·         Application performance

·         Authentication and authorization

·         Handling thread-safety from background updates, including the following:

       Data races

       Data synchronization

       Handling UI updates from multiple threads (the Composite Application Library addresses some aspects of this)

·         Versioning

·         Error handling and fault tolerance

 

For more information about these topics, see the following resources:

·         Smart Client Architecture and Design Guide

·         Occasionally Connected Systems Architecture: The Client

·         Occasionally Connected Systems Architecture: Concurrency

 

Considerations for Choosing the Composite Application Guidance

The Composite Application Guidance is for designing complex WPF applications. The scenarios where you should consider using the Composite Application Guidance include the following:

·         You are building a composite application that presents information from multiple sources through an integrated user interface.

·         You are developing, testing, and deploying modules independently of the other modules.

·         Your application is being developed by multiple collaborating teams.

If your applications do not require one or more of these scenarios, the Composite Application Guidance may not be right for you. The Composite Application Guidance requires you to have hands-on experience with WPF. If you need general information about WPF, see the following sources:

·         Windows Presentation Foundation on MSDN

·         Sells, Chris and Ian Griffiths. Programming WPF: Building Windows UI with Windows Presentation Foundation. Second Edition. O’Reilly Media, Inc., 2007.

·         Nathan, Adam. Windows Presentation Foundation Unleashed. Indianapolis, IN: Sams Publishing, 2006.

More Posts Next page »



What's New

  • re: Introducing psake

    Phew. I thought I was going to have to write one myself.
    Posted to James Kovacs (Weblog) by Anonymous on 07-04-2008
  • Kostenloses E-Book &laquo; Kostja&#8217;s .NETte Welt

    Pingback from Kostenloses E-Book &laquo; Kostja&#8217;s .NETte Welt
    Posted to Karl Seguin (Weblog) by Anonymous on 07-04-2008
  • re: The outlook calendar, iCalendar and RFC 2445

    Floating time is still not floating in Outlook 2007. I'm writing an app to enter flight information into a user's calendar, so most of the time the return leg originates in a different time zone to the outward leg. I have ways of working out the timezone and dst parameters for each airport which would allow me populate with UTC time or specify a VTIMEZONE...
    Posted to Peter's Gekko (Weblog) by Anonymous on 07-04-2008
  • record from dvd

    About this entry Published: 2. 12. 08/ 11pm Category: life , personal , photography , spirituality , thoughts Tags: No comments Jump to comment form comments rss[?] trackback uri[?]
    Posted to Mark DiGiovanni (Weblog) by Anonymous on 07-04-2008
  • re: Get Your Func On

    Good call Todd. I think I like Func<T> ifNull or something simpler. I originally named it block, influenced by rails, tried to pick a more NETish name, but I agree callback is still vague..makes it sound like Get is asynchronous or something...
    Posted to Karl Seguin (Weblog) by karl on 07-04-2008
  • re: Showing some support for LINQ to SQL

    @Simon Sure let's have bumper stickers and T-Shirts to wear at conferences ;-)
    Posted to Ian Cooper [MVP] (Weblog) by Ian Cooper on 07-04-2008
  • re: Showing some support for LINQ to SQL

    Excellent post, surely points out the biased opinions even without using linq to sql. Data Team seems to promote EF heavily ( blogs.msdn.com/.../why-use-the-entity-framework.aspx ) and seeming ready to face very accurate and tough challenges about the limitations of it, but they don't promote what they have, that's insane. Also some additional points...
    Posted to Ian Cooper [MVP] (Weblog) by Anonymous on 07-04-2008
  • decrypter for dvd

    One thing that people in internet publishing need to watch is Google and it’ s interest in the world of mobile technology. Google recently purchased Jaiku. Jaiku is a social platform very similar to Twitter, but even more focused on the cell phones. Google
    Posted to Mark DiGiovanni (Weblog) by Anonymous on 07-04-2008
  • re: Showing some support for LINQ to SQL

    Ian your series and earlier posts on PI with L2S was terrific and I echo your sentiments LOUDLY here. Recently Greg Young created a bumper sticker with the text "I want Spec #", hoping that people would promote the idea on their site and help get the message out. I would gladly include such an image on my blog that conveys our wish for L2S...
    Posted to Ian Cooper [MVP] (Weblog) by Anonymous on 07-04-2008
  • re: Change a database connection string from code

    i have tried doing that instructions one by one i have got the connection string, vb does not return error code but the connection state always return "0" zero which meant not connected or no connection was established. i have search vbcode website and found nothing that really worked, may i request from any one that has a code version of...
    Posted to Peter's Gekko (Weblog) by Anonymous on 07-04-2008

CodeBetter.Com Blogs

Karl Seguin
122 Posts | 1,083 Comments | 289 Trackbacks
Glenn Block
43 Posts | 138 Comments | 81 Trackbacks
Matthew Podwysocki
30 Posts | 85 Comments | 74 Trackbacks
Peter's Gekko
536 Posts | 2,309 Comments | 578 Trackbacks
Ian Cooper [MVP]
31 Posts | 153 Comments | 119 Trackbacks
David Hayden [MVP C#]
281 Posts | 757 Comments | 570 Trackbacks
Jeremy D. Miller -- The Shade Tree Developer
544 Posts | 3,993 Comments | 1,781 Trackbacks
Aaron Jensen
10 Posts | 32 Comments | 18 Trackbacks
Kyle Baley - The Coding Hillbilly
83 Posts | 448 Comments | 143 Trackbacks
Greg Young [MVP]
92 Posts | 533 Comments | 240 Trackbacks
James Kovacs
33 Posts | 105 Comments | 28 Trackbacks
Patrick Smacchia [MVP C#]
55 Posts | 227 Comments | 263 Trackbacks
Dave Laribee
53 Posts | 345 Comments | 114 Trackbacks
Jeff Lynch [MVP]
226 Posts | 486 Comments | 99 Trackbacks
Jeffrey Palermo [MVP]
652 Posts | 2,475 Comments | 620 Trackbacks
Rod Paddock
37 Posts | 142 Comments | 40 Trackbacks
Jacob Lewallen
5 Posts | 40 Comments | 6 Trackbacks
Steve Hebert's Development Blog
309 Posts | 540 Comments | 95 Trackbacks
Raymond Lewallen
298 Posts | 1,917 Comments | 341 Trackbacks

Other Blogs

CodeBetter.Com Events
3 Posts | 0 Comments | 13 Trackbacks
CodeBetter.Com Link Blog
178 Posts | 9 Comments | 2 Trackbacks
All About Products
2 Posts | 4 Comments | 2 Trackbacks
Featured Articles
1 Posts | 4 Comments | 1 Trackbacks

CodeBetter.Com Alumni

Jean-Paul S. Boodhoo
136 Posts | 453 Comments | 131 Trackbacks
Don Demsak
5 Posts | 14 Comments | 1 Trackbacks
Jay Kimble -- The Dev Theologian
423 Posts | 1,431 Comments | 167 Trackbacks
Eric Wise
290 Posts | 1,480 Comments | 208 Trackbacks
Brian Peek [MVP C#]
15 Posts | 15 Comments | 3 Trackbacks
Mark DiGiovanni
88 Posts | 322 Comments | 36 Trackbacks
Paul Laudeman
113 Posts | 231 Comments | 22 Trackbacks
Ben Reichelt's Weblog
172 Posts | 514 Comments | 70 Trackbacks
Ranjan Sakalley
41 Posts | 272 Comments | 6 Trackbacks
Public Class GeoffAppleby
300 Posts | 1,943 Comments | 108 Trackbacks
DonXML - Live From PDC
3 Posts | 4 Comments | 3 Trackbacks
Grant Killian's Blog
171 Posts | 473 Comments | 8 Trackbacks

CodeBetter.Com Emeritus

Darrell Norton's Blog [MVP]
724 Posts | 2,380 Comments | 328 Trackbacks
Brendan Tompkins [MVP]
405 Posts | 2,715 Comments | 345 Trackbacks