Thursday, July 22, 2010
The evil of process over craftsmanship
By taking the time to build a quality product, it will cost more up front, talented people cost money, to do the job right takes time(time=money) but because it was done right the first time it costs a lot less in the long run.
Unfortunately in the software development world it’s far to common to just get it out and worry about fixing known problems later. This becomes even more painful when the schedule or process becomes the reason for poor craftsmanship.
Here are two problems, one is building a house the other is building software:
1) A builder starts working on a house and discovers that the property has a high water table and that every spring there would be flooding in the crawlspace. The two ways to solve this problem are: bring in enough dirt to raise the house up so the crawlspace doesn't get flooded or add subpumps to pump the water out. Both fix the problem, while the subpumps are going to be quicker to setup, it’s not going to get out all of the water and it will add to maintenance costs which in the long run will be much more expensive.
2) A pair of developers are tasked with writing a service for importing data into a database and half way though writing it they find out the data has duplicate records and some other garbage data. There are two ways to solve this, build a validator to remove the garbage data or pass it off and have the DBAs create a job to remove the garbage from the database.
I’m fairly sure we would all much rather take the time to put in the fill dirt then have to deal with the maintenance of having sub pumps, and yet for some reason it’s very common for developers to be told “we don’t have time to add a filter” and to push the task of removing the garbage from the database onto the DBAs, or worse yet just live with the garbage data.
We know that when the process(schedule/tasking) trumps craftsmanship(using subpumps or having the DBAs remove bad data) you end up with a lower quality product with higher overall costs so why do we still do it?
The tools of the software craftsman: TDD, design patterns(command, strategy, observer, etc ), decoupled design, source control, continues integration, paired programming, etc. and by using any of them you will end up with better software with lower overall costs and yet it feels like it’s a constant battle to get them into our development process. We need to take a stand, we need to be craftsman and insist on building quality products.
Friday, May 28, 2010
Using the Observer Pattern
The first part is the the class that manages the observer classes
1: public class EventManager<T>
2: {
3: private Dictionary<string, ISubscriber<T>> _subscribers = new Dictionary<string, ISubscriber<T>>();
4: public Dictionary<string,ISubscriber<T>> Subscribers
5: {
6: get { return _subscribers; }
7: set { _subscribers = value; }
8: }
9:
10: public void Notify(T newState)
11: {
12: foreach (var observer in Subscribers.Values)
13: {
14: observer.State = newState;
15: observer.Update();
16: }
17: }
18: }
Next let’s take a look at ISubscriber<T> interface
1: public interface ISubscriber<T>
2: {
3: T State { get; set; }
4: void Update();
5: }
1: public class TweetLocation : ISubscriber<Location>
2: {
3: public ITwitter TwitterInterfacer = new FakeTwitterClient();
4: public Location State { get; set; }
5:
6: public void Update()
7: {
8: TwitterInterfacer.TweetMessage(string.Format("currently at ({0},{1})",State.Lat,State.Lon));
9: }
10: }
1: public class SaveLocation : ISubscriber<Location>
2: {
3: public ILocationReposigtory LocationRepository = new FakeLocationRepository();
4: public static EventManager<string> ErrorHandler = new EventManager<string>();
5:
6: public Location State{get;set;}
7:
8: public SaveLocation()
9: {
10: ErrorHandler.Subscribers.Add("ErrorMailer",new ErrorMailer());
11: }
12:
13: public void Update()
14: {
15: bool success = LocationRepository.SaveLocation(State);
16: if (!success)
17: {
18: ErrorHandler.Notify("Failed to save location");
19: }
20: }
21: }
Finally here is an example of actually using it
1: class Program
2: {
3: public static EventManager<Location> LocationHandler = new EventManager<Location>();
4:
5: static void Main(string[] args)
6: {
7: LocationHandler.Subscribers.Add("Repository",new SaveLocation());
8: LocationHandler.Subscribers.Add("Twitter",new TweetLocation());
9:
10: Location currentLocation = new Location(){Lat = 111,Lon = -121};
11:
12: LocationHandler.Notify(currentLocation);
13:
14: Console.ReadKey();
15:
16: currentLocation.Lon = 1211;
17: LocationHandler.Subscribers.Remove("Twitter");
18: LocationHandler.Notify(currentLocation);
19:
20: Console.ReadKey();
21:
22:
23: }
24: }
A real world example of using “Observer Pattern” is a service bus like NServiceBus or MassTransit, where an event driven application needs to send messages to one or more subscribers.
As always here is a link to the project source.
Wednesday, May 12, 2010
Another walk in the cloud with Amazon Web Services
Like I wrote in “A walk in the Cloud” the Amazon cloud can be accessed though a web service so you have the option of rolling your own tools or using their API lib. The has SDK has defiantly improved and the install process is a lot easier now. Before you had to download the source, build the project, etc, now all you have to do is download AWSSDKForNET and install it. This adds the Clint to your GAC, and add templates into Visual Studio, if you still want to see what they are doing under the hood you can still download the source.
Amazon may not provide you with any tools but there are a few free ones that work fairly well. CloudBerry Explorer is a fairly solid tool for managing your S3 storage, it looks kind of like an ftp client and it lets you manage multiple accounts, create buckets, upload/download content, generate web URLs(http and https), search, etc. Another client is the Firefox plug-in S3Fox, basically the same as CloudBerry but it runs in Firefox.
Pulling data from S3 is relatively simple, this is a code sample for pulling your list of buckets, then building a list of links to the images in each bucket
1: AmazonS3 s3Client = AWSClientFactory.CreateAmazonS3Client(
2: ConfigurationManager.AppSettings["AWSAccessKey"],
3: ConfigurationManager.AppSettings["AWSSecretKey"]);
4:
5: ListBucketsResponse response = s3Client.ListBuckets();
6:
7: foreach (S3Bucket bucket in response.Buckets)
8: {
9: HtmlGenericControl header = new HtmlGenericControl("div")
10: {
11: InnerText = bucket.BucketName
12: };
13:
14: DivlistOfImages.Controls.Add(header);
15:
16: ListObjectsRequest request = new ListObjectsRequest
17: {
18: BucketName = bucket.BucketName
19: };
20: ListObjectsResponse imageList = s3Client.ListObjects(request);
21:
22: foreach (S3Object s3Object in imageList.S3Objects)
23: {
24: HtmlAnchor imageLink = new HtmlAnchor
25: {
26: InnerText = s3Object.Key
27: };
28: string bucketName = bucket.BucketName;
29: string objectKey = s3Object.Key;
30: GetPreSignedUrlRequest preSignedUrlRequest = new GetPreSignedUrlRequest
31: {
32: BucketName = bucketName,
33: Key = objectKey,
34: Protocol = Protocol.HTTP,
35: Expires = DateTime.Now.AddDays(7)
36: };
37:
38:
39: imageLink.HRef = s3Client.GetPreSignedURL(preSignedUrlRequest);
40: DivlistOfImages.Controls.Add(imageLink);
41: }
42: }
With this you can have your content be managed by another department with a tool like CloudBerry and remove the work of updating images and other forms of content.
As always here is a link to the sample code project
Thursday, April 15, 2010
Taking Telerik’s Just Mock for a test drive
HttpContext Test
Test: Can I mock HttpContext, set a value, and get the value, in this case Error 1: ErrorLoger target;
2: private const string TestError = "Test Error";
3: public MockILogger MockLogger;
4:
5: [SetUp]
6: public void Setup()
7: {
8: target = new ErrorLoger();
9: HttpContext mockContext = Mock.Create<HttpContext>();
10: Mock.Arrange(() => mockContext.Error).Returns(new Exception(TestError));
11: target.Context = mockContext;
12: MockLogger = new MockILogger();
13: target.LoggerInterface = MockLogger;
14: }
15:
16: [Test]
17: public void LogError_SetsLoggerMessageEqualToContextErrorMessage_Test()
18: {
19: target.LogError();
20:
21: Assert.AreEqual(TestError,MockLogger.Message);
22: }
Result: Just Mock crashes when it tries to mock HttpContext.
SqlConnection Test
Test: Can I mock a SqlConnection and open a connection with out really opening a connection.1: private DataRequest target;
2: private bool SqlConnectionOpened;
3:
4: public void SqlConnectionOpenedCalled()
5: {
6: SqlConnectionOpened = true;
7: }
8:
9: [SetUp]
10: public void Setup()
11: {
12: SqlConnectionOpened = false;
13: target = new DataRequest();
14:
15: var mockSqlConnection = Mock.Create<SqlConnection>();
16: Mock.Arrange(() => mockSqlConnection.Open()).DoInstead(SqlConnectionOpenedCalled);
17: target.Connection = mockSqlConnection;
18: }
19:
20: [Test]
21: public void GetUserList_Test()
22: {
23: List<string> actual = target.GetUserList();
24: Assert.AreEqual(true, SqlConnectionOpened);
25: }
Result: Just Mock was able to create the mock without crashing but when I try to set alternate functionality to the Open method, recording that I called Open, it crashes saying invalid connection string. My question is why does it care about a connection string when I’m setting behavior, unless I’m missing how to set this up.
Conclusion
As you can see in the examples the syntax is nice and simple, unfortunately Just Mock failed to pass either of my test and to be honest I’m not surprised, it’s in early beta and I tested it against the hardest problems I can think of to solve, something that none of the other mocking frameworks I have looked at even attempt.What really impressed me was that while working on this I tweeted about having problems and within a couple of hours @hkosev (Hristo Kosev) from Telerik, who isn’t one of my followers, tweeted me asking what I was doing to get the errors and asked me if I would mind sending him the source for what I was doing so they could solve the problem, without even asking for help, very nice.
As always here is the link to my source code.
Sunday, April 4, 2010
Using what works
What’s with the hating, can’t we all just get along? The agile guys vs. non-agile, Windows vs. Mac vs. Linux/Unix, and we can’t forget the language wars. So why do we get so entrenched in the belief that the way we do it is right and everyone else is wrong; call it ego, pride, or something else, it doesn't really matter, why do we do it. By nature we are problem solvers so why do we have such a hard time accepting other’s ways/tools for solving problems?
Agile vs. Non-agile
Having worked in both agile and non-agile environments, I have to say I like agile, I think if done right for most development environments it has a lot of advantages, the key here is if it’s done right, and for most environments. If your daily scrum meeting are taking more then 30min, there is strong possibility your doing something wrong. On the other side with a few exceptions, the idea of specifying every feature your project is going to have before anything is written is, well naive at best. At the patterns and practices conference Billy Hollis make some comments that really upset a fair number of people in the agile community, and in return they responded with that Billy doesn't know what he’s talking about, etc. To this my thought was your both right and at the same time wrong.
Agile doesn't work for everyone, some teams just can’t do it, and that’s ok, you shouldn’t feel bad because your not doing it the way the “cool kids” are, the important thing is to find a development methodology that works for your team. Having said that, there are a lot of practices that have come out of the agile methodologies that can greatly benefit the non-agile groups, I don’t care what you say unit testing benefits everyone, having a build deploy server helps everyone, etc.
To the agile zealots out there, agile is A WAY to develop successful and maintainable software, it’s not the only way. Lots of very successful projects have been written with non-agile methodologies and lots of very unsuccessful projects have been written using agile. Everything has it’s advantages and disadvantages, let’s face it the larger your team the harder agile gets. As in most things zealotry is wrong, I don’t care how good the dogma is, it’s not more important then getting the job done, the most important thing is to get the job done, so find what works for you and do it.
Windows vs. Mac vs. Linux/Unix
The OS fan boy wars are a never ending battle between people who for the most part really just don’t get it. So let’s break down the fan boys:
- Windows fan boys: For the most part they have never used anything but windows, everyone else uses windows so it must be the best at everything so it doesn't matter what Microsoft provides it’s the best.
- Mac fan boys: Their like the popular kids in school that you don’t understand why their popular because no one really like them that much, and then you add on a devotion that is almost like a cult with Steve Jobs as their messiah. Some are disillusioned windows fan boys others where born into the Mac fold and all have a limited understanding of what’s out there.
- Linux/Unix fan boys: Seeing themselves as elite or ultra power users they look down at windows and Mac users as lower life forms, yet at the same time they are constantly defending their OS.
I must make the disclaimer that I am a former Linux fan boy and to this day I see a lot of faults with windows, but on the flip side I see a lot of improvements that have been made in windows that make it a lot more attractive, but I still really like Linux, funny that I’m a .NET developer. All three OS have their strengths and their weaknesses and all three work as a development platform, albeit some are better at some development stacks(.NET is easier on windows) and some development requires a specific OS(if you are doing IPhone development you need to have Mac), in all honestly all three work well and it really comes down to what the user likes out of their OS. I have known some very talented graphic artists that don’t like Macs and have been very frustrated by having to use one, on the flip side I have a Ruby developer friend that really likes Macs.
So in the end it really comes down to is how can we make what we have work for what we are doing, and choosing the right tool for the job, and for who is doing it verses following some techno dogma.