Archive for September, 2009

The 7 Software Development Wastes – Lean series Part 7 – Defects

Introduction

When one looks at all the wastes, defects has to be the most obvious one. The cost and repercussions of finding defects varies depending on where in the cycle they're found. Defects found early on in the development life-cycle are way less costly to resolve than defects found later on in the cycle; the most expensive being when applications are already in-production.

Additionally, depending on when the defects are found, defects can and do trigger other wastes like task switching, relearning etc.

Defects can be very costly for an organization. So the trick with defects is that you need to 1) Prevent them from happening in the first place and 2) Find and fix them as early in the development life-cycle as possible.

So what can you do to prevent them from happening in the first place?

  1. Keep your stories small, and unambiguous.
  2. Ensure that each story has well defined acceptance test criteria (assisted by input from the customer).
  3. Ensure that your code is well tested. Adopting good Test Driven Development habits will pay back in spades.
  4. Pair programming and code reviews are excellent ways in which to prevent bugs from being created in the first place.
  5. The more you automate the better. So automated functional testing is a good way to automate the functional test plan and get results fast and to ensure that new code changes aren't breaking other parts of the code.
  6. Ensure staging environments mimic production as closely as possible.
  7. Make sure that as you find new defects, you add unit tests to your test suite to keep your unit testing current.
  8. Finally, document your code well.

An interesting quote from Mary and Tom Poppendieck's book called Implementing Lean Software Development,

"If software routinely enters final verification with defects, then it is being produced by a defective process"

.... which needs to be fixed. So...

Step 1. Prevent the bugs from happening in the first place by "mistake proofing" your code
Step 2. Do whatever you can to find the bugs early on in the process while the code is fresh in the developers minds - i.e. ensure you have good functional test plans and test tools.
Step 3. Ensure a proper staging (or test environment) that mimics production environment as closely as possible
Step 4. Get the software into the hands of customers as quickly as possible, so good Agile practices help here.
Step 5. If you find defects, ensure they never happen again by keeping your unit tests current.


Syndicated via RSS From: http://agilesoftwaredevelopment.com

Automatically Implemented Properties

Automatically implemented properties offer a concise syntax for implementing property accessors that get and set a private field. They create a field backed property without requiring you to actually create a field. The compiler automatically generates it for you at compile time. They can be used only for simple get and set of properties because there is no body and no field. No property body means no breakpoints or validation logic can be used. No field means no default value. Typing “prop [tab][tab]” is the Visual Studio code snippet for producing an automatically implemented property. This can make your code much more concise. A classic example of a field back property might look something like the code below.

private int myProperty = 0;
public int MyProperty
{
   get { return this.myProperty; }
   set { this.myProperty = value; }
}

A simpler example that uses automatically implemented properties for the same field is below.

public int MyProperty
{
   get; set;
}

However, it is important not to be too lazy and use this haphazardly. Examine the code below where you define a Customer class. Take note of the CustomerKey property that is defined. Typically, such a key field is a readonly item that is set once and doesn’t change. When taking a shortcut using automatically implemented properties, it allows for undesired behavior with the code.

class Customer
{
   public string CustomerKey { get; set; }
   public string ContactName { get; set; }
   public string City { get; set; }
}

You might try refactoring the code to have a private set and use a constructor to control the value. Although this does protect the field from the outside, it could still be altered internally to the class.

class Customer
{
   public Customer(string customerKey)
   {
      CustomerKey = customerKey;
   }

   public string CustomerKey { get; private set; }
   public string ContactName { get; set; }
   public string City { get; set; }
}

In reality, an automatically implemented property probably isn’t appropriate for the CustomerKey property and the code should look like the example below. The class in question in this example is pretty simple, but it illustrates the point that the automatically implemented properties should be applied liberally, but with caution.

class Customer
{
   public Customer(string customerKey)
   {
      this.CustomerKey = customerKey;
   }
   private readonly string customerKey;
   public string CustomerKey
   {
      get return this.customerKey;
   }

   public string ContactName { get; set; }
   public string City { get; set; }
}

Joining a Network

If you want to connect to a network during Setup, you must have the correct hardware installed on your computer and be connected to your network.

If you will be using a network, first determine whether your computer is joining a domain or a workgroup.

If you’re not sure, select Workgroup when you are prompted during Setup. (You can always join a domain later, after Windows XP Professional is installed.) Any computer user can join a workgroup—you don’t need special administrative permissions. You must provide an existing or new workgroup name, or you can use the workgroup name that Windows XP Professional suggests during Setup.

If you select Domain ask your network administrator to create a new computer account in that domain or to reset your existing account. Joining a domain requires permission from the network administrator.

Joining a domain during Setup requires a computer account to identify your computer to the domain you want to join. If you’re upgrading, Setup uses your existing computer account; or if there isn’t one, Setup prompts you to provide a new computer account. Ask your network administrator to create a computer account before you begin Setup. Or, if you have the appropriate privileges, you can create the account yourself and join the domain during Setup. To join a domain during Setup, you need to provide your domain user name and password.

Unless you’re an advanced user, it’s recommended you use the default settings.

Dual Boot XP

A computer can be configured to let you choose between two or more operating systems each time you restart the computer. With multibooting, you can choose which operating system to run or specify a default OS if no selection is made during the restart process.

Computers Containing Multiple Windows 2000 or Windows XP Partitions
Before installing Windows 2000 and Windows XP on the same machine, you need to prepare your system with different partitions (a process that divides a hard disk into separate sections that can be formatted for use by a file system. Partitions typically have different drive letters such as C or D).
One OS per partition
It’s important to install each operating system on a different partition and install the applications used with each operating system on the same partition as the OS. If an application is used with two different operating systems, install it on two partitions. Placing each operating system in a separate partition ensures that it will not overwrite crucial files used by the other OS.

Install Latest OS Last
In general, you should install the most recent OS last—after you have installed all other operating systems on the target computer. In this case, you should install Windows 2000 and then install Windows XP.

Unique Computer Name
You can set up a computer so that it has multiple installations of Windows XP on multiple partitions. However, you must use a different computer name for each installation if the computer participates in a Windows 2000 Server domain. Because a unique security identifier (SID) is used for each installation of Windows XP on a domain, the computer name for each installation must be unique—even for multiple installations on the same computer.

Checklist Summary
To configure a computer containing Windows 2000 and Windows XP, review the following guidelines:

Install each operating system on a separate drive or disk partition.
Install Windows XP after you have installed Windows 2000.
When you perform a new installation of Windows XP (as opposed to an upgrade), by default, the installation is placed on a partition on which no other operating system is located. You can specify a different partition during Setup.
Don’t install Windows XP on a compressed drive unless the drive was compressed with the NTFS file system compression feature.
On any partition where you perform a new installation of Windows XP (as opposed to an upgrade), you will need to re-install any programs, such as word processing or e-mail software, after Setup is complete.
Install the programs used by each operating system on the partition with that system. If you want your programs to run with multiple operating systems, you need to install separate copies of the programs in each of the operating system partitions.
If the computer is on a Windows 2000 Server domain, each installation of Windows XP on that computer must have a different computer name.

Computers Containing Windows NT 4.0 and Windows XP
Setting up a computer to run Windows XP as well as an earlier operating system such as Windows NT Workstation 4.0 requires addressing compatibility issues among different file systems: NTFS, FAT, and FAT32.

Normally, NTFS is the recommended file system because it supports important features, including the Active Directory™ service and domain-based security. However, using NTFS as the only file system on a computer that contains both Windows XP and Windows NT is not recommended. On these computers, a FAT or FAT32 partition containing the Windows NT 4.0 operating system ensures that when started with Windows NT 4.0, the computer will have access to needed files. In addition, if Windows NT is not installed on the system partition, which is almost always the first partition on the disk, it is recommended that the system partition also be formatted with FAT. This is because earlier operating systems, with one exception, can’t access a partition if it uses the latest version of NTFS. The one exception is Windows NT version 4.0 with Service Pack 4 or later, which has access to partitions with the latest version of NTFS, but with some limitations.

Even the latest Service Pack does not provide access to files using the new features in NTFS. Windows NT 4.0 cannot access files that have been stored using NTFS features that did not exist when Windows NT 4.0 was released. For example, a file that uses the new encryption feature won’t be readable when the computer is started with Windows NT 4.0 Workstation, which was released before the encryption feature existed.

Note: If you set up a computer so that it starts with Windows NT 3.51 or earlier on a FAT partition, and Windows XP on an NTFS partition, when that computer starts with Windows NT 3.51, the NTFS partition will not be visible.

Checklist Summary
To configure a computer containing Windows NT 4.0 and Windows XP, review the following guidelines:

As explained above, using NTFS as the only file system on a computer containing both Windows XP and Windows NT is not recommended.
Make sure that Windows NT 4.0 has been updated with the latest released Service Pack available for download before installing Windows XP.
Install each operating system on a separate drive or disk partition.
When you perform a new installation of Windows XP (as opposed to an upgrade), by default, the installation is placed on a partition on which no other operating system is located. You can specify a different partition during Setup.
Don’t install Windows XP on a compressed drive unless the drive was compressed with the NTFS file system compression feature.
On any partition where you perform a new installation of Windows XP (as opposed to an upgrade), you will need to re-install any programs, such as word processing or email software, after Setup is complete.
Install the programs used by each operating system on the partition with that system. If you want your programs to run with multiple operating systems, you need to install separate copies of the programs in each of the operating system partitions.
If the computer is on a Windows NT Server or Windows 2000 Server domain, each installation of Windows XP on that computer must have a different computer name.

Computers Containing MS-DOS or Windows 9x and Windows XP
As explained above you need to address file system compatibility to ensure a multibooting configuration with these earlier operating systems and Windows XP. Remember to install the latest operating system last otherwise important files may be overwritten.

Checklist Summary
To configure a computer containing Windows XP and Windows 9x or MS-DOS, review the following guidelines:

On computers that contain MS-DOS and Windows XP:

MS-DOS must be installed on a basic disk on a partition formatted with FAT. If MS-DOS is not installed on the system partition, which is almost always the first partition on the disk, the system partition must also be formatted with FAT.
Windows XP must be installed last. Otherwise important files needed for starting Windows XP could be overwritten.
On computers that contain Windows 95 and Windows XP:

As in the case above, Windows 95 must be installed on a basic disk on a partition formatted with FAT. (For Windows 95 OSR2, FAT32 may be used.) If Windows 95 is not installed on the system partition, which is almost always the first partition on the disk, the system partition must also be formatted with FAT (or FAT32 for Windows 95 OSR2).
Compressed DriveSpace or DoubleSpace volumes won’t be available while you are running Windows XP. It is not necessary to uncompress DriveSpace or DoubleSpace volumes that you will access only with Windows 95.
Windows XP must be installed last. Otherwise important files needed for starting Windows XP could be overwritten.
On computers that contain Windows 98 (or Windows ME) and Windows XP:

As in the cases above, Windows 98 or Windows Millennium Edition (ME) must be installed on a basic disk on a partition formatted with FAT or FAT32. If Windows 98 or Windows ME is not installed on the system partition, which is almost always the first partition on the disk, the system partition must also be formatted with FAT or FAT32.
Compressed DriveSpace or DoubleSpace volumes won’t be available while you are running Windows XP. It is not necessary to uncompress DriveSpace or DoubleSpace volumes that you will access only with Windows 98.
Windows XP must be installed last. Otherwise important files needed for starting Windows XP could be overwritten.

Installation and How to :

The order of installation is critical if you want a successful multiboot installation. In general terms, install non–Microsoft operating systems and earlier versions of the Windows operating system first. This would mean installing UNIX or Linux operating systems first; then Windows 95 or Windows 98 or Windows Me; then Windows NT; and finally, Windows 2000 and/or Windows XP. (In the unlikely event that you’re installing MS–DOS, you can install that either before or after UNIX– or Linux–based operating systems, and generally I’d opt for before.) It’s also important to understand that, without using a third–party product to help out, you can’t install non-Microsoft operating systems, or Windows 95 and Windows 98 on the same computer, and that you can install only a single version of Windows95/98/Me. But you can install as many different versions of Windows NT and later versions of the Windows operating system as you have available logical drives, with the sole caveat that you must install all Windows NT versions before you install any Windows 2000 or Windows XP versions.

Let’s take a typical installation. Our target computer must be able to boot into Windows 98, Windows NT 4 Workstation, Windows 2000 Professional, and Windows XP Professional. We have a 2–GB partition to hold our programs and the whole thing must fit on a single 10–GB hard drive. No problem. First, we partition the hard drive into two partitions: a 2–GB primary partition, and an 8-GB extended partition using FDisk. In the extended partition, we’ll create four logical volumes—D, E, F and G—to hold our remaining operating systems and our programs.

After the disk is partitioned, format the primary partition using the FAT16 file system and install Windows 98 on it. So far so good. Now, format your D drive with FAT16 as well. Eventually, you’ll install your programs on D drive.

Next, install Windows NT 4 Workstation. You will install this on any of the logical volumes not already used (either E drive, F drive or G drive) and choose NTFS as your file system. Leave D drive alone, because your applications go there where they’re visible to all operating systems. When you install Windows NT, it recognizes that you already have Windows 98 on the computer. Then it automatically sets up for dual booting between Windows 98 and Windows NT by creating a boot.ini file, which creates a menu of available operating systems. After you have Windows NT 4 installed, immediately apply Service Pack 6, before you install Windows 2000.

Finally, install Windows 2000 and Windows XP, each in its own logical volume. Again, choose NTFS as the file system. As you install them, they are automatically added to the boot.ini file on your C drive, which lets you choose operating systems at start up.

Using Remote Desktop

You must first enable the Remote Desktop feature on your office computer so that you can control it remotely from another computer. You must be logged on as an administrator or a member of the Administrators group to enable Remote Desktop on your Windows XP Professional-based computer.

To setup your office computer to use Remote Desktop:

Open the System folder in Control Panel. Click Start, point to Settings, click Control Panel, and then double-click the System icon.

On the Remote tab, select the Allow users to connect remotely to this computer check box, as shown below.

Ensure that you have the proper permissions to connect to your computer remotely, and click OK.

Leave your computer running and connected to the company network with Internet access. Lock your computer, and leave your office.

The Remote Desktop Connection client software allows a computer running Windows 95, Windows 98, Windows 98 Second Edition, Windows Me, Windows NT 4.0 or Windows 2000 to control your Windows XP Professional computer remotely. The client software is available on the installation CD for Windows XP Professional and Windows XP Home Edition. The client software is installed by default on computers running Windows XP Professional and Windows XP Home Edition.

To install Remote Desktop Connection software on a client computer

Insert the Windows XP compact disc into your CD-ROM drive.

When the Welcome page appears, click Perform additional tasks, and then click Setup Remote Desktop Connection as shown below.

When the installation wizard starts, follow the directions that appear on your screen.

Once you have enabled your Windows XP Professional computer to allow remote connections, and installed client software on a Windows-based client computer, you are ready to start a Remote Desktop session.

To create a new Remote Desktop Connection

Open Remote Desktop Connection. (Click Start, point to Programs or All Programs, point to Accessories, point to Communications, and then click Remote Desktop Connection.)

In Computer, type the computer name for your computer running Windows XP Professional that has Remote Desktop enabled and for which you have Remote Desktop permissions

Click Connect.

The Log On to Windows dialog box appears.

In the Log On to Windows dialog box, type your user name, password, and domain (if required), and then click OK. The Remote Desktop window will open and you will see the desktop settings, files, and programs that are on your office computer. Your office computer will remain locked.

Nobody will be able to work at your office computer without a password, nor will anyone see the work you are doing on your office computer remotely. Note: To change your connection settings, (such as screen size, automatic logon information, and performance options), click Options before you connect.

To open a saved connection

In Windows Explorer, open the My DocumentsRemote Desktops folder.

Click the .Rdp file for the connection you want to open. Note: A Remote Desktop file (.rdp) file contains all of the information for a connection to a remote computer, including the Options settings that were configured when the file was saved. You can customize any number of .rdp files, including files for connecting to the same computer with different settings. For example, you can save a file that connects to MyComputer in full screen mode and another file that connects to the same computer in 800×600 screen size. By default, .rdp files are saved in the My DocumentsRemote Desktops folder. To edit an .rdp file and change the connections settings it contains, right-click the file and then click Edit.

To log off and end the session

In the Remote Desktop Connection window, click Start, and then click Shut Down.

The Shut Down Windows dialog box appears.

In the drop-down menu, select Log Off , and then click OK.

Photos from AgileEE 2009 in Kev, Ukraine

Few days ago I was honored to speak about Agile Planning on Agile Eastern Europe conference that happened in Kiev on 18th and 19th of September. I promised many people to share the conference photos, so here is a slideshow. I also added some pictures of the Kiev and its people to help you feel the atmosphere and showcase my great photo talent If you prefer looking at photos one by one, you can find them in this flickr collection.

I hope you'll like the pictures.
Enjoy!
<!--break-->


Syndicated via RSS From: http://agilesoftwaredevelopment.com

Documentation Driven Development!

So I was having lunch with our Programmer Writer, Tamra Myers the other day, and we got onto the conversation of documentation. I’m a huge Huge HUGE fan of documentation, in fact, when I coded in anger, I was known for my extensive, well written, downright Elizabethan doco.

I was then having lunch with Simon Guest on a different day and we got onto the topic of doco too, in fact, we were talking about some research he had done into how much of MSDN doco actually had code samples! You might start seeing a trend emerge… yes, I love to eat lunch with passionate doco people!

So what has this got to do with the price of Tzatziki in Redmond? Well, we all strive (in software engineering anyway) to build technology that people can use, or at least, work out how to use. If you build software, especially developer platform software, it’s not always easy to build highly intuitive APIs and components. So what’s left is the doco. The doco is the first port of call for the user of developer goo, in there, they can orientate themselves around the nuances and intricacies of a component and the bend it to their will. However, if you don’t provide doco, well then, you’re putting the developer user in a world of pain, and forcing them to make a choice. They can either try and hack away, using coincidental discovery to work out how your thing works, or try and find a blog post from someone who has. If they choose the former, they could waste a bunch of time and never hit paydirt, if the they choose the latter, there is always the chance that the code they are using is not optimal, or inline with the way the component/API was designed.

So why is there such poor doco? Well first of all, the engineering process if fundamentally broken. It starts with requirements, then specs, then code, then test, then release, then somewhere along the way, doco. Now, it’s like running a marathon, they always tell you to stretch and cool down afterwards, but for most of us, when you hit the finish line, you just want to pass out. Coding is the same, when you’ve squashed that last bug, and checked in your final build, the last thing you want to do is write your coding memoirs. However, herein lies the travesty! Because most of us don’t summon the last drops of energy to write good doco, all our hard work is wasted because know one knows where to find the secret red button that can transport us through space and time. Instead they are left to prod around the facade and try and find the switch.

How do you solve the problem? Start with doco first! Just like the industry realized that by putting testing after development, you’re putting the cart before the horse, putting doco before testing makes sure you stay true to what the customer is meant to have and what it’s meant to do. And more important, you can see how easy or usable your stuff is before you code it. I mean, how many of us have written a component, then given it to someone, had them ask us for a quick sample, then as you develop the sample you realize, “Damn, this is hard to use” or “I could have added a method that would have reduced this from 10 lines to 2 lines of code”? By starting with how should someone use the component, what it does, what are the inputs/outputs, exceptions, expected behavior, you have more than just the functional spec to work against. And, most importantly, when you’re ready to release, you have the best doco on earth, better than the code! To the customer anyway ;)

By the way, if you want to read more on this topic, check out the following paper:

Now go forth and doco!

Technorati Tags:

Syndicated via RSS From: http://blogs.msdn.com/b/davidlem/

The dirty secret of pair programming

Pair programming is one of the more controversial extreme programming practices. Having two people work on the same piece of code at the same time looks very unpractical and inefficient to someone not familiar with this practice. Pair programming proponents like me are usually quick to point out the benefits like improved quality, less rework, better communication and better knowledge sharing within teams but I think the biggest reason pair programming works is usually kept quiet.
<!--break-->
People work harder when there is someone looking over their shoulder.

I'm going to be completely honest with you here. When I work alone I spend a considerable amount of time surfing the web, reading email, twittering (you can follow me at @mendelt) getting coffee and talking to coworkers. This means I'm spending less time working but it also means I'm constantly interrupting myself during the time I am doing work making me even less productive.

Now we don't tell our managers this because it wouldn't do anyone much good, the problem is a bit more complex than just people slacking off. What I've observed is most people have a hard time pacing themselves. We do really focused work for five minutes and then take a break. Unfortunately breaks have a habit of taking more time than they should and productivity goes out the window.

To solve this problem we need a way to maintain a sustainable pace. Pair programming is a way to do just this. Forcing yourself to explain what you do to your pair is a great way to maintain a sustainable pace and work a bit harder.


Syndicated via RSS From: http://agilesoftwaredevelopment.com

Generating Dynamic Methods with Expression Trees in Visual Studio 2010

Expression trees first appeared in Visual Studio 2008, where they were mainly used by LINQ providers. You can use expression trees to represent code in a tree-like format, where each node is an expression. You can also convert expression trees into compiled code and run it. This transformation enables dynamic modification of executable code as well as the execution of LINQ queries in various databases and the creation of dynamic queries. Expression trees in Visual Studio 2008 are explained in Charlie Calvert’s blog post Expression Tree Basics.

In this post I’m going to show how expression trees were extended in Visual Studio 2010 and how you can use them to generate dynamic methods (a problem that previously could be solved only by emitting MSIL). But although I strongly recommend reading Charlie’s blog post first, I still need to repeat some basics to spell out certain nuances.

Creating Expression Trees

The easiest way to generate an expression tree is to create an instance of the Expression<T> type, where T is a delegate type, and assign a lambda expression to this instance. Let’s take a look at the code.

// Creating an expression tree by providing a lambda expression.< ?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Expression<Action<int>> printExpr = (arg) => Console.WriteLine(arg);

 

// Compiling and invoking the expression tree.

printExpr.Compile()(10);

// Prints 10.

In this example, the C# compiler generates the expression tree from the provided lambda expression. Note that if you use Action<int> instead of Expression<Action<int>> as a type of the printExpr object, no expression tree will be created, because delegates are not converted into expression trees.

However, this is not the only way to create an expression tree. You can also use classes and methods from the System.LINQ.Expressions namespace. For example, you can create the same expression tree by using the following code.

// Creating a parameter for the expression tree.

ParameterExpression param = Expression.Parameter(typeof(int), "arg");

 

// Creating an expression for the method call and specifying its parameter.

MethodCallExpression methodCall = Expression.Call(

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }),

param

);

 

// Compiling and invoking the methodCall expression.

Expression.Lambda<Action<int>>(

methodCall,

new ParameterExpression[] { param }

).Compile()(10);

// Also prints 10.

Of course this looks much more complicated, but this is what actually happens when you supply a lambda expression to an expression tree.

Expression Trees vs. Lambda Expressions

A common misconception is that expression trees are identical to lambda expressions. This is not true. On the one hand, as I have already shown, you can create and modify expression trees by using API methods, without using lambda expression syntax at all. On the other hand, not every lambda expression can be implicitly converted into an expression tree. For example, multiline lambdas (also called statement lambdas) cannot be implicitly converted into expression trees.

// You can use multiline lambdas in delegates.

Action<int> printTwoLines = (arg) =>

{

Console.WriteLine("Print arg:");

Console.WriteLine(arg);

};

 

// But in expression trees this generates a compiler error.

Expression<Action<int>> printTwoLinesExpr = (arg) =>

{

Console.WriteLine("Print arg:");

Console.WriteLine(arg);

};

Expression Trees in Visual Studio 2010

All the code examples I have shown so far work (or don’t work) the same in both Visual Studio 2008 and Visual Studio 2010. Now let’s move to C# 4.0 and Visual Studio 2010.

In Visual Studio 2010, the expression trees API was extended and added to the dynamic language runtime (DLR), so that language implementers can emit expression trees rather than MSIL. To support this new goal, control flow and assignment features were added to expression trees: loops, conditional blocks, try-catch blocks, and so on.

There is a catch: You cannot use these new features “an easy way”, by using lambda expressions syntax. You must use the expression trees API. So the last code example in the previous section still generates a compiler error, even in Visual Studio 2010.

But now you have a way to create such an expression tree by using API methods that were not available in Visual Studio 2008. One of these methods is Expression.Block, which enables the execution of several expressions sequentially, and this is exactly the method that I need for this example.

// Creating a parameter for an expression tree.

ParameterExpression param = Expression.Parameter(typeof(int), "arg");

 

// Creating an expression for printing a constant string.

MethodCallExpression firstMethodCall = Expression.Call(           

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }),

Expression.Constant("Print arg:")

);

 

// Creating an expression for printing a passed argument.

MethodCallExpression secondMethodCall = Expression.Call(          

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }),

param

);

 

// Creating a block expression that combines two method calls.

BlockExpression block = Expression.Block(firstMethodCall, secondMethodCall);

 

// Compiling and invoking an expression tree.

Expression.Lambda<Action<int>>(

block,

new ParameterExpression[] { param }

).Compile()(10);

I’ll repeat this: Although the expression trees API was extended, the way expression trees work with lambda expression syntax did not change. This means that LINQ queries in Visual Studio 2010 have the same features (and the same limitations) that they had in Visual Studio 2008.

But because of the new features, you can find more areas outside of LINQ where you can use expression trees.

Generating Dynamic Methods

Now let’s move to the real problems where the new API can help. The most well-known one is creating dynamic methods. The common solution to this problem is to use System.Reflection.Emit and work directly with MSIL. Needless to say, the resulting code is hard to write and read.

Basically, the expression tree that prints two lines to the console that I have shown previously is already an example of a dynamic method. But let’s try a little bit more complex one to demonstrate more features of the new API.  Thanks to John Messerly, a developer on the DLR team, for providing the following example.

Assume that you have a simple method that calculates the factorial of a number.

static int CSharpFact(int value)

{

      int result = 1;

while (value > 1)

{

result *= value--;

}

return result;

}

Now you want a dynamic method that does the same thing. We have several essential elements here: a parameter that is passed to a method, a local variable, and a loop. This is how you can represent these elements by using the expression trees API.

static Func<int, int> ETFact()

{

 

// Creating a parameter expression.

ParameterExpression value = Expression.Parameter(typeof(int), "value");

 

// Creating an expression to hold a local variable.

ParameterExpression result = Expression.Parameter(typeof(int), "result");                                   

           

// Creating a label to jump to from a loop.

LabelTarget label = Expression.Label(typeof(int));

 

// Creating a method body.

BlockExpression block = Expression.Block(

 

// Adding a local variable.

new[] { result },

 

// Assigning a constant to a local variable: result = 1

Expression.Assign(result, Expression.Constant(1)),

 

// Adding a loop.

Expression.Loop(

 

// Adding a conditional block into the loop.

Expression.IfThenElse(

 

// Condition: value > 1

Expression.GreaterThan(value, Expression.Constant(1)),

 

// If true: result *= value --

Expression.MultiplyAssign(result,

Expression.PostDecrementAssign(value)),

 

// If false, exit from loop and go to a label.

Expression.Break(label, result)

),

// Label to jump to.

label

)

);

 

// Compile an expression tree and return a delegate.

return Expression.Lambda<Func<int, int>>(block, value).Compile();

}

Yes, this may look more complicated and less clear than the original C# code. But compare it to what you have to write to generate MSIL.

static Func<int, int> ILFact()

{

      var method = new DynamicMethod(

      "factorial", typeof(int),

      new[] { typeof(int) }

      );

      var il = method.GetILGenerator();

      var result = il.DeclareLocal(typeof(int));

      var startWhile = il.DefineLabel();

      var returnResult = il.DefineLabel();

 

      // result = 1

      il.Emit(OpCodes.Ldc_I4_1);

      il.Emit(OpCodes.Stloc, result);

 

      // if (value <= 1) branch end

      il.MarkLabel(startWhile);

      il.Emit(OpCodes.Ldarg_0);

      il.Emit(OpCodes.Ldc_I4_1);

      il.Emit(OpCodes.Ble_S, returnResult);

 

      // result *= (value--)

      il.Emit(OpCodes.Ldloc, result);

      il.Emit(OpCodes.Ldarg_0);

      il.Emit(OpCodes.Dup);

      il.Emit(OpCodes.Ldc_I4_1);

      il.Emit(OpCodes.Sub);

      il.Emit(OpCodes.Starg_S, 0);

      il.Emit(OpCodes.Mul);

      il.Emit(OpCodes.Stloc, result);

 

      // end while

      il.Emit(OpCodes.Br_S, startWhile);

 

      // return result

      il.MarkLabel(returnResult);

      il.Emit(OpCodes.Ldloc, result);

      il.Emit(OpCodes.Ret);

 

      return (Func<int, int>)method.CreateDelegate(typeof(Func<int, int>));

}

If You Want to Know More

In Visual Studio 2010, expression trees were developed as a part of the dynamic language runtime, which is also released as an open-source project. You can download the source code and find the specification and documentation for expression trees on the CodePlex Web site.

A more advanced example of using the new expression trees API is shown in Bart De Smet's blog post Expression Trees, Take Two – Introducing System.Linq.Expressions v4.0.

And of course, to try the examples, you need to download Visual Studio 2010 and .NET Framework 4 Beta 1 here.

Syndicated via RSS From: http://blogs.msdn.com/b/csharpfaq/

Setting Fullscreen mode under Windows

The following code changes screen resolution and sets windows that are created as WS_POPUP into fullscreen mode:

bool EnterFullscreen ()
{
	DEVMODE newSettings;
	// now fill the DEVMODE with standard settings, mainly monitor frequenzy
	EnumDisplaySettings ( NULL, 0, &newSettings );
	//  set desired screen size/res
 	newSettings.dmPelsWidth  = 800;
	newSettings.dmPelsHeight = 600;
	newSettings.dmBitsPerPel = 16;
	//set those flags to let the next function know what we want to change
 	newSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
	// and apply the new settings
	if ( ChangeDisplaySettings ( &newSettings, CDS_FULLSCREEN )
		!= DISP_CHANGE_SUCCESSFUL )
	return false; // in case of error
	else return true;
}

// and to reset the screen  on program exit:
void ResetScreen ()
{
	// this resets the screen to the registry-stored values
  	ChangeDisplaySettings ( NULL, 0 );
}