April 2009 - Posts

Explain from the Questioner’s perspective, not your own

I was involved in an interesting discussion about how the C# language has evolved, and how it’s getting harder and harder to teach developers to be proficient in the language with each passing version.

I think that’s our fault.

As leaders and experienced C# developers, we too often teach and explain from our perspective: We learned C# 1.0, learned the new features in 2.0. Then, we learned LINQ and the other syntax additions in 3.0. Now, we’re looking at adding the new 4.0 features to our repertoire of techniques. It makes sense to us, because that’s how we learned.

But we are not them.

That’s an inefficient way for someone approaching C# now to learn the language. Instead, we should explain these new concepts based on how one should learn now, not how we learned. I wish I could take credit for this amazing insight, but I must credit Bjarne Stroustrup. He wrote an essay for C++ Users Journal back in 1999 asserting that the C++ community must change how they taught developers C++.  Back then, everyone teaching C++ just assumed that every novice C++ developer was a veteran C developer. And that’s how they taught. Stroustrup instead claimed that developers should learn the best C++ idioms, rather than be taught C, then how to move to C++.

Lambda Expressions as Example

Explaining Lambda expressions is a great example of what I mean in C# today.

When I explain lambda expressions to a novice C# developer, I use this example:

   1: var someNumbers = new List<int>(Enumerable.Range(-20, 200));
   2: someNumbers.RemoveAll(n => n > 30);
   3:  
   4: bool assertion = someNumbers.TrueForAll(n => n < 40);

Line 1 creates a collection with a bunch of numbers.

Line 2 introduces a lambda. It removes all numbers greater than 30 from the collection. The lambda expression “n => n > 30” describes the condition for all elements to be removed from the list. A lambda expression is a short hand description of a method: n is the parameter. The expression returns a boolean, the result of the test ‘n > 30’.

At this point, I’ll often get a few questions:

‘what type is n"?’

That’s easy: the compiler infers types for the parameters to lambda expressions. Here, the compiler infers that n must be integer, because the collection someNumbers contains integers.

‘there’s no return value’

Yes, I know that’s not a question. But it does express the confusion, and that’s how it’s often stated. I say that the compiler infers the return type. List.RemoveAll() takes a Predicate<T> as its parameter, and Predicate<T> returns a bool. therefore, the expression ‘n > 30’ must be a boolean expression. To illustrate this, I’ll modify the code to show how the compiler checks the type. The lambda expression ‘n => n.ToString()’ doesn’t compile, because n.ToString() evaluates to a string, not a boolean.

Then, I go on to the concept: a lambda expression is a mechanism that enables you to pass code (in the form of a lambda) to another method for execution later. Internally, List.RemoveAll() evaluates the lambda expression parameter for every element in the list. All elements that return true are removed.

I follow the same process to explain the TrueForAll() method call.

Yeah, but what about delegates, anonymous delegates and expression trees?

Those of you that are experienced C# developers are probably concerned: I didn’t mention that lambdas are implemented like anonymous delegates. I didn’t drill down further to state that anonymous delegates are just like delegates.

In short, I didn’t work back from a lambda expression to the equivalent C# 1.0 syntax. But, that’s the point. Unless you have been working with C# since the beginning, those concepts don’t help you. Someone starting to learn C# now doesn’t have that prior knowledge about C# 1.0, or C# 2.0.

Read my explanations above again.  They don’t dive into great detail about how a lambda expression is interpreted by the compiler. Rather, they give you a good description of how you would write code using lambda expressions, and what they do for you.

Nothing I said is wrong, but a lot of details are left out.  That’s ok, hiding details helps novices get started.  We can fill in those holes as these new C# developers develop a greater understanding, and want a deeper understanding.

At that point, they are ready for a different explanation.

Until then, we are better off explaining concepts using explanations that help them, even if those explanations are different than how we learned.

Live Framework and custom resource types

I’ll start this post with a couple caveats. I’m learning the Live Framework SDK, just everyone else. This (and upcoming) blog posts on the Live Framework are based on my initial learning on Live Framework. All the usual disclaimers apply.

My plan is to work through some of the Live Framework SDK samples. As I’m doing that, my normal work pattern is to take lots of notes on what I’m learning. My blog seems as good a place as any. Unlike posts on technologies where I’ve spent lots of time, I’m a noob on the Live Framework too. But, there’s only one way to learn.

The Project Manager Sample

I decided to start with the WPF Project Manager sample. It’s a WPF application that lets you create projects. You can add milestones to those projects. Obviously, you can edit both projects and milestones. The projects are stored as MeshObjects. The milestones are stored as DataEntries in the MeshObjects (representing projects).

This first post is mostly looking at the application, with a small look at the code.

I ran the code, created a project and some milestones.  Cool enough.

Then, I went to the developer mesh website, and looked at my mesh desktop. I expected to see new folders, or something that showed the projects and milestones I created. I was surprised that nothing was there.

The answer was in the code. Remember from my first post on the Live Framework that the MyPhotos application used resource types of LiveMeshFolder, and LiveMeshFiles. That makes objects that are visible in the mesh, obviously as folders and files.

This sample uses different resources types. The sample defines a “Project” resource type for the project, and a “Milestone” type for the milestones.

Both Project and Milestone are C# classes. They are (more or less) POCO objects. They are decorated with the DataContract attribute (and their properties are decorated with the DataMember attribute).

Here’s the Project type:

   1: [DataContract(Namespace = "Microsoft.Samples.Workflow.ProjectManagerWPF")]
   2: public class Project
   3: {
   4:     /// <summary>
   5:     /// UUID of the parent MeshObject
   6:     /// </summary>
   7:     [DataMember]
   8:     public string MOID { get; set; }
   9:     /// <summary>
  10:     /// Title of the milestone (during save/update, this matches MeshObject.Resource.Title, 
  11:     /// but is stored here when the custom object is databound instead of the resource)
  12:     /// </summary>
  13:     [DataMember]
  14:     public string Title { get; set; }
  15:     /// <summary>
  16:     /// Date when project will be started
  17:     /// </summary>
  18:     [DataMember]
  19:     public DateTime KickOffDate {get; set;}
  20:     /// <summary>
  21:     /// Estimated Date for Completion
  22:     /// </summary>
  23:     [DataMember]
  24:     public DateTime CompletionDate {get; set;}
  25:     /// <summary>
  26:     /// Date when project was shipped
  27:     /// </summary>
  28:     [DataMember]
  29:     public DateTime ShippedDate {get; set;}
  30:     /// <summary>
  31:     /// Description of Project
  32:     /// </summary>
  33:     [DataMember]
  34:     public string Description {get; set;}
  35: }

Storing and retrieving the Project type from the Mesh is straightforward Live Framework code. Here’s the code to read a project:

 

   1: //grab the Project Instance object from the mesh object and populate an instance of our Project Domain Class
   2: Library.Project SaveProject = this.ExistingProjectMeshObject.Resource.GetUserData<Library.Project>();

You simply convert the Resource to the POCO type, using the GetUserData<T> method to convert the resource. Cool. Saving it back is just as easy:

   1: MO = ExistingProjectMeshObject;
   2: SaveProject = ExistingProjectMeshObject.Resource.GetUserData<Library.Project>();
   3: MO.Resource.Title = tbTitle.Text;
   4:  
   5: //Set the custom attributes of the mesh object to the values from the library/domain class, 
   6: //this will popualte the userfield data with the deserialized content from the Project object created above
   7: MO.Resource.SetUserData<Library.Project>(SaveProject);
   8:  
   9: //Set the type of the mesh object's resource to PRoject
  10: MO.Resource.Type = "Project";
  11:  
  12: //Update the object in the cloud.
  13: MO.Update();

The SetUserData<T> call converts the POCO Project object to a mesh resource. Then, you just need to send the data to the cloud.

Future posts will dive into the code in more detail, and start on some other mesh style programming. Just this little dive makes me think more about what I can build with this.

Search

Go

Blog Group Links

Nascar style badges