Monday, September 29, 2008

Is NDA in conflict with YAGNI?

I got a question on my previous post (The No Dependency Architecture (NDA)) if NDA is not in conflict with YAGNI, and when I was writing the response it became more or less an actual post, so there you go :)

Explaining the thought behind the No Dependency Architecture (NDA) in combination with YAGNI in one sentence would be something like this: “You anticipate change at a technical level, not at a functional level”.

I believe that the “You Ain’t Gonna Need It” (YAGNI) principle does not imply that writing software accordingly to the SOLID principles is bad practice. When you are following these principles (and there are others that are good to follow too) then you are writing software that assumes change, right? I believe that YAGNI is more targeted to functional overhead.

I.e. using a IoC container to fulfill the Dependency Inversion Principle (DIP) is not in conflict with YAGNI because that is at a technical level, but when you are writing extra code for no other reason than that you assume the object might be used in a certain other way also, then you are violating the YAGNI principle because then you are creating additional functionality that is not needed.

From Wikipedia ( http://en.wikipedia.org/wiki/You_Ain't_Gonna_Need_It) YAGNI, short for 'You Ain't Gonna Need It', suggests to programmers that they should not add functionality until it is necessary

So I would recommend using the various SOLID principles when writing your software assuming things will change because that is just good practice. Change is a fact, we just don’t know what will change, but by conforming to SOLID we can handle these future changes without too much headache.

As to using an Event Driven Architecture, I am surely not saying each object should only interact using events, that would not make much sense, but most (larger) systems will be build up using multiple sub systems. Having these sub systems communicate via events is a very good way to isolate them from each other. Then it is unknown to each sub system who they are really talking to (i.e. dispatching the events to). In fact it is a 1 to n relationship where the dispatched event might have no, one or many subscribers.

To make the actual handling of subscribing and publishing easier you could use a service bus that deal with that for you. This will also make the system easier adaptable to change. You can also specify that the event can be handled by any instance of the same subscriber enabling load balancing.

“Don’t call us, we call you” ( http://en.wikipedia.org/wiki/Hollywood_Principle); is the basis of an Event Driven Architecture, and this is very true, because no system is waiting on an answer from another system. They fire events and they act on events, it is merely coincidence if these events have anything to do with each other.

So I would also recommend using an Event Driven Architecture (EDA) straight from the beginning, perhaps not using a service bus from the start, but just using EDA will make refactoring to use one at a later stage a lot easier.

Thursday, September 25, 2008

The No Dependency Architecture (NDA)

We already have many, many, many acronyms in our profession; TDD, BDD, DDD, SOA, EDA, DIP and SOLID just to name a few. So who am I to add yet another one in the mix, well I am a nobody. Having covered that, I would like to continue explaining this new one.

NDA is a software architecture that has no dependencies between the different components. It’s all in the name :)

By combining the Dependency Inversion Principle (DIP) and an Event Driven Architecture (EDA) we can achieve software that has no dependencies, not internal not external. So why would we want that? Well it enables you to just replace any part in your software solution with something else without it affecting the rest of the solution. And you will be able to scale the solution much easier.

So let’s look a bit more into the details, first I would like to start with DIP. Dependency Injection can be achieved using an Inversion of Control (IoC) container. An IoC container will provide an already instantiated object that (when done properly according to DIP) is based on an interface. The consumer of the object is only using the interface and does not know anything about the actual implementation.

One simple rule about how to provide the dependent objects is that when the consumer object cannot work without the dependent object it should be provided in the constructor of the consumer object; if the consumer object can continue without the dependent object (i.e. logging module) than that object should be provided via a setter property of the consumer object.

Modern IoC containers can Auto Wire the dependencies when creating an object, meaning that if a object of the requested type is present in the configuration you will not have to specify the dependent object in the constructor arguments of the consumer, this will be done automatically. I am a fan of keeping the configuration of the IoC container in a configuration file, this way I can easily provide a different implementation of the requested objects by just changing the configuration file. No need to recompile anything. I currently am working a lot with Castle Windsor which is a great IoC container.

So this should take care of dependencies your code may have between other parts of your code (i.e. object between object). Now we can move on to try and get rid of dependencies between different systems or major parts of your system (i.e. between services and consumers). When using an Event Driven Architecture your code is basically sending out events when something happens and does not care who or what is acting on those events. Different systems may subscribe to these events and may do their own thing. And to take this one step further you should consider using a service bus architecture, which basically means that events will be published into a cue. Consumers of these events subscribe to the cue and will get notified whenever there is an event waiting for them. There can be as many consumers subscribing to the events via the service bus as needed. The publisher does not know nor care about the consumers; it fires the event and moves on. Consumers don’t know or care about the source of the event, just that it is the type of event they are interested in.

As you can see this decouples the different systems from each other, since none of them know about each other there can be no dependencies between each other. Currently I am looking into NServiceBus, I got a real nice demo today from my college John that started this current thought process.

So now I believe we have a system that does not depend on anything, well realistically it depends on things, but these things can be switched, replaced, multiplied and even be offline nobody knows. I plan to go over these different parts in the coming posts, so if you have any comment I would love to hear from you.

Castle Windsor http://www.castleproject.org/container/index.html
NServiceBus http://www.nservicebus.com/

Wednesday, September 24, 2008

Silverlight with Einar Ingebrigtsen from Objectware

Today was another interesting NNUG (Norwegian .Net User Group) meeting where Einar presented Silverlight 2 in two separate sessions.

The first session covered more how easy it is to get a nice look and feel, together with some nice animations. During this presentation Einar used both Visual Studion 2008 and Expression Blend 2.5, and demonstrated how well they work together.

The second session was more technical and went into using WCF (Windows Communication Foundation) to have the Silverlight application communicate with the server. This session was very code driven and that was great about it. He demonstrated how to create the WCF service using a Visual Studio file template, I don’t know the exact name for it, but similar to creating a new class he created a new Silverlight WCF services, and how to consume it in the WCF code. Btw there is nothing special about a Silverlight WCF services except that it is using the BasicHTTPBinding

Einar Ingebrigtsen http://www.ingebrigtsen.info/

Saturday, September 20, 2008

That Agile Thing

I think he nailed it, doesn't matter what mythologies (pun intended) you are using, it is about delivering required functionality to your customer. And doing that in small iterations has been proven to work.

http://ayende.com/Blog/archive/2008/09/20/that-agile-thing.aspx

-Mark

How to test your XAML Behavior using unit tests

With WPF and Silverlight a whole new area opens up for application development. Using XAML it is so much easier to create something ‘Cool’ than was possible before with ‘normal’ Windows Forms. Another even more important thing is the separation of the GUI and the application code; this makes testing more easily because you have a clear cut line between your GUI and code. Not to mention much more maintainable and extendable. There are many more good reasons why you might want to use WPF or Silverlight instead of the previous technologies, but going back to the ‘Cool’ part. Now It is also very possible that I as a developer create an extremely simple GUI just to verify some needed functionality and then move on to the actual code. In the meantime we send the XAML file to our design department and they start working on actually making it ‘Cool’, because be honest; no matter how easy they make it for me, I will never be able to create a cool graphical design ;) So also for this example I shamelessly took something that I think looks cool from Gøran Hansen from the MSDN Live presentations he is keeping in Norway.

Anyway below here is a screenshot of a Window that Gøran Hansen created, I only converted it to a UserControl and changed the behavior to be in the XAML definition without external data binding.

XAML UserControl


I just noticed that images are not provided to the Google Reader so if you are missing these just go to the original post.

So the XAML file gets returned to me by one of our graphical designers and now I have to check that all the previous existing functionality is still there and working. So what I really want to be able to do is replace my original file with the new one and have some tests run to verify that all my functionality still is valid. I want unit tests for my XAML Behavior.

XAML UserControl Unit tests


XAML Behavior, didn’t you just say that the GUI is now separated from the application code, so it should also be separated from any behavior right? Well no not exactly, we can still define some logic in the XAML definition, quite a lot actually. If this is something we want is another discussion, let’s assume because it is possible it will be used ;) So I did define some basic behavior in my XAML definition, namely: • I wanted the Save button to be disabled until both the Web Dashboard URL and the Poll interval where filled in. • I wanted to only be able to select a successful build sound file when the user check that option, the same for the broken build sound file. So this behavior is independent of any code or other logic than is defined in the XAML definition. Ok I admit I wrote a small convertor that is used in the XAML definition, but that is more an XAML extension.

So when I received the new design from our graphics department it looked like this:

XAML UserControl


Ok this didn’t actually go to them ;) this is me being creative, but in the process of making these huge changes to the design I broke some of the previous behavior, behavior that I am counting on to work. For example I don’t want users to click the Save button before they filled out the needed information? So how do I know I broke these behaviors? Well look at the following screenshot, isn’t that a clear picture?

XAML UserControl Unit tests


So finally I get to the interesting parts, how did I get Unit testing for my XAML Behavior? For this I wrote a really simple helper class that is responsible for loading and parsing the XAML. This helper class is then used in the unit testing framework of your choice; I used NUnit in this example.

Class: XamlUnitTestHelper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Threading;

namespace Fohjin.XamlBehaviorVerifier
{
    /// <summary>
    /// This is a static helper class to use with any unit testing framework.
    /// </summary>
    public static class XamlUnitTestHelper
    {
        private static ParserContext _XamlContext;
        private static Viewbox _Viewbox;

        /// <summary>
        /// Loads the xaml into a Viewbox so that we can parse it and verify its working.
        /// </summary>
        /// <param name="xamlFilePath">The xaml file path.</param>
        public static void LoadXaml(string xamlFilePath)
        {
            String xamlFileStream = File.ReadAllText(xamlFilePath);
            if (xamlFileStream.IndexOf("x:Class=") != -1)
                xamlFileStream = Regex.Replace(xamlFileStream, "x:Class=\\\".+([^\\\"])\\\"", "");

            object obj = XamlReader.Load(new MemoryStream(new System.Text.ASCIIEncoding().GetBytes(xamlFileStream)), XamlContext);
            _Viewbox = new Viewbox
            {
                Child = ((UIElement)obj)
            };
            _Viewbox.UpdateLayout();
            FlushDispatcher();
        }

        /// <summary>
        /// Gets the object.
        /// </summary>
        /// <typeparam name="T">This is the type of control that is being searched for</typeparam>
        /// <param name="name">The name of the control that is being searched for</param>
        /// <returns>If the control is found a reference to this control is returned else null</returns>
        public static T GetObject<T>(string name) where T : class
        {
            if (_Viewbox != null && _Viewbox.Child != null)
            {
                FrameworkElement child = _Viewbox.Child as FrameworkElement;
                if (child != null)
                {
                    return child.FindName(name) as T;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the xaml context, to be used by the XamlReader.
        /// </summary>
        /// <value>The xaml context.</value>
        private static ParserContext XamlContext
        {
            get
            {
                if (_XamlContext == null)
                {
                    _XamlContext = new ParserContext();
                    _XamlContext.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                }
                return _XamlContext;
            }
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher()
        {
            FlushDispatcher(Dispatcher.CurrentDispatcher);
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher(Dispatcher ctx)
        {
            FlushDispatcher(ctx, DispatcherPriority.SystemIdle);
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher(Dispatcher ctx, DispatcherPriority priority)
        {
            ctx.Invoke(priority, new DispatcherOperationCallback(delegate { return null; }), null);
        }
    }
}

As you can see it is really simple and straightforward, the FlushDispatcher is something I need for Data Binding this is I discussed in a previous post Saving a WPF Xaml FlowDocument to XPS with working DataBinding. I am not using Data Binding in this example, but in a next post I’ll see if I can get that to work also.

Class: SettingsUserControlTests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System.Windows.Controls;
using Fohjin.XamlBehaviorVerifier;
using NUnit.Framework;

namespace WpfControlLibrary.Test
{
    [TestFixture]
    public class SettingsUserControlTests
    {
        private const string _XamlFilePath = @"C:\Projects\Fohjin.XamlTest\WpfControlLibrary\SettingsUserControl1.xaml";
        //private const string _XamlFilePath = @"C:\Projects\Fohjin.XamlTest\WpfControlLibrary\SettingsUserControl2.xaml";

        private const string _SoundsCheckBox = "soundsCheckBox";
        private const string _SoundsCheckBoxNotFound = "Could not find CheckBox control '" + _SoundsCheckBox + "'";
        private const string _SoundsCheckBoxIssue = "Issue with a value of '" + _SoundsCheckBox + "'";

        private const string _BrokenCheckBox = "brokenCheckBox";
        private const string _BrokenCheckBoxNotFound = "Could not find CheckBox control '" + _BrokenCheckBox + "'";
        private const string _BrokenCheckBoxIssue = "Issue with a value of '" + _BrokenCheckBox + "'";

        private const string _BtnOnSuccessFileDialog = "btnOnSuccessFileDialog";
        private const string _BtnOnSuccessFileDialogNotFound = "Could not find Button control '" + _BtnOnSuccessFileDialog + "'";
        private const string _BtnOnSuccessFileDialogIssue = "Issue with a value of '" + _BtnOnSuccessFileDialog + "'";
        
        private const string _BtnOnBrokenFileDialog = "btnOnBokenFileDialog";
        private const string _BtnOnBrokenFileDialogNotFound = "Could not find Button control '" + _BtnOnBrokenFileDialog + "'";
        private const string _BtnOnBrokenFileDialogIssue = "Issue with a value of '" + _BtnOnBrokenFileDialog + "'";

        private const string _TxtWebDashboardUrl = "txtWebDashboardUrl";
        private const string _TxtWebDashboardUrlNotFound = "Could not find TextBox control '" + _TxtWebDashboardUrl + "'";
        //private const string _TxtWebDashboardUrlIssue = "Issue with a value of '" + _TxtWebDashboardUrl + "'";

        private const string _TxtPollInterval = "txtPollInterval";
        private const string _TxtPollIntervalNotFound = "Could not find TextBox control '" + _TxtPollInterval + "'";
        //private const string _TxtPollIntervalIssue = "Issue with a value of '" + _TxtPollInterval + "'";

        private const string _BtnSave = "btnSave";
        private const string _BtnSaveNotFound = "Could not find Button control '" + _BtnSave + "'";
        private const string _BtnSaveIssue = "Issue with a value of '" + _BtnSave + "'";

        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);
            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_SoundsCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);

            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsNotNull(checkBox, _SoundsCheckBoxNotFound);

            checkBox.IsChecked = true;
            Assert.IsTrue(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsDisabledAgain()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_SoundsCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);

            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsNotNull(checkBox, _SoundsCheckBoxNotFound);

            Assert.IsFalse(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);

            checkBox.IsChecked = true;
            Assert.IsTrue(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsTrue(button.IsEnabled, _BtnOnSuccessFileDialogIssue);

            checkBox.IsChecked = false;
            Assert.IsFalse(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }

        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);
            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_BrokenCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);

            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsNotNull(checkBox, _BrokenCheckBoxNotFound);

            checkBox.IsChecked = true;
            Assert.IsTrue(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_BrokenCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);

            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsNotNull(checkBox, _BrokenCheckBoxNotFound);

            Assert.IsFalse(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);

            checkBox.IsChecked = true;
            Assert.IsTrue(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsTrue(button.IsEnabled, _BtnOnBrokenFileDialogIssue);

            checkBox.IsChecked = false;
            Assert.IsFalse(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }

        [Test]
        public void VerifyThatbtnSaveIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsDisabled1()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsDisabled2()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "";
            txtPollInterval.Text = "10";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain1()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);

            txtWebDashboardUrl.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain2()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);

            txtPollInterval.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
    }
}

Pretty cool and simple, right? Well you need to make sure that your unit tests are running in a ApartmentState.STA thread. When you are using NUnit you only need to add a configuration file to your test library with the following content:

App.Config file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configSections>
  <sectionGroup name="NUnit">
   <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"></section>
  </sectionGroup>
 </configSections>

 <NUnit>
  <TestRunner>
   <add key="ApartmentState" value="STA"></add>
  </TestRunner>
 </NUnit>
</configuration>
I intend to continue working on this a bit more too see how far I can take this without it becoming too big for unit testing. I hope you can also see the value in these types of tests. You can download the full solution from here: http://downloads.fohjin.com/Fohjin.XamlBehaviorTester.rar

Saturday, September 13, 2008

How to reference DLL’s in your .Net projects, don’t assume anything

“How great is this I just found this cool library; it fits perfectly in my current project, it even comes with an installer so I can reference it straight away?” So how are you going to provide this to your team members? “Well we have a shared folder that contains all our third party installers.”

What is wrong with this scenario?

Well every time you get a new developer on your team you have to make sure that he has all the third party libraries installed, and make sure that they are of the correct version. If you have got all the installers placed together than this is not the worst thing, but in reality you are probably missing one or two, or you don’t exactly know what is required, this is not your only project is it?

So let’s say you got the new guy up and running, it took both of you about half an hour just to get the source to compile. The new guy has to fix a bug and sees there is an update for library xyz. This update is exactly what he needs, so he downloads it installs it, compiles the code and checks in the changes. Now suddenly all other developers who updated their code need the new library to be able to compile. But which version did the new guy actually use; he went home to take an early weekend. Your Continuous Integration process also immediately stopped working because the new guy didn’t install the new version on there either. Didn’t we tell him to do that?

That’s what’s wrong.

What to do about it? Well create a folder “Libraries” in your solution and place all the needed third party libraries in there. And I basically mean everything that doesn’t come with the default .Net Framework installation. Then create absolute references to these libraries (Add reference – Open Browse tab – Find your “Libraries” folder – Select the DLL’s to include). Check-in the changes including all third party libraries, you are using a version control system right? Now when ever, where ever you check out your code you can instantly compile it. One quick way to get all the needed DLL’s is to Publish the solution, then just copy every non project DLL into the new “Libraries” folder.

But I have an ASP.Net website project and don’t have a reference folder or even a project file in my project. I really dislike the decision of Microsoft to provide projects without actual project files. In that case I would suggest using a Web Application project and include all needed files and libraries in there manually.

So the lesson is: “Don’t assume everybody is using the same DLL version, make sure everybody is using the same DLL version”.

Tuesday, September 9, 2008

MSDN Live – Bergen

Today MSDN Live was visiting Bergen, and I must say it was a very interesting day all together. My day looked like this:

  • Introduction to Silverlight 2 by Gøran Hansen
    Basic introduction on how Silverlight works, what the possibilities and limitations are of the .Net 3.5 Framework subset that is used by Silverlight. How Silverlight communicates to the hosting server and the cross site communication possibilities. This combined with some clear XAML code examples.

  • ASP.NET Dynamic Data by Gøran Hansen
    This is great! Well when you have to build a data entry web application than this is a live saver. Nobody really wants to create all the different pages to populate and manage database tables. ASP.NET Dynamic Data will do this for you, and the great thing about it is that you can use templates to customize the generated pages. A nice fact is this is also supposed to be made available for ASP.MVC.

  • Want SOA? Throw out your web services by Anders Norås
    Hehe SOA without Web Services, Anders argues that using web services are still creating a too tight coupling between the various systems. He instead suggests using a service bus where messages / events are being fired and clients can register to these messages / events. He shown examples using NServiceBus. I guess I got some more reading and playing to do :)

  • Internet Explorer 8 for Developers by Anders Norås
    This for me was the least interesting part of the day, which has nothing to do with the presentation, but more with the actual topic. I lost interest in the different browsers quite some time ago. One cool thing was to hear that Microsoft IE 8 now is actually complaint and will not be as forgiven anymore, possible breaking many internet pages. There is of course an IE 7 mode.

    Scott also just wrote a post about comparing Microsoft IE8 and Google Chrome: http://www.hanselman.com/blog/MicrosoftIE8AndGoogleChromeProcessesAreTheNewThreads.aspx

  • Application Development in WPF by Gøran Hansen
    This was a very interesting presentation, which involved lots of code, code is good :) the talk was targeted using WPF, but it could have been about any programming language or framework. The main message was to create lousy coupled code, program to interfaces and separation of concerns. This all sounds very true to me, so it was enjoyable to listen too ;) Than in combination with WPF Gøran showed how to disconnect the GUI front end XAML from the code using it. And he went into how to test the code that would be using the XAML.

    Afterwards we discussed a little bit the ability (or disability) to actually test the XAML file, I have some ideas about that and will try to create a small project around that and will post it in my blog.
Thanks guys for this interesting and entertaining day.

Gøran Hansen - http://blog.goeran.no/
Anders Norås - http://andersnoras.com/blogs/anoras/default.aspx

Saturday, September 6, 2008

Google Chrome

Yay,

Just downloaded Google Chrome and am trying it out, so you could say I am a late adopter :) Looks great, feels great, works great. There are some things I especially like. For example it is what you use a browser for, browsing, Google Chrome is using the biggest screen area possible, having said that I would still like to see a smaller address bar.

But from a developer point of view I really like the 'Create application shortcuts' idea. This makes a web based application look and feel a little bit more like a desktop application. You don't want to confuse your users by having them open a web browser to do their work, nahh... I can see an installer just placing this little shortcut on the users desktop :D

I am a bit disappointed that they haven't integrated their Google Bookmarks into Google Chrome, but I am sure that is only a matter of time. A nice little tip is to add your Google Bookmarks search box to the Chrome search options (for lack of a better name for it). Go to options and click on the 'Manage' button next to the 'Default search'. Choose to Add a new search engine. Use the following values:

Name: Google Bookmarks
Keyword: gb
Url: http://www.google.com/bookmarks/find?q=%s

Name: Google Reader
Keyword: gr
Url: http://www.google.com/reader/view/#search/%s/

Now when you start typing 'gb' you will see the option 'Search Google Bookmarks for <search term>' select that and everything you type after that will be redirected to the Google Bookmarks search page. I know you can do simulair stuff in other browsers, but in Chrome I don't have to select which search engine I want to use, I just type 'gb <search term>'. Great!

I would encourage you to download and install it, you will be missing a lot of add-on support (since it doesn't have it). Its minimalistic ;)