Jonathan Birkholz

Distinct With Func

When you go to look for the ability to run a Distinct Linq query using a func and it isn’t there… it causes some confusion.

To get around this troublesome omission I had to create my own extension.

I first created my own implementation of IEqualityComparer that will utilize a func to do the equals comparison.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class FuncEqualityComparer<T> : IEqualityComparer<T>
{
public FuncEqualityComparer(Func<T, T, bool> func)
{
_func = func;
}
readonly Func<T, T, bool> _func;
public bool Equals(T x, T y)
{
return _func(x, y);
}
public int GetHashCode(T obj)
{
return 0;
}
}

Next I will need an extension method off of IEnumerable.

1
2
3
4
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items, Func<T, T, bool> func)
{
return items.Distinct(new FuncEqualityComparer<T>(func));
}

Now when I check to see what Distinct options are available I see my new Func extension.

And to test whether this new distinct is working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Test]
public void should_return_distinct_items()
{
var jedis = new[]
{
new Jedi {Name = "Mace Windu"},
new Jedi {Name = "Mace Windu"},
new Jedi {Name = "Luke Skywalker"},
new Jedi {Name = "Yoda"},
new Jedi {Name = "Yoda"},
};
IEnumerable<Jedi> distinct = jedis.Distinct((j1, j2) => j1.Name == j2.Name);
distinct.Count().ShouldBe(3);
}

All this code can be found in my Learning Repository –> Learning CSharp solution.

http://github.com/RookieOne/Learning

Using Extension Methods to Remove Dependencies

Yesterday I had a discussion with a co-worker about extension methods, he was concerned with some of the extension methods I was using and emailed this guidance when to NOT use an extension method:

When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.

I was confused because I read that guidance and I think that is a perfect time to use an extension method. I asked where he got the guidance and he set me the following links:

If you look at the second link you see that in fact the guidance is FOR when to use extension methods. So apparently there was just a miscommunication on what the guidance was saying.

Here is my feeble attempt at explaining what the guidance is saying.

All the code can be found in my Learning GitHub Repository and the Learning CSharp solution @ http://github.com/RookieOne/Learning

Suppose we have a class Foo. And with Foo we have a method ‘Whatever’ that returns a type Bar. Normally we would do something like this:

1
2
3
4
5
6
7
public class BadFoo
{
public Bar Whatever()
{
return null;
}
}

By writing our method this way, we make the BadFoo class dependent on the Bar namespace / assembly. When someone uses a BadFoo class they get to see the Whatever method and not realize they are going to also be dependent on the Bar namespace / assembly.

Instead of writing the Whatever method as an instance method, we can write the method as an extension.

1
2
3
4
5
6
7
public static class FooExtensions
{
public static Bar Whatever(this GoodFoo f)
{
return null;
}
}

I now can see that the Whatever method is clearly an extension method off of Foo. And yes, if I use the method I will then need the Bar namespace / assembly, etc. The difference is that with an extension method it is more of an opt in scenario. I can have users of Foo that don’t need the Bar assembly nor the Whatever method.

This is sort of hard to explain but I am giving it my best shot. :) Maybe some whiteboarding will help.

Without the extension method, the Foo.dll has to reference the Bar.dll. If we instead moved the Whatever method out into an extension method in the X.dll we can see that Foo.dll no longer needs to reference the Bar.dll.

Anyway, I like extension methods and think there is a lot of misconceptions surrounding when and how to use them. I think a more interesting topic for extension methods is limiting their scope in order to provide bounded context specific operations. This ‘removing of dependencies’ aspect is just part of that topic.

Again check out some of the code in my Learning solution http://github.com/RookieOne/Learning

Basic NoRM Ids

Again I want to reiterate I am by no means an expert at Mongo DBs or NoRM, but I am sure there are tons of people like me looking for some of the basics. And maybe some of the things I learn will help others.

When you start with NoRM you might quickly discover that if you don’t have an id for your object, you can’t insert or update that object.

When you try to insert an object without an identifier, you receive an MongoException that says:

This collection does not accept insertions/updates, this is due to the fact that the collection’s type does not specify an identifier property

So how can we specify an identifier property?

The basic methods include

  • Use Id property of ObjectId type
  • Use Guid property type and identify with MongoIdentifier attribute
  • Use Guid property type and map as id with MongoConfigurationMap

ObjectIds

The easy method is to use a property of type ObjectId (NoRM type) and named Id. In my learning project I am using this with Book.

1
2
3
4
5
6
public class Book
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
}

This property is also set once you insert a new book into a collection as demonstrated here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[SetUp]
public void setup()
{
Mongo mongo = MongoTestHelper.create_new_database_connection();
mongo.Database.DropCollection(typeof (Book).Name);
_book = new Book();
mongo.GetCollection<Book>().Insert(_book);
}
[Test]
public void should_set_id_on_insert()
{
_book.Id.ShouldNotBe(ObjectId.Empty);
}

Guid + MongoIdentifier

Another method is to use a Guid and then mark that Id property with a MongoIdentifier Attribute. In my learning project I am using this with Movie.

1
2
3
4
5
6
7
8
9
10
11
12
public class Movie
{
public Movie()
{
Id = Guid.NewGuid();
}
[MongoIdentifier]
public Guid Id { get; set; }
public string Title { get; set; }
}

Notice that although I labeled the Id property with the MongoIdentifier attribute, it doesn’t automatically get set. I have to set the id to a new guid in the constructor.

Repeating the previous test shows that yes our movie can be inserted and the id set.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[SetUp]
public void setup()
{
Mongo mongo = MongoTestHelper.create_new_database_connection();
mongo.Database.DropCollection(typeof (Movie).Name);
_movie = new Movie();
mongo.GetCollection<Movie>().Insert(_movie);
}
[Test]
public void should_set_id_on_insert()
{
_movie.Id.ShouldNotBe(Guid.Empty);
}

This test really isn’t that helpful since we set the new guid in the default constructor. Let’s test that the Id can be read and set from the database.

1
2
3
4
5
6
7
8
[Test]
public void should_read_and_set_id()
{
MongoQueryProvider provider = MongoTestHelper.create_query_provider();
Movie movie = new MongoQuery<Movie>(provider).First();
movie.Id.ShouldBe(_movie.Id);
}

Using Mongo Configuration Map

If you are like me and prefer the POCO lifestyle, you can use a MongoConfigurationMap to specify the identifier.

In my learning project I am using this with Customer.

1
2
3
4
5
6
7
8
9
10
public class Customer
{
public Customer()
{
Id = Guid.NewGuid();
}
public Guid Id { get; set; }
public string Name { get; set; }
}

And then I am creating a map for customer.

1
2
3
4
5
6
7
8
9
10
11
public class CustomerMap : MongoConfigurationMap
{
public CustomerMap()
{
For<Customer>(x =>
{
x.IdIs(c => c.Id);
x.ForProperty(c => c.Name);
});
}
}

And the tests…

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
[SetUp]
public void setup()
{
Mongo mongo = MongoTestHelper.create_new_database_connection();
mongo.Database.DropCollection(typeof (Customer).Name);
_customer = new Customer();
mongo.GetCollection<Customer>().Insert(_customer);
}
Customer _customer;
[Test]
public void should_read_and_set_id()
{
MongoQueryProvider provider = MongoTestHelper.create_query_provider();
Customer customer = new MongoQuery<Customer>(provider).First();
customer.Id.ShouldBe(_customer.Id);
}
[Test]
public void should_set_id()
{
_customer.Id.ShouldNotBe(Guid.Empty);
}

So those are three basic methods of setting an identifier for an object to be inserted or updated in a MongoDB with NoRM. All the code is in my learning git hub repository in the Learning_NoRM solution. The source can be found here : http://github.com/RookieOne/Learning

Learning Mongo DB and NoRM

I am currently working on a WPF application I will be using to manage our TFS system here at SolArc. Well it isn’t for everyone, just for me (for now). I look at the TFS interface and I can’t see what is important to me and doing the operations I want seems counter-intuitive. So what does a programmer do? He naturally writes an app for himself. :D

The problem I am running into is that although the WorkItems API is nice, it isn’t exactly what I want. I would rather not hit the SQL database as well. My current thoughts is to replicate the TFS workitems in a MongoDb. Naturally the WorkItems won’t be ‘workitems’ but will actually be the shape and correct context for how we use them. For example we have work item types for Epic Scenarios, Scenarios, and Tasks. Anyway the nuts and bolts of the app can be another blog post once I have something more concrete to share.

Since I am learning Mongo DB, I decided to write a post so that I will have something I can go back to when I inevitably forget how I got something to work.

I got MongoDB at http://www.mongodb.org/

Then in the bin folder I tried to run mongod. Unfortunately it failed because I had not created a data/db folder. That is the default location for MongoDB to store data files.

After creating the folders on the C:\ drive, I reran mongod and it started the database.

I heard a lot about NoRM at Open Spaces so I figured I would use that to work with the MongoDB.

I got NoRM at http://github.com/atheken/NoRM

The NoRM tutorials I found online were using a different code base so the way I connected to the database was a bit different. My first test looks like:

I am sure there are better ways of writing the tests, but I thought I would share the minimum test that I wrote to prove that NoRM and MongoDB were working.

I will be adding more learning tests and add them to the Learning_NoRM project in my Learning GitHub Repository.

http://github.com/RookieOne/Learning

Houston Open Spaces

It might be a week late, but I still want to share how awesome Houston Open Spaces was. I was concerned at first when I found out how small it was going to be and that certain intellectual giants were not going to be in attendance.

But… I knew I should have been prepared to be surprised. And I was.

First of all, the WPF Workshop was well attended and I enjoyed presenting. Unfortunately all my recording attempts failed. :( But we live and learn. I figured out my issues with Camtasia. I made some newbie mistakes like not stopping the recording during every break. So although the talk isn’t online or recorded, the slides and code are. They can be found on my GitHub: http://github.com/RookieOne/JBsWpfExamples

At the conference proper I had a blast and learned a lot. Open Spaces is truly a unique type of conference. The philosophies around the conference and the quality of people in attendance naturally lends itself to fantastic conversations and melding of the minds.

Check out the site here : http://altnethouston.com/

For those that could not attend, be sure to go check out the wiki (http://houstonaltnet.pbworks.com/). A lot of work was put into the wiki by attendees in order to share what was talked about in each of the sessions.

I also brought my recorder to do some trial runs recording sessions. I was extremely pleased with the quality of the audio it recorded. Especially when you consider the size of the rooms and the volume levels people were talking at.

Not all the sessions I attended I was able to record but check out these sessions for the audio.

http://houstonaltnet.pbworks.com/Polyglot

http://houstonaltnet.pbworks.com/Virtual-Brown-Bag-One-Year-Later

http://houstonaltnet.pbworks.com/Design-Patterns

I convened the Polyglot and the VBB One Year later sessions. I then attended the Design Patterns and had a blast discussing patterns.

Ruby was discussed a lot and it is on my short to-do list for this year. I was pointed to Why’s Poignant Guide to Ruby (http://mislav.uniqpath.com/poignant-guide/) and have begun to go through this hilarious and informative online guide. The writing style and zaniness is exactly what I need in a technical manual. :D

I also really enjoyed Rod Paddock’s session on Movie Making as a metaphor for software. Although nothing concrete came out of the session, I left with a lot to think about. I might look into a book about movie making and see what I can learn. Sometimes you need to take a step back and re-examine what you think you know and this was a great session to challenge me with a new perspective on software development.

I am looking forward to being active in next year’s Open Spaces. I also think I will plan to attend the one in Seattle next year as well.

So a big thank you to all those who put the conference together and those who attended. You guys rock!

Houston Open Spaces - What It Means to Me

As I began preparing for Houston’s Alt .Net’s Open Spaces 2010 Conference (http://altnethouston.com/), I started to reflect on the year since the last Open Spaces. Last year, I had a decision to make: do I go to the already scheduled Nascar weekend with my Godfather’s family or do I attend the inaugural Houston Open Spaces. After lots of time weighing my options, I opted to go to Open Spaces. I am glad I did.

At Open Spaces I got lots of time to meet and interact with some of the greatest minds in .Net. Being able to talk to people like Jeremy Miller and Jeffrey Palermo was invaluable. Numerous sessions introduced me to brand new ways of thinking and solutions to common problems. To say I enjoyed Open Spaces would be an understatement.

But for me, the biggest boon was that I recognized a huge gap in my professional career. Before Open Spaces I didn’t even know who most of the heavy hitters in our professional community even were. Sad? Yes, but true. I decided at Open Spaces to start reaching out and pay more attention to the community. It was time to expand my understanding of the programming world. Also I knew it was time to start blogging more, sharing more, and presenting more.

I think I have a knack for programming and was applying the appropriate principles and patterns; I just had difficulty expressing why I was coding the solution a certain way. I knew I was right but lacked the experience to express why. I remember when Ryan Riley (@panesofglass | http://wizardsofsmart.net/) came over to my computer one day and shared a Hanselminutes podcast featuring Uncle Bob. As I listened I got more and more excited. Uncle Bob was expressing in clear articulate terms exactly the principles I knew and coded by. I knew then that I needed to start learning the appropriate terms, definitions, and principles to express how to produce quality code.

So at Open Spaces when Claudio Lassala (@claudiolassala | http://claudiolassala.spaces.live.com/blog/) mentioned conducting Virtual Brown Bags, I quickly worked to volunteer and share what I was doing. The led to me being the substitute coordinator for several meetings. And now the one year anniversary for Virtual Brown Bags is coming up. What is a VBB?

Check out Claudio on CodeCast: http://www.code-magazine.com/codecast/index.aspx?messageid=d0e149ed-d8e7-44d2-bf7e-94d68ef4c1c3

In short, we meet over Live Meeting every Thursday 12pm-1pm (central) and share whatever we are working on or feel like talking about. :)

Every week I pressure myself to talk and share whatever I am working on. It has been great practice in talking as I code, expressing what and why I am doing something. I also surprised myself that every week I have something to share. I have a hard time sitting down and writing a blog post, but it’s easy for me to plug into Live Meeting and just go over whatever code or blog post has my current attention.

Beyond Virtual Brown Bags, I started to do public presentations at user groups and conferences.

Here is the list of presentations I have done this last year:

WPF Substance over Style - South Harris Dot Net User Group Evolve Your Code - Houston Tech Fest & C# SIG INETA recorded this session (http://live.ineta.org/Videos/Player.aspx?video=1ce91b60-5e4b-416d-9cb2-34740fdab8c6) WPF Input Validation – Houston Tech Fest WPF in an Hour – EPOG Silverlight 4 – Aggieland DNUG I also was able to do a podcast episode on CodeCast talking about Convention over Configuration:

http://www.code-magazine.com/codecast/index.aspx?messageid=0001bf99-1394-45c2-8949-388c673ac7a5

And I volunteered to conduct a free Advanced WPF Workshop.

Also at EPS I presented 2 3-day WPF Training Sessions. Now if that doesn’t challenge you on how long you can talk, then nothing will. :D

As you can see, this was a busy year. Open Spaces allowed me to meet incredibly talented people and engage them in shop talk. It encouraged me to reach out and start mastering my craft, so I can teach others. Open Spaces 2009 was one of the most influential events in my career.

And now we have 2010’s Open Spaces coming up and it should be fantastic!! Not only will I be attending, but I will also be conducting another WPF workshop for Open Spaces 2010. More details will be shared later, but I am very excited about this presentation.

The quality of the discussion and individuals at last year’s conference led to my expansion this last year. I was blessed with so many opportunities to talk, share, and grow. I know that this year’s session will provide me with the fuel to take 2010 to that next level.

I hope to see you all there.

Dynamic + Extension Methods = Fail

I am playing around with dynamics right now working on a solution for a completely different problem.

I discovered a issue I didn’t foresee (and maybe I am doing something wrong).

I use AssertExtensions to make my tests more readable so I created my first extension.

1
2
3
4
5
6
7
public static class AssertExtensions
{
public static void ShouldBe<T>(this T actual, T expected)
{
Assert.AreEqual(expected, actual);
}
}

I created a test to ‘get’ a property from a dynamic object.

1
2
3
4
5
6
7
8
9
[TestMethod]
public void should_be_able_to_get_property()
{
var book = new Book {Title = "Icarus Hunt", Author = "Timothy Zahn"};
var d = book as dynamic;
d.Author.ShouldBe("Timothy Zahn");
}

Should work right?

Wrong.

Oh noes!

Apparently the RuntimeBinder can’t figure out the extension to string. My solution was to do this:

1
2
3
4
5
6
7
8
9
10
11
[TestMethod]
public void should_be_able_to_get_property()
{
var book = new Book {Title = "Icarus Hunt", Author = "Timothy Zahn"};
var d = book as dynamic;
var author = d.Author as string;
author.ShouldBe("Timothy Zahn");
}

I just found it interesting that it didn’t behave the way I would have expected.

100 Books Every Man Must Read

So over lunch I decided to mark down which of the 100 books every man must read I have actually read.

Read

  1. The Great Gatsby
  2. 1984 <- multiple times… pure genius
  3. The Catcher in the Rye
  4. The Picture of Dorian Gray
  5. How to Win Friends and Influence People
  6. Call of the Wild
  7. Swiss Family Robinson
  8. Catch-22 <- love it! I need to reread.
  9. Lord of the Flies
  10. Don Quixote … yes I’ve read it. It was long and I don’t remember any of it.
  11. The Hobbit
  12. Huckleberry Finn
  13. Animal Farm <- again.. genius.
  14. Frankenstein <- Fire…. bad
  15. Hamlet
  16. The Stranger
  17. The Island of Dr Moreau
  18. All Quiet on the Western Front <- literally changed my mind about going into the army :)
  19. To Kill a Mockingbird

Read Excerpts

  1. The Prince
  2. The Republic
  3. Brave New World (still need to finish it)
  4. The Iliad and Odyssey
  5. Walden
  6. The Metamorphosis
  7. The Art of Warfare
  8. The Divine Comedy <- I read Inferno
  9. The Politics
  10. The Federalist Papers <- genius
  11. Moby Dick <- started but never finished
  12. Paradise Lost
  13. The Red badge of Courage
  14. The Bible
  15. Zen and the Art of Motorcycle Maintenance

Adv WPF Videos

The videos are up from the Adv WPF Workshop we had here at EPS.

Videos (the links are kind of slow and funky atm. I will look into it on Monday. I had more luck downloading the file as opposed to streaming it)

Part 1 Part 2 Part 3 Part 4 Part 5

I had a great time talking through some of the things we are doing here with WPF. I think it took awhile to get started but towards the end I think we picked up speed.

I don’t exactly recall the topics right now but I believe we did cover these items from the original agenda:

  • INotifyPropertyChange
    • Normal
    • Type Safe
    • Dynamic Proxy
    • AOP
  • View + ViewModel
    • Typical methods
    • IView extensions
    • IView
    • ViewRegistry
    • Also will be covering StructureMap conventions (TypeScanners) and Type Interceptors
  • Event Aggregator
    • using Events
    • Publish extension method
    • ISubscribe
    • Putting it all together with a Region Controller

I guess one big note would be that PostSharp is no longer open source therefore you need a license for their 2.0 product. At EPS we picked up licenses for our current solution. The benefit we get out of PostSharp and AOP far surpasses the license price even when you have to buy the license for every developer.

Check PostSharp out at (http://www.sharpcrafters.com/)[http://www.sharpcrafters.com/]

I think we are going to work on a PostSharp CodeCast or some other informative session on the tool.

Considering we have the Houston Open Spaces coming up, I will probably delay another workshop for a bit. But I had a good time and will probably do another one around May or June.

I want to thank everyone who came online and on site. It was a lot of fun! Please provide feedback so we can make the next workshop even better.

Creating My First TFS 2010 Build

My work this iteration on my project is setting up a CI build and then migrating all our POC code to the solution.

Right now I am creating a simple build as practice for setting up the actual build.

I am approaching this from a complete n00b when it comes to creating a TFS build. I have created builds before but they have been small and just simple MSBuild files. This is the first time I am using TFS and creating not only a build but a continuous integration environment.

I created a Team Project and added a simple C# project to source control. I then looked at the Team Explorer and noticed that there is a Builds section under my project. Intuitively I right clicked and found where I can create a New Build Definition.

I looked at the options available to me on the Build Window and noticed a Trigger section. Investigating the Trigger section allowed me to select what triggers this build. Oh look a CI trigger that builds after each check-in!

I then had to set an output folder so I created a folder on our build machine and set the folder to that.

And then I was done.

I do have to say we already had a TFS Build Controller setup so I can’t comment on that for now.

I then ran a couple of experiments. I first added a class foo to my project and checked in. I then double clicked on my Build under the TFS explorer and was given two reports. One report showed the current queued builds and the other had a list of the completed builds.

After I ran my first successful build I then made a compile error and checked it in. I then had a failed build.

When I double clicked the failed build I got this UI.

I then created a test project and then made a failing test. Now my build looks like this:

And when I double clicked I got this report.

So that was a real quick run through with creating a CI build with TFS 2010. I have to say… I was surprised that it was that easy. I am continuing my work with the build but it looks like the simple scenario was incredibly easy!