DCSIMG
April 2008 - Posts - Shai Raiten's Blog

Shai Raiten's Blog

It's all about code...

April 2008 - Posts

Data Driven Development

Data Driven Development

The Full Article 

Recently I heard the question “What is the Data Driven Development?” 

Data Driven Development isn't new and probably is an old Basic of development.

Let’s look into the problem with help of example.
We will create an aquarium. And it is not a joke.

Let’s formulate our goal at the beginning.
We want to make a model of the aquarium with small fishes in it.

We will create the aquarium by the traditional OOP way. Our model consists from two main things – the aquarium itself and all objects which can be placed in the aquarium. In our case these objects are small fishes and plants. Any fish can swim, eat food and do many other things.

So the object hierarchy can be as at the picture below.

ddd 

I would like to show another example in the spirit of Passover:

Drawing1

If we need to create new fish or plant we have to inherit from correct object and overload few methods only. The program architecture we got is very flexible. For example it is easy to add a toy submarine in the aquarium.

However such solution has a problem. Let we have need to add a new property to the fish, for example it can be a text description. We have to look up all our fish’s classes and add there correct description for each fish. What shell we do if it is necessary to create 20 different fishes? Making of 20 classes which are almost the same is not most interesting work. What about adding of two new properties to these 20 classes? What to do if there will be 5 properties and 50 classes? It is obvious we need to change something in our architecture.

The good solution of this problem is making unnecessary of inheritance for each type of fish. We can create a single class which will be initialized from the table instead of inheritance. It can look as below (C++).

enum FISH_FOOD
{
INSECTS = 0x01,
WORMS = 0x02,
GRUBS = 0x04,
};
 
enum BEHAVIOR
{
SHOAL = 0x01,
CAMOUFLAGE = 0x02,
FEAR = 0x04,
};
 
struct FISH
{
const char * name;
int effective_size;
int food;
int behavior;
} fish[] = {
{"guppy", 10, INSECTS GRUBS, SHOAL},
{"neon", 12, WORMS INSECTS, SHOAL CAMOUFLAGE FEAR},
{"golden fish", 8, GRUBS, FEAR},
{NULL, 0, 0}
};
 
 
class Fish
{
void Eat() {}
public:
Fish(const char * name) {}
void Move() {}
};
 
 
int main()
{
Fish guppy1("guppy");
Fish guppy2("guppy");
return 0;
}

In this case we have to add only one line of data to the table to make the new type of fish. An experts, who asking to add new fishes in our aquarium, can make there requirements in the form we can place to the program without changing.

This simple example illustrates what is Data Driven Method. It has disadvantages.
Main disadvantage is loosing of flexibility. We could create unique behavior for each fish before. Now such unique behavior will be pressed by the borders of few parameters for one algorithm. Of course, we can create “switch-case” instructions which return flexibility we loose. However, excess of “switch-case” leads to heavily supported code.

Customizing Work Items in Visual Studio

Customizing Work Items in Visual Studio

As commonplace "Customizing Work Items" sounds like, I was slightly surprised to find out that some companies still use the default MSF methodology templates comes with Team System, not because the templates fits to their needs, because they didn't know that is possible to customize a work item in Visual Studio Team System.

Customizing Work Item Types in Team System isn't quite as easy as it should be, but it's not difficult.

The Work Items are actually XML. To export them, you use the command line utilities witimport and witexport, which are located in the
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE path by default.

Here's how to export a specific work item type:

witexport /f C:\CurrentBugTemplate.xml /t teamsystem /p ShaiProject /n "Bug"

Once you download the work item type XML files, you'll need to edit the resulting XML files to make whatever changes you need in the Work Items. There's some good guidance at MSDN on making common Work Item Type edits:

But editing raw XML still isn't my idea of a good time. You can make the experience slightly more pleasurable by adding IntelliSense to Visual Studio 2005 for Work Item Type XML. Rob Caron describes how. It's quite easy.

  1. Download the process template schemas from the MSDN help topic Process Template Schemas Download.
  2. extract the contents to: %ProgramFiles%\Microsoft Visual Studio 8\Xml\Schemas

After you copy the schemas to the right place, restart the IDE and you'll discover some shiny new IntelliSense when you begin editing the Work Item XML:

workitemtype-

Once you're done making edits, validate your changes to make sure you didn't break anything.

witimport /f C:\CurrentBugTemplate.xml /t teamsystem /p ShaiProject /v

There is no need to specify the Workitem type name in the witimport line,
the workitem type name located inside the schemas xml within the "WORKITEMTYPE" element.

Then, if you're happy with the validation results, remove the /v flag to import the work item.

witimport /f C:\CurrentBugTemplate.xml /t teamsystem /p ShaiProject

And you're done! Wasn't that easy? OK, I wouldn't call it easy, but it's not too painful.

Web Access - Send an email with a work item or query results

 

Let's say you're going through your bugs and want to ask someone a question about one of them.  You can use Team System Web Access to send that person an email containing all of the work item's information and a link to it.

To email a work item, open the work item in TSWA.  Go to the Tools menu shown below and choose Send as Email.

1

You'll get a new window where you can enter the person's full email address and type a message.  The message body contains a link to the work item in Team System Web Access and all of the work item's fields and contents.

2

You can also email query results.  As with the work item above, go to the Tools menu and choose Send as Email.

3

You'll then get a similar email window that contains the results of the query and a link so that the email recipient can run the same query.

4

Enjoy!

Access Token With C#

Last week I had a task to build a tool that can control IIS and Services in another computer in different domain.
Performing IIS reset or control Services status in different computer is easy, but when the computer belongs to a different domain those actions becomes quite complicated. 

So I found that create an dynamic Access Token is the best way to accomplish those actions.

An access token is an object that describes the security context of a process or thread.
The information in a token includes the identity and privileges of the user account associated with the process or thread.

With dynamic Access Token I can run each part of my C# code as a different Domain\User.
That solved all my problems.

Create a new class: (I called it Impersonator)

namespace Tools
{
    #region Using directives.
    using System;
    using System.Security.Principal;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    #endregion
 
    public class Impersonator :
        IDisposable
    {
        #region Public methods.
        public Impersonator(
            string userName,
            string domainName,
            string password)
        {
            ImpersonateValidUser(userName, domainName, password);
        }
        #endregion
 
        #region IDisposable member.
        public void Dispose()
        {
            UndoImpersonation();
        }
        #endregion
 
        #region P/Invoke.
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern int LogonUser(
            string lpszUserName,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int DuplicateToken(
            IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool RevertToSelf();
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern bool CloseHandle(
            IntPtr handle);
 
        private const int LOGON32_LOGON_INTERACTIVE = 2;
        private const int LOGON32_PROVIDER_DEFAULT = 0;
        private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
 
        #endregion
 
        #region Private member.
 
        private void ImpersonateValidUser(
            string userName,
            string domain,
            string password)
        {
            WindowsIdentity tempWindowsIdentity = null;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
            if (userName != null && domain != null && password != null)
            {
                try
                {
                    if (RevertToSelf())
                    {
                        if (LogonUser(
                            userName,
                            domain,
                            password,
                            LOGON32_LOGON_NEW_CREDENTIALS,
                            LOGON32_PROVIDER_DEFAULT,
                            ref token) != 0)
                        {
                            if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                            {
                                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                                impersonationContext = tempWindowsIdentity.Impersonate();
                            }
                            else
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            }
                        }
                        else
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error());
                        }
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                }
                finally
                {
                    if (token != IntPtr.Zero)
                    {
                        CloseHandle(token);
                    }
                    if (tokenDuplicate != IntPtr.Zero)
                    {
                        CloseHandle(tokenDuplicate);
                    }
                }
            }
        }
 
        private void UndoImpersonation()
        {
            if (impersonationContext != null)
            {
                impersonationContext.Undo();
            }
        }
 
        private WindowsImpersonationContext impersonationContext = null;
 
        #endregion
    }
}

How to use it:

using  (new Impersonator(User_Name, Domain, Password))

       ***  The following code is executed under the impersonated user. ***
}

If you want to test it, just create a user with a low privilege and run this code:

                string[] files = Directory.GetFiles( "c:\\windows" );

Hope I helped.