December 24, 2007
Annika Joyce Humility Brandsma
Born today (Dec 24, 2007) at 11:33 am. 7 lbs 9 oz, 20.5 inches long.
Both mommy and baby are doing fine.
December 21, 2007
Confessions of a bad web developer
I've been moonlighting with the ASP.Net MVC framework lately. Not a lot, just enough to get acquainted for right now. Yesterday I had my "Road to Damascus" incident. I don't know HTML.
OK, not completely true, I know lots of html tags, table, ul, div, p, a, etc; and I know how to use them without looking things up. More importantly, I know a ton of asp.net controls. What I don't know, specifically, is how they all work.
Like the form tag. I know every Asp.Net page I have ever made has had one of them (and only one, at least as of .Net 1.1 that is all you were allowed). But I don't remember how to use it any more. How to read data from it, pass values from one page to the next. I used to, did it a few times in fact. Then came Asp.Net, and I haven't looked back.
Have I written JavaScript during this time? Sort of. If you count copying code from Google (and testing it of course). Over the years I have large blocks of Googled JavaScript code in existing projects that I've move from page to page. Cut-and-paste is a type of reuse...right? And lately, when my JavaScript requirements have not been Google-able, JQuery has become my savior (more posts on that soon). But I haven't written a JavaScript object, Prototype, or any such tomfoolery since Netscape 4.8.
And just to clarify. I once wrote my own tree control in JavaScript. Or, I wrote one for Netscape 4.04, 4.08, 4.5, 4.75, 4.8, and IE. I never thought I could hate a language until Netscape. Netscape killed any love of JavaScript for me.
But now with Ajax on the scene I can't do without it anymore. And as cool as the Asp.Net Ajax Library is and all of the things that the control toolkit can do for you: without a bit of JavaScript muscle, it just isn't going to work for you. Take a look at the Google Maps API and tell me you aren't thinking of things that could be done with it. But it ain't going no where without some JavaScript know-how.
CSS I have come to terms with. I know the difference between .tag and #tag. I've written a hover or two. But there are still unknowns there as well. I still visit w3schools regularly, and spend way too much time with FireBug and Fiddler. And CssZenGarden -- that is just beyond me right now.
But even in Asp.Net. How does a post back work? How is it that a button click is hooked up to an event handler? I'm a firm believer that their is no "magic" in programming. Post back is magic to me. Maybe once years ago I knew, but not anymore.
But things like: if you have a table, and every row has a check box on it, on the server side, how do you know which check box is which? Heck, how do I figure that out on the client side with JavaScript? The magic is ViewState, I know. But...
That really is the beauty of WebForms. It provides a nice insulating coat that insulates you from all of the goo that is html and JavaScript. ViewState is my friend. But what does this have to do with Asp.Net MVC? Absolutely everything.
Asp.Net is a stripped down version of web development with .Net. ViewState: gone. asp:Button: hope you are familiar with submit. The cozy jacket is gone and has been replaced with a wind breaker. All those old techniques that we threw away with our last ASP page needs to be resurrected.
Being how I already live in a cold climate, I know that the biggest part of working in cold weather is to acclimated to the temperature. Part of it as well, is knowing that you have to work in the cold climate. So this isn't time to put things off. Spring is still a ways off. So, for Asp.Net WebForms developers, that means re-familiarizing yourself with a few technologies that we all thought we didn't need to know that well:
- XHML
- CSS
- JavaScript
- JASN
- JQuery
- Asp.Net Ajax framework
I'm not going to specify particular books. I don't have time for that, and you can search Amazon as well as I can. Actually, I bought a couple of these books for $1 at Hastings near my house. Worth every cent.
Also worth noting what is not on my list: XML. The language we thought was the lingua franca of the web. I've had enough XML, and the Asp.Net Ajax library talks via JASN (which is much smaller). So XML is out for me. And that is fine, I think, there is enough to learn as is.
December 20, 2007
ReSharper 3.1 Released
I am a ReSharper addict. I admit it. I have this habit of upgrading my ReSharper every time JetBrains releases a new version.
Speaking of which: ReSharper 3.1 is out and ready for download.
Or you can read the release notes.
But, if you are hoping this will add C# 3.0 support...it doesn't. That is supposed to be next month, in ReSharper 4.0. BTW, there is a small note on the web site, if you buy ReSharper 3.0 now, you will get a free upgrade to ReSharper 4.0.
November 14, 2007
There is no tooth fairy
I don't claim to have a normal house. We don't strive to be different, but normal just doesn't always happen in our place.
One such oddity is the tooth fairy. Our kids don't believe in Santa Claus, the Easter Bunny, or Halloween...but the tooth fairy is another matter. You don't just mess with the tooth fairy.
This has now come to a head with our six year old Lily loosing teeth faster than an old school hockey player at a triple header. She just lost one tooth yesterday, and three others are currently loose and ready to go at any time. Should make for a fun Christmas this year.
Now combine that with two parents that are a bit frazzled right now. The wife is due in a month, and dad is busy dealing with mom being due in a month -- plus Thanksgiving, plus Christmas (minus Santa Claus) -- the Tooth Fairy has fallen behind in its duties.
At this point, Lily figured it out. Luckily she is a good sport, and still willing to play along. For the third night in a row, her tooth will be in a zip lock bag, underneath her pillow.
Hopefully the tooth fairy doesn't need further directions than that.
November 12, 2007
Joining Elegant Code
After three years on my own domain (going strong since Aug 2004), I'm moving my technical content to ElegantCode.com, joining my friends David Starr, Jason Grundy, and David Betts.
Note: I'm only moving my technical content to ElegantCode, which gives me four blogs to keep up to date. I need to do some content separation just to keep things straight. So here it goes:
- ElegantCode: Software development related posts
- BSDG.org: Industry news, user group updates
- BoiseCodeCamp: code camp news (yes, that does happen)
- ChrisBrandsma.com: updates and musing from family Chris Brandsma.
Actually, I do think this is a good thing, put in a little bit of virtual separation for all of my mental parts. Plus, as a side benefit, it will make my blog a whole lot less confusing to the rest of my family.
Also, for the of my friends and family: join FaceBook and find me there.
November 05, 2007
Visual Studio 2008 and .Net 3.5 due this month
This has been making the rounds for about a week now, but Visual Studio 2008 and .Net 3.4 is expected to be released this month (November 2007).
More info below:
http://blogs.msdn.com/somasegar/archive/2007/11/05/teched-developer-in-europe.aspx
http://msdn2.microsoft.com/en-us/vstudio/products/default.aspx
Also there is a rumor that the Microsoft ASP.Net MVC framework will also be released REAL SOON (meaning: when they feel like it, but probably after the Visual Studio 2008 launch -- and they will probably change the name).
For those of you who don't know: the Asp.Net MVC Framework is a MonoRail/Ruby On Rails-esk web development framework for Asp.Net. It does not use WinForms at all. This actually has a lot of people really excited right now. Phil Haack and Rob Conery both left their current jobs for Microsoft just so they could help work on this.
Haack must be the single greatest last name for a developer....
Scott Hanselman (now a blue badge Microsofty) has two videos from the ALT.NET conference last month with Scott Guthrie and himself.
http://www.hanselman.com/blog/ScottGuMVCPresentationAndScottHaScreencastFromALTNETConference.aspx
October 29, 2007
Kids pictures
October 27, 2007
Best Practices Discussions and Debates
I think I have learned something today that I was previously unaware.
Starting a discussion about software development best practices is akin to talking about parenting techniques with a group of mothers. Most will patiently listen, but at least one will get super defensive and tell you in detail about why that wouldn't work with their baby.
I have relatives who are also very argumentative, in that they just love to argue. The funny part is that they will argue about things THEY AGREE WITH! Unfortunately, they are too bent on arguing that they don't care that they agree.
I see this happen on blogs all the time. And while I think that blogs are great ways to spur discussion, they are not great ways to HAVE a discussion. User groups, phone calls, and hallways are all vastly superior environments for a discussion.
In my case, I have a commenter on my blog post about best practices that is doing a wonderful job of arguing some of my points, all while telling me I'm wrong. We disagree on one point: Developers should have their own copy of the database they are developing against, and developers should have access to all source code and software need to do their job.
I think the reason the anonymous poster and I are not able to agree is because we really aren't able to talk to each other about the ideas. Plus, I have a strong feeling we are separated by a common language (we have different definitions of the same words). More than likely we agree on the software, we just don't agree on the terminology.
As far as the database part: there are a ton of ideas hidden in that statement that are not easily expressed. There are scripts that extract the meta-data out of a database, source control that houses that script, continuous integration for verifying all of the changes work to both code and database scripts, creation of development data, etc.
Then the kicker: 90% of that is automated. I really don't thing the anonymous submitter saw that point. In fact that should be a blog post in itself. He/she saw it as another backbreaking task the developer would have to maintain by hand. But if you do it right, it isn't. Updating the database scripts is as simple as running a batch file. And not updating the batch file and then running it, no -- just run it. The batch file creates the scripts for creating the entire database. This should take 5-30 seconds. Then you are ready to go.
As I said, there are a lot of aspect to this that were not mentioned in this post or the previous post. But blogs are there to START discussions, not to have them.
Elegant Code expands
I'm hoping this is the start of a new vibrant community, as is it is comprised of some of the best and brightest that I know anyway.
ElegantCode.com is expanding beyond a one man blog. Now included is a group of managers, Scrum Lords, coding architects, non-coding architects (the most dangerous type of architect), and top notch developers.
I'm excited to see if this takes off.
October 26, 2007
Rob Conery (SubSonic) is joining Microsoft
This is great news, Rob Conery has been hired by Microsoft.
Even better news: Microsoft hired him to work on SubSonic.
Better news still: SubSonic is staying open source.
I'm trying to find a negative here...and failing at it.
Cheers.
October 25, 2007
Rhino Mocks 3.3 Released
Straight from Ayende, Rhino Mocks 3.3 has been released. The peasants rejoiced. Well, I rejoiced anyway.
New features:
- Adding support for calling void methods using Expect.Call
- Adding remoting proxies.
- Made IMethodOptions generic. Allows compile time type safety on Return.
- Adding a PublicFieldConstraint
The biggest change for the day to day developer: you can now use Expect.Call on methods that return void. This wasn't a big problem per-say, but it did cause a lot of confusion. You would see code mocking a function call like this:
Expect.Call(mockObject.MyFunction()).Return(1);
Then your method returning void would look like this:
mockObject.MyMethod();
Not the most consistent API. Now that should be fixed. So mocking a method will now look like this:
Expect.Call(mockObject.MyMethod());
Rhino mocks is on my list of source code to read as soon as I'm finished going through SubSonic.
Have you thanked Ayende today?
October 20, 2007
Software Development Essential Practices
I was in an interesting discussion last night: what software development practices do you consider essential?
While opinions varied, I think there was some consensus on a few items. In my list I also include some tools. Some of these were mentioned by the group, but consider them my own additions. Also, I am making this list specific to .NET, but the list applies to just about every language.
Universally agreed Practices
- Source Control (1)
- Subversion
- VSTS ($)
- Vault ($)
- Local Development -- Every developer should have everything on their computer to run the system. This includes all of the software and all of the source code.
- Bug Tracking - nuf said. There are to many tools available to list here.
- TDD - Test Driven Development. There was a little bit of back and forth, but the general consensus was that this should be done.
- NUnit
- MBUnit
- Rhino Mocks (2)
- TypeMock ($) (2)
- NMock (2)
- ORM - Object-Relational Mapping
- NHibernate
- SubSonic - My person favorite
- LINQ to SQL - not yet, but I feel this should be on the list.
- LLBLGen ($) - Not free, but I've heard many good things about it.
- More
- Continuous Integration - Simple process that sits on a server and waits for things to get checked into your source control system. When it sees something new, it gets all of the latest source code, compiles it, and runs all of the unit tests. If there are any problems anywhere in that process it alerts the users (email, desktop icon, wave red flag, etc). (3)
- One Step Build - it is unbelievably cool to be able to click one button and have your entire project compile, run all tests, and possibly create an install in one step. Personally, I do like it, but with the current set of tools this is one of the hardest parts to setup.
- MSBuild
- Nant
- BooBS/Bake (Ayende please, please, please change the name to Bake. As cool as a project named BooBs could be -- I don't want to start an HR nightmare)
- FinalBuilder ($)
- Visual Build Pro ($)
Highly thought of but non-essential practices
- IOC - Inversion of Control - Everyone seemed to agree it was a good idea...but not actually essential.
- Castle Windsor - DotNetSlackers has a nice series on using this.
- Spring.Net
- StructureMap
- ReSharper ($) - Not a best practice per say, but it sure does make life easier. (4)
I'm sure I have missed some tools in the list, but it is the practices that are more important anyway. But if you put a comment about any tool that I missed I will add it to the list.
(1) Source Safe was notably not in the list. While I don't like it either, it is better than nothing. But if your team is greater than 5 people or you have multiple people working on the same project you really should look at one of the other products on the list.
(2) Not a unit testing library, but a Mock Object library. Pick a unit testing libarary (NUnit, MBUnit, XUnit), then pick a mock object library (Rhino Mocks, TypeMock, NMock) to use with it.
(3) I really need to talk about continuous integration more. But it is one of those things that leads you down a path. First you add source control, then you start adhering to separation of concerns, then you start unit testing and mocking more, then you add continuous integration, and then one step builds are all part of the mix. One best practice leads to another, but they don't make a bit of sense without some of the prior pieces.
(4) If you are a Code Rush person instead of a ReSharper person -- carry on, you are in good company.
($) The cost money - not just beer, but may have free version versions as well.
October 17, 2007
Testing for Exceptions with NUnit
a. Make sure an exception was thrown
b. After it was thrown, make sure nothing else happened.
This is what happens when you throw exceptions from SQL Stored Procedures.
The Problem
The standard way of checking for exceptions in NUnit are thus:1. ExpectedException attribute on the test method
2. Have your own try/catch block in your test method.
The problem with option 1 is that no assertions can be checked after the exception. The code runs until the exception is thrown, then you are done. That isn't what I need.
The problem with option 2 is that it is ugly. Yes, I'm being a cry baby here. I think the try catch throws more code in the test than I think should be there.
My Solution
So I created a new method called ExpectException. Here is the code:1: public T ExpectException<T>(MyMethod method) where T : Exception
2: {
3: try
4: {
5: method.Invoke();
6: }
7: catch(T e)
8: {
9: return e;
10: }
11: return null;
12: }
So now in my case, I have a stored procedure that throws an SqlException. I want to call the method and return the exception so I can check the exception for specific values (make sure the message is correct). Also, if any other exception is thrown, say a Exception -- not a SqlException, the test will fail.
Here is my new code:
1: SqlException e = ExpectException<SqlException>(delegate { ReplaceUnitCall(oldUnit, newUnit); });
2: Assert.IsNotNull(e);
So as long as you are familiar with anonymous delegates, this is a pretty nice solution -- to me.
Current favorite ReSharper shortcuts
Ctrl-- (control-minus): return cursor to previous position.
This is especially useful if you just had ReSharper create a field or do any number of other items that will automatically jump the cursor to some other place -- be it in the current class, or another file. Very useful. I seem to use this most when I'm creating properties.
Ctrl-Alt-V: Introduce Variable.
If I type:
System.IO.File.ReadAllLines(filename);
Then hit the Ctrl-Alt-V, it will create a variable for the return of the function. So you will end up with this:
string[] lines = System.IO.File.ReadAllLines(filename);
Ctrl-Shift-N: Find file by name
I'm used to using Ctrl-N, find type by name. But usually what I was looking for was find file by name. If your classes have the same names as your files, not a big difference, but there is a difference.
What I'm hoping for in the next version of ReSharper
Enhanced Interface support. If my class has an interface, I want to be able to right-click on a method that is not in the interface, and have ReSharper automatically add the method to the interface.
Update:
From my comments I see that this feature already exists, it just has an odd name and no short-cut. The feature is "Push member up".
So put your cursor on a method/property, right-click->Refactor->Push Member Up and you will get a dialog for adding the member to an interface.
The name is the odd part, but if you do think about all the implications, it does make sense. Anyway, the more you know... Thank you Ilya Ryzhenkov
October 05, 2007
MSDN Presentation and the Demo Gods
Everyone who has ever done a presentation in front of a large group of people, with a computer and powerpoint, will have some crack about appeasing the demo gods.
Yesterday I gave a presentation on LINQ for the MSDN Event here in Boise, and apparently I pissed the demo gods off something fierce.
I get up on stage, hook up my laptop, start everything up (powerpoint and VPC) plug in the projector's cable, and...
I hear a lot of beeping. I open Windows explorer and suddenly all of my icons start expanding to enormous proportions. My PowerPoint presentation will not move past the first slide.
I reboot. Restart PowerPoint and VPC. I hear beeping again. I'm supposed to have started 5 minutes ago. Not good.
I start talking anyway. LINQ has a lot to cover. Philosophy, data access, xml, objects, language enhancements, etc.
It is as I start talking, sans PowerPoint, that suddenly the crowd goes: "Ohhh", with a couple of faint "Doh!"s in the mix. My laptop had just Blue Screened.
The demo gods were not happy with me.
So, reboot again, and keep talking about LINQ. Needless to say I was a bit flustered this time, but I kept moving (I had a time limit). Luckily, my laptop booted just fine this time, everything loaded, I was able to breeze through a bunch of slides and get the VPC started and start the actual demo.
After that everything went mostly well. I covered all of my demos, and they all worked. I also knew which of my demos would take a long time to run, and used that time to ask the audience for questions -- and they had a lot. The biggest question to come up, repeatedly, had to do with the misconception that LINQ was only about database access. It isn't, LINQ is about data manipulation with ALL of your data.
The only thing I missed: each of my demos had two parts. Showing how things are probably being coded now, and then showing how they are done with LINQ. I skipped the first part, trusting the audience to believe me that they worked. I don't think that was a bad thing. They came to see new stuff, not old.
Anyway, I'll have to figure out what I need to sacrifice for the demo gods before I give another presentation.
And if anyone managed to get a picture of my blue screen, I would love to have a copy of it.
Start everything back up.
September 24, 2007
NMock as compared to RhinoMocks
At a recent developer group meeting I was asked why we were using Rhino Mocks instead of NMock. He also pointed out that NMock had minor api rewrite that made it nicer to use.
My answer was that Rhino Mocks was standardized before I started with my current team, but I would look into NMock. It never hurts to comparison shop.
So to get get started. If you are not familiar with either framework, I suggest looking at their quick start guides:
Rhino Mocks Quick Start
NMock Quick Start
How to mock an object.
NMock: |
Mockery mocks = new Mockery(); |
Rhino Mocks |
MockRepository mocks = new MockRepository (); |
So far so good, no real difference between them. Rhino Mocks has a minor more typing involved, but frankly, I have code templates for all of that anyway.
Which is better: Tie. They both work just fine.
But lets backup a second. What does IMyInterface look like. This is what we are going to work with:
public interface IMyInterface
{int MyProperty { get; set; }
int Add(int i, int j);void MyMethod(int i, int j);event EventHandler<EventArgs> MyEvent;
}
Mock libraries create fake objects to send to your real objects. Your real object can call the fake object's methods and properties, but you have to give the Mocked objects their values (this is called setting expectations). First to note: you aren't testing the mocked object, you are testing the object calling the mocked object.
Anyway, if you need more info on where or when to use a mocked object I'm sure Google will have many excellent examples for you.
OK, so now that we have that part set, lets move on.
Set and get a property:
Quick note: this is telling the mocked object to expect the property to be set to a value. We are not actually setting the value. Also, when we get the property, we have to tell the mock library what to return.
NMock |
// set the property |
RhinoMock |
// set the property |
OK, both sets of calls are supposed to be equivalent. The first thing to notice is that whatever typing saving we had in the construction of the mock object has not been completely lost. But I still think amount of typing it takes to do something is somewhat shallow, so lets dig deeper into the syntax.
As you can see, in NMock nothing is implied. The properties setter will be called exactly once, and the value will be retrieved exactly once. In Rhino Mocks, that detail is implied. But more troubling with NMock is the reliance on using strings to specify which property is being called. Where as with Rhino Mocks, you are using the mocked interface itself.
So if I change the name of my property on the interface, both tests will fail. But with Rhino Mocks it will fail at build time, NMock will have to wait for run time. Also, if I'm using Find Usages (a feature of ReSharper) to find every place that MyProperty is being used, it will pick up the Rhino Mocks code, but will not pick up the NMock code. To me that is a usability issue.
Rhino Mocks wins.
Next test: Call a function and return a value; call a method
NMock |
Expect.Once.On(aMock).Method("Add").With(1,2).Will(Return.Value(3)); |
Rhino Mock |
Expect.Call(aMock.Add(1,2)).Return(3); |
The nice thing here is that both libraries are consistent in their approach. I still don't like how you have to specify the method names by a string though. Also, the Will(Return.Value()) does not seem natural to me.
But I do have to nock Rhino Mocks on how it does methods a bit. If there is nothing to return, you just call the method. If there is something to return you use the Expect.Call method. This does not seem as consistent as it should.
Rhino Mocks wins.
Handle multiple calls
This is actually kind of interesting. With the NMock api, specifying multiple calls is actually quite natural, where as Rhino mocks seems like a hack. In NMock the Expect function has the following options:
- Exactly(int count)
- AtLeastOnce
- AtLeast(int count)
- AtMost(int count)
- Between(int start, int stop)
- Never
With Rhino mocks there are two ways to do this, but in both cases you use the Repeat object. Remember if you are calling something that doesn't return a value, you don't have to use the Expect object. So Rhino Mocks adds the LastCall method. LastCall modifies the expectations for the last call you made to a mocked object.
But you are using the Repeat object itself. And here is what you get with that:
- Any()
- AtLeastOnce()
- Once()
- Twice()
- Times(int count);
- Time(int min, int max)
- Never()
First thing I will note between Rhino Mocks Repeat and NMocks Expect is that they are mostly equivalent. I would like the wording of NMocks Between over the Rhino Mocks Times function though. But, Rhino Mocks is missing the AtLeast(int count) function.
So if I wanted to call both methods of my interface at least 2 times, here is what it would look like.
NMock |
Expect.AtLeast(2).On(aMock).Method("Add").With(1,2).Will(Return.Value(3)); |
Rhino Mocks |
Expect.Call(aMock.Add(1,2).Return(3).Repeat.Times(2, int.Max); |
As much as I love Rhino Mocks, NMock is the winner on the repeating calls front. The syntax makes more sense and is easier to follow than Rhino Mocks. But to fix Rhino Mocks should be hard. Add an AtLeast function and make it possible to use the Expect function on methods with no return values and I think it is there.
But I still don't completely like NMock as either. I don't like it that you have to set the number of times something is being called before you tell the mock library WHAT is being called. I don't thing that helps readability at all.
Winner: NMock.
Raising Events
All of us have this. Small little routines that are only used when an event is raised. So we need a way to mock the event so we can test that code.
NMock |
// First read this article: http://becomingagile.blogspot.com/2007/03/raising-events-in-nmock-20.html |
Rhino Mocks |
aMock.MyEvent += null; |
Can you raise events in NMock: Yes. Is it directly supported: No.
Can you raise events in Rhino Mock: Yes. Is it directly supported: Yes.
Now working with events can be a bit hard. Working with events on a fake object takes a bit of mental yoga to really make sure you understand what is going on as well. I am not overly ecstatic with how Rhino Mocks does events...but it is supported without doing Google searches and writing another class.
Rhino Mocks wins.
Throwing Exceptions
We also have code that catches exceptions. How often do you test that code? You should. Here is how you do it.
NMock |
Expect.Once.On(aMock).Method("MyMethod").With(1,2) |
Rhino Mocks |
Expect.Call(aMock.MyMethod(1,2)).Throw(new Exception("Hi there"); |
So again, both do the job. But I still like the Rhino Mocks terseness better.
Rhino Mocks wins.
Summary
In the end I will stick with Rhino Mocks. The Method(string methodName) style still just kills it for me because it breaks compile-time checking, and the fact that you can't set method parameters in a type safe way. If I change a something in an interface I want that to break my build -- even in my test code!
Will NMock do the job: yes. But I still think Rhino Mocks does it better.
September 21, 2007
Rhino Mocks: New syntax
I was browsing though the Rhino Mocks documentation when I found there is an entirely new way to setup a test with mocks.
The old way:
[Test]
public void MyOldTest()
{
// Record your expectations here
Expect.Call(myObject.MyProperty).Return(1);
mocks.ReplayAll();
// do your work here
int i = myObject.MyProperty;
// check you values
mocks.VerifyAll();
Assert.AreEqual(1, i);
}
The new way:
[Test]
public void MyNewTest()
{
// Record your expectations here
using ( mocks.Record() )
{
Expect.Call(myObject.MyProperty).Return(1);
}
// do your work here
int i;
using ( mocks.Playback() )
{
i = myObject.MyProperty;
}
// check you values
Assert.AreEqual(1, i);
}
Now, the most obvious thing about the two code examples is that the new way takes more lines of code. But is that really a valid metric? Not always.
The using statements make a nicer differentiation between the setup and the execution. In the old way, the VerifyAll() method was your differentiator. Sorry, but from four feet back, VerifyAll() just looks like another method. The new way, with the 'with' keyword makes for easier transitions from "what we expect to occur" to "Ok, lets do this thing", and "make sure everything worked as planned."
But wait, there is more!Now for those of you who think you can NEVER have enough ways to do the same thing, and think that anonymous delegates are the GREATEST THING EVER! There is something for you too.
It is the With statement which gives you a fluent interface (which is all the rage on the blogosphere these days). Anyway, it looks like this:
int i;
With.Mocks(mocoks).Expecting( delegate
{
// Record your expectations here
Expect.Call(myObject.MyProperty).Return(1);
})
.Verify(delegate
{
// do your work here
i = myObject.MyProperty;
}
}
// check you values
Assert.AreEqual(1, i);
Now normally I am all in favor of fluent interfaces. SubSonic, LINQ, and Lambda are all great examples of this. But I worry that the fluent style interface is trying too hard in this case.
That said, sometime soon I'll probably see a use for it and it will be wonderful. But until then.
So now you have seen three ways of doing the same thing with one mocking library. That should be enough to keep everyone busy for a while.
September 20, 2007
No Silverlight for you
There are always problems to be found when dealing with new technologies. Currently, I'm playing with Silverlight.
My first project with silverlight was to convert my header (the flaming computer at the top of the page) to a silverlight header. Rev one would be a straight, look alike, conversion of the existing header. The only really cool part is that I would be able to change the text on the header. I can't do that right now because all of the text is an image.
And I did it. It works beautifully...except on my blog. All I get from there is a blank box.
A bit of digging with FireBug and it appears my web host is blocking all xaml files. And you know you are in for a bad day when you call support and they say "What is xaml?" Answer: it is just like Flash.
Oh well, they are supposed to get back to me today. We will see how that goes.
If you want, check out my sample page. Hopefully it will be working in the next day or two.
September 13, 2007
2 Days in Boise
Sept 6 is the bottom picture, Sept 7 is the top picture.
The top picture, from Sept 7, is what I would consider a hazy day in Boise.
The bottom is about as bad as it gets. On days like that you can really smell the smoke in the air. That is the type of day that you see asthma sufferers looking for their inhalers.
Now I know that my blog has a reference to fire on it...but this really isn't what I was referring to.
September 11, 2007
Boise MSDN Event on Oct 4
Thursday, October 04, 2007 1:00 PM - Thursday, October 04, 2007 5:00 PM Mountain Time (US & Canada)
Welcome Time: 12:00 PM
Theater - Edwards Boise Stadium 21
7701 Overland Road
Boise Idaho 83709
United States
Language(s):
English.
Product(s):
ASP.NET, Office, Visual Studio and Windows Vista.
Audience(s):
Developer.
Event Overview
MSDN Events are free, live sessions designed to enhance your coding skills and make your life a little easier. By attending you’ll get up –to-the-minute technology delivered by seasoned developers and have lots of time to network and ask questions. Chat with your fellow developers get the latest coding tools and tips and learn how to create rich new applications. Register today for a free live event in your area and get the hands on knowledge you need. For more information visit: http://www.msdnevents.com.
September 05, 2007
JQuery is just cool
a bit these days. I'm not exactly a Javascript expert by any means, but
JQuery is just cool -- and a bit odd. We know that Javascript is a functional
language, but it does have some object-like stuff you can do with it as well.
But everything is still a function. JQuery has it's own function that you use to
access everything in it as well. The function is $. I'm not kidding, it is $.
Instead of a JQuery function, we have the function formally known as JQuery now
called $. Just wonderful. Then you find out it plugs into the CSS classes. What
now? How the heck? But a typical script you will write looks like this:
$(document).ready(function(){
$("a").filter(".clickme").click(function(){alert("Hi there");}).end() });
Here is what is going on with that statement:
- (first $) Find the document node, set a function to the ready() function (that
lets you know everything is loaded) - (second $) Find any link ( <a>) with a css classes named "clickme" (e.g.
<a class="clickme">) - Override that links click function.
- When the link is click display "Hi there" to the user in a message box
So what you can do with that silly $ is pretty darn cool. Plus there are
plug-ins for it. I have an ASP.Net GridView on my form. In this case I can
display all of the data on the grid without paging or anything special. But I
want to sort the data. There is a JQuery plug-in called
TableSorter that you can use. This will
sort any table with a theader tag. Which would normally work fine as is, but the
GridView doesn't output a theader tag without some modifications. The following
C# does the trick (note: did not come up with this code, I found it on
DotNetSlackers):
private void MakeGridAccessible(GridView grid)
{
if (grid.Rows.Count > 0)
{
grid.UseAccessibleHeader = true;
grid.HeaderRow.TableSection = TableRowSection.TableHeader;
grid.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
Use that function right after you load your data into your gridview. Next you
need to setup your javascript. You have to include JQuery.js, and
jquery.tablesorter.pack.js, then call tablesorter on your table via javascript.
This works for a GridView named grdData:
And done. Really, that is it. We are done. You can click on any of the headers
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.tablesorter.pack.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
$("#grdData").tablesorter();
}
);
</script>
on the grid and the grid resorts itself. No other fussing, no ajax calls to get
more data. I like it.
August 30, 2007
Performance Testing Guidance for Web Applications
Free download? Got that.
Printed version? That is why you bought a printer.
Free time to read it? I can't help you there. Stop watching so much TV!
Here are a few other links about people talking about it:
J.D Meier's Blog
Rico Mariani's Blog
Next step: get Ayande to write one of these for NHibernate.
August 26, 2007
Book Review: Practices of an Agile Developer
But that underscores a lot of interest I am seeing in methodology books in general (but that might just be me). At some point you realize that technology ABC really doesn't matter that much. Ruby, PHP, ASP.NET, Java -- whatever, pick one and lets get the job done. They all do the same basic things, a few of the details are different, but really, that can be learned pretty easily.
What is changes is your approach to development. Do you use source control? Are you test driven? Do you Scrum? While standing up? How important are any of those things? Why are they important?
There in lies the purpose of Practices of an Agile Developer. Why is it important to have a daily scrum -- while standing -- every day -- and why aren't there a bunch of managers there? And more importantly, what does it feel like when you are getting it right?
Have you ever released software where you feel good about it, knowing that it does what it is supposed to, and that the underlying systems all work? If you haven't, this book will help you get there.
The other beauty of this book, it talks about all of this and it is only 180 pages. That is a thing of beauty. It puts in just enough information to give the idea without belaboring the idea. There is something to be said for treating your reader like a thinking adult.
So what is this book? This is the first book that I would recommend to all software developers that contains almost no code. I also don't care if you have no interest in management -- everyone with 5 years of experience should read it (if you have less than five year, there are probably still have a book list three feet tall to plow through -- this one can wait a bit).
Official site
Amazon
Authors blog
Other books worth reading:
Code Complete 2
Framework Design Guidelines
Mythical Man Month
August 24, 2007
LINQ to SQL: Interfaces on your Domain objects
Note: a domain object, as I am using the term here, is an object that maps column-to-property with a table. For example, if you have a Customer table with an ID and a Name field, you will have a Customer class with an ID and Name property.
I found that it is trivially easy to create. Every object in Linq to SQL is a partial class. So create a partial class that maps to the generated partial (there is no good way to say that, I swear). Then you can use the built in refactoring "Extract Interface" to create an interface that implements the fields in domain object.
The key point that I did not realize is this: you can assign an interface to class in any of the partial class declarations.
So, in Linq to SQL, keeping with our Customer table paradym, your generated partial class will look like this:
public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
Now your other partial class (in an entirely different file) will look like this:
public partial class Customer : ICustomer
Both declarations define interfaces. I didn't know you could do that.
Now the cool part is that the interface can be defined anywhere. If you are trying to create a true separation between layers you will probably want to define it an an assembly other than the assembly that the domain classes are defined in.
Anyway, that is my discovery for today. Have a good weekend.
August 22, 2007
Lily Rides a bike
The joy of having a large amount of pavement and a slight hill (my house is on the top of a hill, and there used to be a tennis court below the house). I got her to coast down the hill with her feet down, then when the pavement flattened out she just started pedaling.
Best part: no having daddy trying to run behind her on his bad knees.
LINQ to SQL: Extension Methods
In my previous example, I showed a sample database that looked like this:
My designer is named "LinqTests.dbml", which is an xml file that is used to generate LinqTests.designer.cs. That is where we find all of the code.
First, we will look at the classes that map to the tables. We have a Customer, Product, and CustomerProduct tables. In each class there is a region named "Extensibility Method Definitions", that is where we are looking right now.
For the Customer class, this is what we see:
Basically, that accounts for two extension methods for every column in a table, plus three more: OnLoaded(), OnValidate(), and OnCreated().
If you can't tell from the name: OnCreated is called right as a new Customer object is created, the OnLoaded() is called after data is loaded into it by Linq to Sql, and OnValidate is called before the code is saved (I think -- since I can't find the code that actually calls it).
The others are for before and after a particular property is set.
Looking into the code further you can see how the code is being called. Here is the constructor:
public Customer()
{
OnCreated();
this._CustomerProducts = new EntitySet<CustomerProduct>(}
new Action<CustomerProduct>(this.attach_CustomerProducts),
new Action<CustomerProduct>(this.detach_CustomerProducts));
The line OnCreated(); calls the OnCreated method (duh!), but if you search the code you wont find anywhere that OnCreated does anything. That is for you to do in a partial class.
Now, to add some business logic to my Customer class for when the class is created or loaded, the code will look like this:
public partial class Customer
{
partial void OnCreated()
{
this.Name = "Billy-Mac";
}
partial void OnLoaded()
{
if (string.Empty( this.Name ))
this.Name = "Jim-Bob";
}
}
Back to basics here. The generated DataContext class also has some Extension Methods
So now you have three extension methods for each table that the Data Context has to manage. One for Insert, Update, and Delete; plus one more for when the Data Context class is created.
Lets take a step back now. Does this really get us anywhere? Before, with generated domain objects (those are the objects that are created to hold data) you could still accomplish all of this using inheritance. The problem with using inheritance is that now you have to use the inherited class and shouldn't user the base class. Worse, there really isn't a good way to tell people not to use the base classes.
Now with extension methods you will have less need to inherit your base domain objects. Now you have the hooks you need to extend your domain objects to fit your business needs. Your developers (or just yourself) now have one set of objects to remember to use. Kind of like one stop shopping.
I've still heard a bit of moaning and groaning about extension methods on the web -- I don't agree with them. I think extension methods are a wonderful addition to C# that will really help fix a need. And what Linq for SQL has done has only helped to illustrate that need for everyone.
LINQ to SQL: Many-To-Many Tables and Joins
So what I've been playing with lately is using LINQ to SQL for querying against Many-To-Many tables. For an illustration, I'll use a table structure like this: (click on it to see a bigger version)
Once imported into your Linq to Sql file type in visual studio, and viewed through a class diagram, you get this:
In my Customer table I have 5 customers, I also have 5 products (Product ID=1 is "Computer"). The CustomerProduct table has about 20 records.
Now we can start having fun with some queries. The question I wanted to answer was: "Which customers have a particular product?". Simple enough.
I found, as with many things, there are multiple ways of getting the same answer. My first query looked like this:
int Computer = 1;
LinqTestsDataContext cx = new LinqTestsDataContext();
var customersWithProduct = from c in cx.Customers
from cp in c.CustomerProducts
where cp.ProductID == Computer
select c;
OK, background note. This code is using the LinqTestsDataContext object to query the Customer table and the CustomerProduct table to find all of the customers with a Computer (product id = 1). What is returned is a IQueryiable
This lovely piece of Linq generates the following SQL code:
{SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[Customer] AS [t0], [dbo].[CustomerProduct] AS [t1]
WHERE ([t1].[ProductID] = @p0) AND ([t1].[CustomerID] = [t0].[ID])}
How do I know that is the SQL that is generated? After I run that line I can mouse over the variable (customersWithProduct) and the tooltip displays the generated SQL. I cant change it (that I know of), but at least I can look at it.
Anyway, that is not what I would call the best SQL I have ever seen -- and it is slow.
Next came attempt two at Linq to SQL. I wrote this:
int Computer = 1;
LinqTestsDataContext cx = new LinqTestsDataContext();
var customersWithProduct = from c in cx.Customers
join cp in cx.CustomerProducts on c.ID equals cp.CustomerID
where cp.ProductID == Computer
select c;
In the previous example, I used that Customer.CustomerProducts object to filter the products. This time I am explicitly joining the Customers and the CustomerProducts tables together in Linq. The only odd part of the query was the "equal" keyword that you have to use in the join.
The SQL generated was much better:
{SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[Customer] AS [t0]
INNER JOIN [dbo].[CustomerProduct] AS [t1] ON [t0].[ID] = [t1].[CustomerID]
WHERE [t1].[ProductID] = @p0}
Look: an actual join. Trust me, this works much faster. The first query took 3.24 seconds, the second took 0.06 seconds. I call that significant. Especially considering the amount of data I am querying (not much). You add some real data (thousand and millions of records) and you could be talking about some significant downtime.
Lots more to discover here. All a matter of time.
August 20, 2007
LINQ to SQL: SQL IN clause
In standard SQL your query would look like this:
SELECT myColumn FROM myTableBut lets put another kink in, shall we. I'm not using LINQ, I'm using Lambda.
WHERE myColumn IN (myVal1, myVal2, myVal3)
It turns out my savior was Contains.
Every generic List ( List
So, when creating a new query via LINQ for SQL in Lambda, you get a IQueryable interface with a Where extension method ...
Oh crap, here is the code, this will take to long to fully explain:
MyDataDataContext cx = new MyDataDataContext(); // from the LINQ to SQL dbmlSo what have we, and what was created. Well, we just used LINQ to SQL to generate a query that will look like this:
IQueryableq = cx.MyTables.AsQueryable(); // creates the query object
ListlistOfData = {1,2,3,4};
q.Where( x => listOfData.Contains(x.MyIntValue));
var result = q2.Select(x => x.MyIntValue);
SELECT [t0].[MyIntValue]There is a @p[number] for every value in the list 'listOfData' above. And to me, the generated SQL is pretty good. That is probably what I would write.
FROM [dbo.MyTable] AS [t0]
WHERE [t0.][MyIntValue] in ( @p1, @p2, @p3, @p4 )
August 03, 2007
LINQ: XElement and Namespaces
So one of the cool new objects you get in .NET 3.5 is XElement for reading xml and being able to use LINQ on it. But...what about querying with namespaces?
Here is how you do it:
Declare a XNamespace object with the namespace. In my case it looked like this:
XNamespace ns = "http://earth.google.com/kml/2.0";
Grab the XML, via a url, into an XElement node:
XElement resultNode = XElement.Load( url );
Now, I just wanted one node buried deap in the structure called "coordinates". This is how I grabbed it:
XElement coordinateNode = resultNode.Descendants( ns + "coordinates" ).First();
So that last line of code. I'm using the Descendants method to return all of the nodes in a flat list. I could have used resultNode.Descendants().Last() and gotten the node I wanted (since the coordinates node is the last node in the document -- but there isn't much of a guarantee that will always be the case.
So I'm asking the Descendants method for the "coordinates" node by name, and I'm prefixing that name with the namespace. Descendants returns an IEnumerable (a list), so I use the First() method to just give me the first instance.
Compared to XPath, this was a dream. But I still hate namespaces.
Here is all the code again in list:
XElement resultNode = XElement.Load( url );
XNamespace ns = "http://earth.google.com/kml/2.0";
XElement coordinateNode = resultNode.Descendants( ns + "coordinates" ).First();
July 28, 2007
C# Parital Methods
I was just looking through the Orcas Beta 1, and I saw something I have been waiting to talk about...Partial Methods!
This allows you to create a method sub in a partial class so you can provide the implementation in another partial class.
A case where I would use this: in code generation. You generate a data object as a partial class. Now say you want to customize the constructor a bit more. Current you have to use inheritance to do that -- but then you have to remember to use the inherited class and not the generated calss. But with partial methods you can use the main class and provide that logic. Also, if the partial method is not implemented in the other partial class, it is taken out by the compiler. Nice.
A second use: logging. You can stub out methods where you would like logging to occur, but you don't want the partial class to have to deal with the implementation of logging, making it easier to switch out later.
I hope you see why I am excited about this enhancement.
A couple of caveats though,
- the method must return void (or a sub for you VB folks).
- out parameters are not allowed -- but parameters are allowed in general.
- You are not allowed access to internal/private members
- They can only be defined and implemented in a partial class.
Below is a stub implementation:
// my generated class in file1.cs
public partial class Class1
{
// a partial method
partial void CalledByInit();
public void Init()
{
CalledByInit();
}
}
// my implementation class in file2.cs
public partial class Class1
{
public void CalledByInit()
{
// do my stuff here
}
}
Now why is this better than:
1. just declaring a delegate in the middle of your class?
2. passing in the code as a predicate parameter?
The answer:
1. A delegate can be assigned by anyone, and potentially have multiple implementations. That isn't always good. The partial method can only have one implementation and only by other partial class.
2. aesthetically that makes a really ugly call, plus it requires that the caller have intimate knowledge of the workings of the method that it shouldn't have to have. Now you can localize that knowledge in one place.
Again, thing about the main use case for the partial method: it should be used in conjunction with code generators. If any of you have used SubSonic, Typed Datasets, NHibernate, or other technologies, right now you are using a mixture of inheritance and partial classes. With this you might be able to drop the inherited class all together. And frankly, I'm for anything that reduces the number of classes lying around a project.
If you are interested in other new features in C# 3.0 I found a nice Power Point from Raj that you can check out.
Partial Methods are mentioned on LukeH's blog.
And they are talked about on the VB Team blog.
July 26, 2007
Some days your better off going home
For any who don't know the difference, ASP.NET Web Site lets IIS compile the code as needed, but not until then. Makes debugging a nightmare and you have to deploy all of your C# code to the server. Web Applications compile to a dll and you only have to deploy the aspx and dll files.
Anyway, I spent 4 hours beating my head against this problem. I found MANY hits on google, none really helped. Including an often quoted article by Eran Sandler.
Finally I went home. I had to drive 200 miles to pick up my kids from grandma anyway yesterday night (that is round trip mileage). Four hours in a car either by yourself or with sleepy kids does give you time to think tho. I devised a plan.
My problem was confined to one custom control, I had already figured that part out. I would recreate the control piece by piece until I found the problem (don't ask why I didn't think of this earlier).
Next day, nice and fresh, I did just that. I had the problem fixed in 15 minutes. On this particular control I had a Validator control and an event with the same name. That was causing the problem (it wasn't a problem in the ASP.NET Web Site mind you -- just in the Web application).
15 minutes. That was it. About the same amount of time it took me to write this up!
Just goes to prove, when you are really beating your head against the wall over and over again, sometimes it is just better to go home.
July 24, 2007
3 months, 3 LINQ presentations
Starting off, I'm no LINQ expert. Yet I have to distill it to the group. Luckily LINQ is an easy sell. There is something there for everyone in LINQ. But when it gets right down to it, what is LINQ about? I put it like this: FOR loops are evil and LINQ is the cure.
FOR loops are not run for cover and grab a Bible evil, more of a general GOTO type evil. It isn't as if GOTO is evil in itself, in some languages the GOTO is a required statement. But like all inherently benign language constructs, in the wrong hands it can go really badly.
For myself, I've seen some of the worst code in my life nestled in for loops. And even worse, most people don't even know it. How would they? You could say that they just don't know any better. But in reality, there often isn't a better way.
What is the FOR loop but a structured GOTO. Really, that is it. And it isn't a very thick abstraction. If you don't believe me, go check out assembly language. Same with WHILE.
Next, what are you doing in the FOR loop (looping through a list -- DUH)? Sorry, I need a better question: what are you trying to accomplish with the loop? Now, look at the loop, and how easy is it to figure that out after the fact?
There is a reason people don't like assembly anymore, it is too hard to understand after the fact AND it is to hard to write in the first place. There are too many moving parts. Even adding two number (registers) is a multi-step operation. Things you do in loops have many of the same qualities.
Here is an example: find the largest value in an array of integers.
First the array:
int[] i = int[]{1, 2, 3, 4, 5, 6, 7 };
Here is what you write in C#:
int iMax = i[0];
foreach(int j in i)
{
if (iMax < j)
iMax = j;
}
Here is what you would write thanks to LINQ (and Extension Methods):
int iMax = i.Max();
How many ways are there for the first code to go wrong? There are 6 lines, 4 of them have code. There is one obvious bug in the code anyway...what if the list has no items? You will get an index out of bounds error right there. But there are many ways to incorrectly write this code. This is also a simplistic example, so imagine how bad this can get when doing real code.
In the second example: I can't find one. Plus, there is very little chance that you, or someone else, will not understand what the code is doing.
Now this is simplistic, which is bad because it hides the true power that is hiding underneath. There is more to link than grab bag of small statistic functions (e.g. Sum, Min, Max, Count). Add in a complex object and the Where method and we begin to see.
Visualize a customer object. It will have properties like FirstName, LastName, Address, City, etc. This in in a CSV file that is coming from Sales and Marketing.
First part: load the CSV into your program. No problem, we have all done that from time to time. Now find me all of the people in Idaho. Crap.
Not in LINQ. If you loaded your data into a list (List
var idahoCustomers = from c in list
where c.State = "ID"
select c;
Want that in Lambda:
var idahoCustomers = list.Where(c => c.State == "ID");
Something you should know about now, there are two ways of doing the same thing, and you should probably know both. First is LINQ. If you see "from blah blah where blah blah select blah blah" -- you are looking at LINQ. If you see a "=>" you are looking at Lambda.
Personally, I love Lambda more than LINQ. Lambda can do everything LINQ can do, plus everything else. Another way of saying that is "LINQ is a subset of Lambda."
Anyway, this post could run on and on about the wonders of LINQ and Lambda -- but there are plenty of other people doing that. Hopefully, you have already read some of that. Where I want to finish off with is a few suggestions for anyone looking to get a grip on all of this.
First, there are a lot of new things to learn these days. WPF, WF, WCF, LINQ, Lambda, etc. Is this different? Yes it is. You need to learn LINQ. Personally I will be asking interview questions based on link in the future.
Second, considering you have limited time, what should you concentrate on? My answer is Lambda and Extension Methods. The more you learn about Extension Methods the more you will be able to do with Lambda. (Warning, if you are going to learn Extension Methods, you should probably learn about Predicates as well).
And some words of warning. Watch your return value types. You will see a lot of IQueryable, IEnumerable, and other strange interfaces as return types. These will often be hidden in 'var's. Be warned, each has its own capabilities, and you should know how to convert between them.
For example. In a List object, you get the ForEach extension method. You don't get that with IEnumerable or IQueryable. But you can get there by calling ToList() on either of those object types.
Finally: measure. Grab a profiler and run with it. Just like FOR saved you from the uglyness of GOTO, LINQ saves you from the complexity of FOR. But it doesn't get you away from the costs. There will still be times when it is better to write the loop yourself. A good profiler will tell you when.
Oh, one final note: I'm using Visual Studio.NET 2008 Beta 1 like everyone else. All code samples are subject to change when Beta 2 releases this week.
July 18, 2007
Where are the DSLs?
First off, in my understanding of a DSL, it might not be a proper definition. Frankly, I don't care if the language is a full on language, with it's own syntax and control structures, or just a set of very specific libraries that add classes and methods for easily reading what is going on inside of an existing language -- like C# or VB.NET.
Personally, I like the second one. I would take the inspiration from SubSonic and NHiberate. Heck, throw in NUnit if you want. The nice thing about using these as your examples is that you know things are easily extendable.
There are a couple that I am thinking of right now. I've been playing around with MSBuild and NANT lately. Those two tools have convinced me that XML sucks as a language format. How do you define a loop in XML? You can't do it in any terse format I can tell you that. XML is for data, not logic. That is why JavaScript doesn't look like HTML.
So no, I dont buy XML as a language. Personally, I have a hard time seeing through all of the angle bracket -- really, I do. They just seem to create a lot of unnecessary noise to me. Readability stinks, which hurts the overall expressiveness of the language -- not to mention aesthetics -- and maintainability is also terrible. Not a whole lot of syntax highlighters for xml these days. Debuggability: None. (is debuggability a word?) Either it works or it doesn't. If it doesn't...may the force be with you.
Anyway, back to the build scripts example. Basically, even if you have sample build scripts to work off of, it will easily waist one day of a developer's life to get a build script off the ground. Just to get started. Then countless more hours keeping the stupid thing up to date.
Why don't we have a build script DSL? Some already do exist, Ruby Rake is one. I'm considering learning it. I would like a C# based one, but I'll take Ruby if I have to.
Another use that I have thought of often has to do with ETL. Now I find I'm not alone. Ayande has recently been bitten by the bug. Which is good. Because with his given track record he might just be able to do it. Would you rather deal with Integration Services GUI or a language specifically designed for that purpose.
Bear in mind, these examples break down at one crucial point: threading. Both of the examples mentioned, ETL and Build Scripts, can benefit heavily from working in parallel. And that is one area that our current languages don't help us with a whole lot yet. It is easy to tell Integration Services to load a bunch of tables at the same time in the GUI -- that is a lot more work in C#.
Now it can all be mocked with the Unit of Work pattern so everything can be batched together. That would hide the complexity from the user of the language at the very least. But that still leaves a lot of complexity behind the scenes.
Which leads me to one of the new great hopes coming from Microsoft sometime in the future: PLINQ. Aka: Parallel LINQ. LINQ is all about building a better FOR loop. But it is still iterating over a list one item at a time. PLINQ takes things that next crucial step: multi-threading the iteration. And all without changing the syntax of LINQ. Now that is flippen cool. Unfortunately, I have heard no release date for PLINQ, and it probably wont come out with .NET 3.5 at all.
Anyway, those are my thoughts. I could go on, but I need to get back to work.
July 04, 2007
I (hart) Fiddler
Enter Fiddler. I was able to intercept the call, check what was being sent and returned, and with the help of the file compare in Context I was able to figure out the problem.
Now I've seen Fiddler before, but that was always as a that-could-be-useful-later. Today it was useful. I don't know how I would have tracked down the problem otherwise.
June 28, 2007
NetDug last week...
Last week I gave a presentation on C# 3.0 and LINQ to NetDug. Mind you, this is a really well run group. We meet at the ProClarity ---erm Microsoft -- building in downtown Boise. Usually someone from Microsoft lets us in, guards over us, and things go really well. Not this time.
It started with one of the group leaders sending me an email, the day before the meeting, telling me that he could not get onto their server, ergo: they couldn't send an email to the group telling them that the meeting was on, and what we were talking about.
Not great, but I can work around that. I sent out a message to the BSDG group, which is also largely Boise area developers and told them. It is largely the same people anyway.
One day goes by.
OK, day of the meeting. I show up and there are already people there waiting outside the building. I'm early so I don't think much of it. The Microsoft building here in Boise is actually a nice spot. There is this cool little spot that had some places to sit in the shade with lots of trees, which was needed because it was over 80 degrees at the time. So we just sat there until someone was going to open the building for us.
Janitors walked in, a few people walked out. I even knew a few of them. It was getting really close to the time of the meeting so I started talking to one of them as they came out. Asking if certain people who are usually there to open the building for us are still in the building to open the building so we can have our meeting. (yes, that is a run on sentence, but appropriate since the person I talked to was a tech writer -- who taught tech writing). They were not there.
Great. First there is no email to tell anyone about the meeting we were supposed to have, and now we don't even have a room to have it in. This is getting better all the time.
By this time there were about eight people there. That is a small gathering for this group. It usually gets 20 people. But, they were still interested in what I had to show them. But we were outside, and my laptop is useless outside running on battery power -- so no power point. There are worse things in life than giving a talk with no power point, really. So next best option: wing it with a pen and paper.
This is where it is a good thing that there were only eight people there. So I started the meeting, outside, and started talking. One thing that does happen when giving a talk like this, you cut out all of the extraneously stuff.
Array initializers -- didn't talk about it.
Extension Methods -- yes, but just enough
Object and Collection initializers -- just barely
Expression Trees -- mentioned that I didn't know anything about them.
But we did talk quite a bit about the var keyword, anonymous types, LINQ, and Lambda. All via pen and paper (which I now refer to as the original Power Point).
So, obviously, I wasn't trying to get the attendees to really grok the material, but I think they did capture some of the general zen. Which, as far as I can tell, is to rethink how and when you use a for loop on a list. With LINQ and Lambda, we should be seeing a lot fewer of them.
In the process we also talked about PLINQ, XLINQ, DLINQ, LINQ for SQL, NHibernate, SubSonic, and Log4Net. It was a good meeting. Not bad for considering the circumstances.
Then to close off the evening for myself, my mom and brother were attending a dairy conference a few blocks away, so I snuck into there and bored myself to sleep. They were talking about whey futures (as in stock market like futures).
I thought I had given a reasonable presentation with no slides earlier, on the street, in 80 degree weather. Here was a guy giving a presentation inside, with a huge projector (20 foot screen - at least) to 50 people and doing it badly.
Now all of this comes from my own general preferences. There is an art to displaying lots of numerical data on a slide. There is also an art to showing charts on a slide. This guy knew about neither, and probably never read anything by Edward Tufte.
Note: I have read Edward Tufte, but please don't blame my bad slides on him -- they are my fault for not reading his books enough.
All of his slides were white. All of his text was black. There was no variation. They could have been printed on a black and white printer and no one would have known the difference. Imagine trying to decipher slide after slide filled with large grids of numbers, each row having a different type of number, and only a thin black line between them. Not good. Then to show emphasis on a particular number -- out comes the laser pointer.
I about made my brother buy me a beer after that. And dinner.
My mom did instead.
June 14, 2007
Fake Objects in RhinoMocks
First to give some background, there is a difference between a Mocked object and a Fake object.
With Fake Objects, think of a simple class with only properties containing both getters and setters. You can set any property to a value, but the fake object really doesn't care what happens to it. If you set a property to a value, it returns that value until that value is set to something else. I am not sure, but I don't thing you can tell a Fake object function what to return. So if you need that, you should probably use the Mock Object -- read on.
With Mock Objects, they are much more complex beasts. You must warn the Mocked object for every call made to the object, and tell the Mocked Object what to return. One nice thing about Mocked Objects is that functions can be mocked.
Each object, Fake and Mock, has their place in a testing scheme, so it is important to know the difference. If you need simple returns with getters and setters, and don't care if something does or doesn't get called use a Fake Object. Otherwise use a Mock Object.
Anyway, if I have an interface that looks like this:
1: public interface IMyObject
2: {
3: public string MyProperty1 { get; set; }
4: public string MyProperty2 { get; set; }
5: }
I can create and use a Fake Object for it like this:
1: IMyObject o = MockRepository.GenerateStub<imyobject>();
2: o.MyProperty1 = "Hi";
3: o.MyProperty2 = "There";
4: Assert.AreEqual("Hi", o.MyProperty1);
5: Assert.AreEqual("There", o.MyProperty2);
1: MockRepository mock = new MockRepository();
2: IMyObject o = mock.CreateMock<IMyObject>();
3: Expect.Call(o.MyProperty1).Return("Hi");
4: Expect.Call(o.MyProperty2).Return("There");
5: mock.ReplayAll();
6: Assert.AreEqual("Hi", o.MyProperty1);
7: Assert.AreEqual("There", o.MyProperty1);
8: mock.VerifyAll();
Have fun.