Archives
-
Scrum tasks, tasks, and more tasks
I find that I'm often letting my teams know some norms around Scrum and the process of a task-oriented system so I thought I would throw these out to the world. We sometimes loose sight of these simple things and get wrapped up in bigger, more grandiose ideas so consider this a Wednesday morning reminder.
- Don't assign tasks to other people. You don't want people telling you what to do because frankly I don't function that way and I don't think people work well in this manner (in general). One of the key principles of Scrum is self-organized teams meaning teams that decide what they need to do to get the job done, not others telling them.
- Don't claim tasks as your own but don't do work on them. I often see people stake claim to tasks in Team System (our Scrum tool) and set them to In Progress but they remain that way the entire sprint. It deflates the value of the system and just makes it look like the team is busy (to outsiders) but we're not really doing anything (or you can't tell what you're doing).
- Don't create huge tasks that take days to implement. My rule is generally under 4 hours. If you have an 8 hour task what you're saying is that, uninteruppted, it will take me the entire day to work on this. In reality you'll be interuppted, they'll be meetings, phone calls, coffee breaks and 8 hours of effort will probably take 12 hours of duration which means you have one task that spans 1 1/2 days and maybe even 2. So as a team member, you're saying to the your team mates, leave me alone for 2 days while I do this in isolation. That's not condusive to a good team effort nor is it helping anyone. If you see a task that's more than 4 hours, ask yourself if it's really 1 big task or 2 small ones? The other advantage to smaller tasks is that you might break something up into two 4 hour tasks and each one can be done by two different people, meaning you actually deliver value faster and isn't that what we're trying to accomplish here?
- If you already have something "In Progress" don't pick up a new task. I've been told that I have ADD and while I might (I do have many projects on the go, both at work and home) I try to manage it. Picking something and saying "I'm working on this" then turning around the next day and saying the same thing on something else just looks like you're trying to look busy. It's okay to grab a couple tasks at a time or grab a new one if one task is just waiting on something or needs a small collaboration say with the customer, but knowing that a task has 2 hours of work left, yet grabbing a new one and starting it without finishing the first is just plain dumb. Why would you do that? Would you wash half your car, then go and cut the lawn knowing your car is covered with soap? Even with ADD I wouldn't.
How do you eat an elephant? Easy, one bite at a time.
-
SharePoint Builder Splash Screen Entries
Here's the first round of splash screen entries for SharePoint Builder. I won't tag who did what yet.
The last one is my fav so far as it shows innovation and is different (that's a hard hat in case you didn't get it). Note that you don't have to include the "Version 1.0" stuff in your entries as that will change so it's better to leave it blank. Remember to submit your entry soon via email and you can comment on the entries on the blog here.
Keep 'em coming!
-
Splash me baby, splash me!
I'm looking for a good graphic design that can beat this:
Specifically a splash screen for my SharePoint Builder tool. Requirements are simple: an image of some size (it's a splash screen remember so 1024x768 might be a bit large) that represents what the program does, namely helps you build SharePoint configuration files.
Think you're up to the challenge? The reward is my undying gratitute, your name in lights, and the warm fuzzy feeling that you contributed to something useful in the universe. Not bad for a Sunday afternoon huh.
So break out your crayons and send me your ideas (final or otherwise) via email. Let's give this 2 weeks from today and see if anyone comes up with something cool. I'll post the entries here and maybe we'll hold a public vote to pick the best.
Thanks for helping out!
-
Best Practices with FitNesse
Google doesn't seem to show me any best practices that anyone has put together with FitNesse, which is odd (or my Google skills suck) so I thought I would capture a bunch here that I've come up with to start.
- Keep your wiki test pages small
- Having a wiki test page with 20,000 tests doesn't do anyone any good. First off, it'll take days to load. Second, it's a sea of gobbly-gook looking at it in edit mode and next to impossible to find that one line that you need to edit. Do your team a favour and keep them small. Like development practices, I like to keep my FIT pages down to a screen or two at most.
- Organize your tests so they make sense
- FIT supports test suites and they're useful, especially for organzing things. Having one table with hundreds of scenarios might be good (more tests are always good) but if they're difficult to read or navigate they'll be cumbersome to maintain. Use a single responsiblity principle when it comes to organizing your tests and try to group them together into some kind of organizational category or unit that makes sense to the tests and users. For example if you have FIT tests that are testing accounts, consider writing a table for each type of account; a table for account fail conditions; a table for special conditions; etc.
- Use "Friendly Names"
- Rather than seeing complete namespaces and fixture names, use friendly names with spaces. So this:
"|MyCompany.MyApplication.MyFixture|"
can become:
"|My Fixture|"
Also you can use the !import table to remove the fully qualified namespaces. This makes it more appealing to look at when you're showing value to the customer of these tests. - Seed your test pages and engage the authors
- Getting started with FIT and actually having tests can be a big hurdle. To be setup for success, have the entire team not only go through creating the fixtures and tests but work with the authors about what scenarios they can test. For example not everyone thinks about the failure conditions that should be tested (using the fail[] markup) so make sure the authors of the tests know all the different things they can try. The best scenario you can ask is a perfect test author who knows all the things to test, but when adopting FIT you might need to do a FitNesse 101 with them and get them introduced to different ideas around testing, not just entering tables over and over again. Quality not quantity is what you're looking for in the end.
Feel free to add your own!
-
My new response to overdemanding clients
-
Where did my SDK go?
If you've downloaded the recent release of the MOSS and WSS SDKs, you may be scratching your head wondering where they installed to? After all, they're just some compiled help files and samples right?
Seems that in their infinite wisdom, some young and bright engineer at Microsoft broke Phil Haacks first rule of hardware design (which bodes the same for software design). The computer belongs to me, not you!
It seems the SDK installers will hunt down and find the last writable drive in your system and install there. No questions asked. So if you have a removable drive or something (even a USB key) plugged in, it'll be there. The install paths for each SDK are as follows:
- WSS: \Windows SharePoint Services Developer Resources
- MOSS: \2007 Office System Developer Resources
Check on your highest drive letter in these paths for the files to see if they ended up there. When I first installed mine, I had a USB drive plugged into F: so it ended up there, after pulling all my external drives, it ended up on C:. I don't have a network drive available right now, but I would assume it might install there if you have write privledges.
-
MOSS and WSS RTM SDKs available now
How's that for posts with the most acronyms? It might be old news to you by now, but MS has finally released the RTM versions of the SDK documentation for both MOSS and WSS. Randall's blog has all the nitty gritty details here. He's also got a great resource called the top 10 resources for SharePoint developers (which is actually 14, who said softies could count?) so check that out here.
As for the SDKs they're final now but wait, there's more... these are the first ones outside of the original core set to be Community Content enabled. Yup, the SDKs allow you (with a passport account and the sacrifice of a willing virgin) to contribute content to any entry, any class, any method, and well... anything in the SDK. So watch for this MVP to bide his time updating the documentation as I can find time, as will others I'm sure. Very cool indeed.
You can download the SDKs directly here:
-
Domain Driven Design for C# 3.0
Or maybe 4.0? Paul Gielens got my brain jump started this morning with a post about DDD support in the C# language. Domain Driven Design can be hard to grasp and even harder to implement. Conceptually it's easy and makes sense (at least to me). We all read the books and get the theory, but when the rubber hits the road the biggest question anyone has is "how do I write code that reflects this?". Everyone has ideas and if you take a quick search of the DDD mailing list, you'll see dozens of code snippets all talking about the same thing but implementing it differently. Sure, software development and pattern is like that. Take any one pattern and give it to 3 people and you'll get 5 different interpretations. However as we continue to dance around implementation, we get confused by the terms and sometimes miss the ball.
Here's a DDD type implementation using C# constructs so the intent isn't all that clear here:
1 namespace Car
2 {
3 class Wheel { ... }
4 class Position { ... }
5 class CarRepository { ... }
6 class FuelTransfer { ... }
7 }
Now given the spark that Paul mentioned, here's the same code written in DDD style:
9 domain Transportation
10 {
11 aggregate Car
12 {
13 entity Wheel { ... }
14 valueobject Position { ... }
15 repository CarRepository { ... }
16 service FuelTransfer { ... }
17 }
18 }
If you've read DDD and internalized Eric Evans' theory around things like aggregates, boundaries, entity and value objects you'll get this. You'll see the domain visually (or at least I do) and understand it. No longer would you have questions like "is x an aggregate of y and where should service z live?". The code tells all. Brilliant.
I love C# but it does have its limitations in that it's just simply regurgitating the language it was based on and has typical constructs like class, namespace, etc. I'm sure (but haven't thought how you could do it) that say a language like maybe Ruby could support this but that's an answer for those smart types like John Lam to answer (although with John at the mothership now and working on the CLR team, anything is possible).
I think it's an excellent idea, my only wish is that something like this could come true someday!
-
Lambda? Llama? We don't need no stinkin' llamas...
Actually this post has nothing to do with llamas but Flickr never fails me:
I've been personally putting off trying to get my head around Lambda expressions in C# 3.0 for awhile as I'm trying to get everything wrapped up with what came with 2.0 however a little gem has come out of the quagmire we call the internet. My good friend Howard Dierking, not a llama but a certification guy and all around cool developer over at the evil empire, has put together an awesome explaination of Lambda expressions and C# 3.0 by walking us through what we do in 2.0 and now C# 3.0.
His explanation and example makes perfect sense, cuts down the clutter of delegate code, is easy to understand, and if you don't get it now you'll really be in trouble when the .NET 3.5 framework hits. Check out Howards blog entry here and judge for yourself.
-
Today could be the first day of the rest of your life
It's been a week since I blogged and mostly it's been staying busy with work, trying to get on top of all the projects I have and most importantly remember the passwords for all my VMs that I seem to have now forgotten. However today was a bit of an experience I never had before. I got into a car accident. 24 years of driving and I've never actually had an accident. Call me a wuss, but I drive the speed limit and when the road conditions are bad, I slow down and try to keep my cool. Or so I thought.
As I was heading into work this morning I hit a patch of black ice and slush and away I went. My Suzuki XJ7 wiggled along the highway and slammed head first into the concrete barrier that separates the northbound and southbound traffic. It was a hard enough hit to deploy the air bag and shook me up for a second or two. Then I realized I was perpendicular to oncoming traffic and all I could see was headlights. No, it wasn't a "My life flashed before my eyes" moment. It was just a "This sucks" moment as I saw the oncoming traffic. Lucky for me it was 5:30am so traffic was light and the roads were bad (with a light dusting of snow) so everyone was travelling pretty slow (I was only doing 70-80km/h when I hit the barrier as opposed to the 110km/h speed limit). I got the vehicle off the road and discovered there were two other vehicles involved as they swerved to avoid me and ended up hitting each other.
No injuries, although my thumb hurts like the dickens right now (I think I clenched the steering wheel when I hit the barrier) and my chest is sore when it hit the airbag/steering wheel. The other guys had no injuries and damage was pretty minor to their vehicles (back bumper torn off and dent on the side panel of one truck). My damage was a little more severe as the front end was all crushed in (hood buckled, bumper, lights, grill, etc.) and the back bumper was ripped off when one of the trucks swerved to hit me on the side and caught my bumper with his. All in all, I have a pretty good suspicion that my truck is a write-off but they might be able to fix it.
So a sucky way to start the morning and the rest of the day was being mad at myself for what happened and sorting out all the insurance crap and whatnot (including trying to track down a rental car which is increasingly difficult in this city these days). On the positive side, besides being alive and kicking it opened up the idea of buying a new vehicle so we're now looking at something like a Jeep Compass which looks pretty sexy.
Like I said, this wasn't a life altering event for me. It was an accident (and my first). Yes, with a slight twist of events in the timeline of what went down I could have been writing this from the great blog space in the sky or a hospital bed but I'm not so you move on. However it does remind me to remember to live life to it's fullest each and every day. Slow down, enjoy what you have and what's going on around you, and relax. There are probably bigger things in the universe to worry about so don't get your panties in a knot over something silly like property damage.
-
Web Service Software Factory update released
I'm a factory kinda guy. Ever since I read Keith Short's book I was enamoured with the concept of how factories work. Microsoft took the ball and got things going with the various software factories they're releasing and now they've updated their Web Service Software Factory.
The Service Factory is a cohesive collection of various forms of guidance that have been build with the primary goal of helping you build high quality connected solutions in a more consistent way with less effort. The Web Service Software Factory comes in the form of a guidance package, that allows guidance to be automated from inside Visual Studio 2005 through the use of a wizard-based dialog than can be modified (by an architect perhaps) to fit the needs of a specific solution.
You can grab the latest release here. As with other factories, you'll need the Guidance Automation Extensions installed to run the factory (and it only runs on the professional SKUs of Visual Studio, not Express).
-
Using Dependency Injection with CAB
I was working through a problem tonight regarding dependency injection and CAB. CAB provides a facility to inject services and whatnot into other class using ObjectBuilder, Microsoft's DI framework. ObjectBuilder isn't the same as a DI/IOC container like Windsor Container or Spring.NET (or Jeremy Millers excellent StructureMap) but more like a framework for building containers. However in CAB it serves the purpose we need.
Let's say I have a service that performs lookups and returns me lists of items from some backend system. I would like to use this LookupService in various modules but I don't want the modules responsible for creating the service (especially since I only want one of them and don't want to deal with singletons) and I want an easy way to ensure the service is loaded and ready to go when I need it. Here's where CAB will help you with this.
First let's look at our service implementation:
public class LookupService : ILookupService
{
public List<KeyValuePair<int, string>> Items
{
get
{
List<KeyValuePair<int, string>> items = new List<KeyValuePair<int, string>>();
items.Add(new KeyValuePair<int, string>(1, "Item 1"));
items.Add(new KeyValuePair<int, string>(1, "Item 2"));
return items;
}
}
}
This is a straight forward service that returns a generic List<> of KeyValuePairs<>. I might use this in my UI in a combo box or whatever, but it's just a lookup of items. The implementation here is hard coded, but you could just as easily have this call out to a database, do an asynchronous web service call, whatever you need.
To share the service, I'll use the Infrastructure.Module project in my SCSF generated solution. This module gets loaded first and using SCSF I have it set to be a dependency so whenever the system loads any module I'll load this one first, ensuring my service is there. Here's my ProfileCatalog.xml that shows the dependency.
<SolutionProfile xmlns="http://schemas.microsoft.com/pag/cab-profile/2.0">
<Section Name="Services">
<Modules>
<ModuleInfo AssemblyFile="Infrastructure.Module.dll" />
</Modules>
</Section>
<Section Name="Apps">
<Dependencies>
<Dependency Name="Services" />
</Dependencies>
<Modules>
<ModuleInfo AssemblyFile="Project.dll" />
</Modules>
</Section>
</SolutionProfile>
The module dependency is part of SCSF so it won't exist if you're just using CAB. In my profile catalog, the moment the Project.dll module loads, it will first load it's dependency module(s) from the Services section of the XML file. You can have as many services as you want here and they'll load in reverse order that they're listed in the file.
To instantiate the service and make it available, I have to load it up and add it to the RootWorkItem and it's list of services. This is done in the ModuleController.cs in the Infrastructure.Module project:
public class ModuleController : WorkItemController
{
public override void Run()
{
AddServices();
ExtendMenu();
ExtendToolStrip();
AddViews();
}
private void AddServices()
{
WorkItem.RootWorkItem.Services.AddNew<LookupService, ILookupService>();
}
private void ExtendMenu()
{
}
private void ExtendToolStrip()
{
}
private void AddViews()
{
}
}
If I were to load it up like a regular WorkItem and only use this code:
private void AddServices()
{
WorkItem.Services.AddNew<LookupService, ILookupService>();
}
Then I would be loading it into the services for this module only, which is great, but I want this for all modules to use so I add it to my RootWorkItem. RootWorkItem is a property of any WorkItem that refers to the one and only root item created by the Shell. This way I know there's only one and I can access it from any module anywhere.
Once it's been added to the WorkItems list of Services, I can inject it into any module I need. I'll inject it into my presenter class as that's where I'll use it. The presenter will call the service to get it's values, and set the View with those values to update some GUI element (implementation of the View isn't shown but it just takes the values and binds them to a listbox or whatever you would use them for). I can inject it into the Presenter class two different ways. First, I can use the [ServiceDependency] tag in a parameter passed to the constructor of the Presenter:
public class ProjectListViewPresenter : Presenter<IProjectListView>
{
private ILookupService _lookupService;
public ProjectListViewPresenter([ServiceDependency] ILookupService lookupService)
{
_lookupService = lookupService;
}
}
Not that nowhere do I have to call the constructor, this is done with the AddViews method in the ModuleController and it knows that it needs a type of ILookupService to inject during construction. The constructor sets a private member variable of type ILookupService to the value passed in. ObjectBuilder knows it needs to get an object of that type and will find it using the ServiceLocator service, which is constructed by the Shell. The second way is I can set a property and decorate it using the [ServiceDependency] tag like so:
public class ProjectListViewPresenter : Presenter<IProjectListView>
{
private ILookupService _lookupService;
[ServiceDependency]
public ILookupService LookupService
{
get { return _lookupService; }
set { _lookupService = value; }
}
}
This is the same effect and is done whenever the object is created. Use one technique, not both as they'll both be called. Even though it's the same service object, it's just a waste to do it twice. Finally I just use the service in a method in my presenter when it's ready to update the view:
public class ProjectListViewPresenter : Presenter<IProjectListView>
{
private ILookupService _lookupService;
[ServiceDependency]
public ILookupService LookupService
{
get { return _lookupService; }
set { _lookupService = value; }
}
public override void OnViewReady()
{
View.Items = LookupService.Items;
base.OnViewReady();
}
}
The end result is that I have a loosely coupled service that's injected into my presenter and provides my view with the services it needs. You can use either technique to set the service in the presenter and the great thing is that using something like Rhino mocks, you don't need to create the implementation of the service so writing presenter tests is a breeze with this technique, as you can setup whatever conditions you want for your tests.
-
52 Game Ideas from a Game Designer
I don't know how I missed this. Grant you, being the Renaissance developer that I am I dabble in everything. SharePoint, Agile, Scrum, CAB, Mobile, Games. You name it and I've either written software for it, or want to. It's been a long time since I did full time game programming but I do follow it these days and recently have been haunting the hallows of the XNA world when I moved my XBox to my office so I could try out some console programming.
One of my favorite games of all time (at least created in the last 5 years) is Stubbs the Zombie. It's brilliant in that it lets you be the zombie and go off and eat brains. I'm all for shooting zombies in the head ala George A. Romero and going all Tom Savini on the screen, but to be the zombie. Man, that stuff just writes itself.
So it was a pleasant surprise that I found the lead designer the of the game, Patrick Curry, had a blog. What was even more surprising is that last year he posted a new game idea. Every week. Yup, 52 new game ideas that he just threw out there for all to see. The list is quite impressive and shows this guy thinks out of the XBox. It's a fun read with each entry giving the high level concept, the platform it's intended for, a description, and some thoughts. The community responses are interesting as well as people come up with extensions to Patrick's idea. Anyway, if you're into this stuff or have nothing better to do on your Saturday afternoon then check out the list here.
-
Using MSBuild with Smart Client Software Factories
The Smart Client Software Factory (SCSF) is an awesome tool. It comes in the form as a guidance package from the patterns and practices guys and kicks off your initial Smart Client app with various services, several projects, and a shell application all built on top of the Composite Application UI Block (CAB).
I have found one problem with the current version of SCSF and that's when you generate the initial solution and try to build it using MSBuild. Create a solution using the factory and try building the .sln file with MSBuild. You'll get a host of errors about projects referencing projects that don't exist. Here's some sample output:
SmartClientSolution1.sln : Solution file warning MSB4051: Project {90BC9A2E-DF32-4D50-AB7A-2967B8F5D8D9} is referencing a project with GUID {BE39A9ED-D4C6-42E7-91D6-63D9B1D185C6}, but a project with this GUID was not found in the .SLN file.
I believe this might be because the .csproj/.sln file is generated before the GUIDs are. It doesn't have a problem in the IDE because it references projects by relative file path, but when you try to build a solution using MSBuild (like via an automated build server) the build fails.
Just to clarify this. The GUIDs in the solution file and csproj files are correct however where each project references another in the csproj file it contains both a reference location and a GUID. It's that GUID that's incorrect.
Here's the section in each .csproj I'm referring to:
<ItemGroup>
<ProjectReference Include="..\Infrastructure.Interface\Infrastructure.Interface.csproj">
<Project>{C0143C3B-2D43-4CC3-B593-236D4097F23F}</Project>
<Name>Infrastructure.Interface</Name>
</ProjectReference>
<ProjectReference Include="..\Infrastructure.Library\Infrastructure.Library.csproj">
<Project>{90BC9A2E-DF32-4D50-AB7A-2967B8F5D8D9}</Project>
<Name>Infrastructure.Library</Name>
</ProjectReference>
</ItemGroup>You can fix this without a problem. To do so just open up the .csproj file and in the ItemGroup section, paste in the correct GUIDs for each project it's referring to from the original .sln file. The references that need to be fixed are:
- Infrastructure.Library referencing Infrastructure.Interface
- Infrastructure.Module referencing Infrastructure.Interface
- Shell referencing Infrastructure.Interface
- Shell referencing Infrastructure.Library
Once you've updated the GUIDs in the .csproj files, you'll be good to go for automated builds of your CAB projects. I've logged this as an issue here on the new CodePlex site so hopefully they'll get to fixing this as it was a real pain to find.
-
My Top 10 Films of 2006
Seems like you do this every year, but a friend asked me what mine were. Here they are:
- The Departed
- El Laberinto del Fauno (Pan’s Labyrinth)
- Cars
- Pirates of the Caribbean
- Letters from Iwo Jima
- United 93
- The Illusionist
- The Prestige
- The Da Vinci Code
- Superman Returns
You could question Superman Returns but I really liked the homages Brian Singer did as a nod to Richard Donner and his amazing version. Cars really did make my feel good, Pirates was a good escape and despite complaints about how off the Da Vinci Code was, it was still fun. However Scorsese really nailed it with The Departed. Oscar nods to him and some of the cast. These are only films I've seen. If I had got out to see A Scanner Darkly, that might bump something like The Illusionist or The Prestige.
So what's your 10?
-
Development mottos to keep the team spirit alive
Today we were talking over some things as we start up the next sprint (sprint #4, 1 maybe 2 to go!). The conversation turned towards the fact that one guy on the team was away on holiday but he was the "report guy" and currently one report was causing problems. Unfortunately we've run astruck of the code ownership problem that I really wanted to avoid, namely being dependent on one resource for one slice of the application. Not a good place to be in and something you want to avoid. As we were chatting this set of syllables came streaming out of my mouth:
"If all you do is what you know, you'll never grow."
Plain, simple, and short. Now maybe I heard this somewhere before but after saying it, it made me think (and laugh) and we all had a good chuckle over it. However it really does ring true. Sure everyone has individual skills and some people are better at database programming vs. UI design vs. domain modeling, but in the end a well-oiled team needs to be able to respond to any problem. In any module. In any area of the code. While you might be great at writing the same thing over and over again, it isn't challenging let alone pushing any kind of thought-provoking edge so how do you expect to move with the times?
We wrote the quote on the whiteboard and it resonated. It's one of the mantras we're adopting to always remember not to paint ourselves into a corner and be dependent on any one resource and to tread into those uncharted areas of the your capacity. So get out a little bit, explore your code and if you've never written a view using MVP, now's as good as time as any to learn.
Later in the conversation we came up with another one (we thought we were on a roll). It started with the U.S. Army's "Be all that you can be" motto and became this:
"Test all that you can test."
Yeah, a little corny but then my co-worker Dale came up with this widget:
"If you don't write tests... you're dead."
It was getting later in the day and things started to go downhill but walk with me on this one. We laughed at it but then combined the two statements:
"Test all that you can test and if you don't write tests you're dead."
While it may sound a little chilling and morbid for a software development project, after we wrote it on the whiteboard it just clicked. The team was dead in the water if we don't write tests. We're currently facing new functionality and dealing with some bugs coming up and doing lots of fairly aggressive refactoring. You can't successfully refactor parts of your codebase if you don't know what it does or what the downstream impact is, so when you come upon muddy waters where there's no tests our mantra is to write one then move on. While we do have about 70 good tests (after 3 months of development) we could have more and we've been procrastinating to write more tests (especially for the presenters) for a long time. Pressures from the users, not enough time, blah, blah, blah, blah, blah. So with this little motto and some team re-enforcement of asking everyone at the Scrum when they mark something as "Done" we'll ask if they have tests for it. If not, we're not going to consider it done. Hopefully that'll get us back on track and be productive at the same time.
Finally, later today we had a technical overview and discussion of a new Smart Client project I'm leading up. It was the usual wallow through all the tools, techniques, technologies, process, and standards that we're going to do (with a load of the usual acronyms [CAB, SCSF, TDD, DDD, BDD, FIT, etc.] all thrown up on the whiteboard for discussion). About halfway through as we were talking about testing and specialization of code, I threw the two statements up on the whiteboard again.
"If all you do is what you know, you'll never grow."
"Test all that you can test and if you don't write tests you're dead."
A completely different team with varying levels of experience on the various tools and processes, yet everyone agreed with what we had written. Yup, that's what we have to do for this project to be successful (well that plus deliver a quality solution to the customer).
Anyways, just something to think about. Even if something sounds corny it's a morale builder and an item to talk about. Remember to keep these little team building exercises fun and light and hey, who knows, you might come up with a little motto for your team to keep things interesting!
-
Handling Multiple Environment Configurations with .NET 2.0
Dealing with connection strings and configuration information is something developers do every day. The problem is compounded when you have to worry about local database connections, QA/Test deployments, and finally your release into production. Luckily with .NET 2.0 configuration is easier and the ability to externalize configurations combined with a little craftiness on your part will make builds easier to deal with.
Let's say you have 4 environments to deal with. Your local machine, an automated build server, a test deployment for QA to do user acceptance testing, and the production release. Each one of them has different needs and will access information like database connections in a variety of places. By default when you create a new project (any project) in Visual Studio you get two configurations, Debug and Release. Debug has symbolic debugging turned on, Release doesn't (plus there are some other optimizations but we don't care about those right now).
In 2.0 application configuration is easier with a little something like this:
142 <connectionStrings configSource="ConnectionStrings.config"/>
Rather than having our connection string all spelled out in App.Config or Web.Config, we can redirect it to a completely separate file. As the connection strings may change from environment to environment you don't want to have to edit this file manually, especially if it's being checked into source control so you're always changing it. This means the next time your buddy pulls down the file he'll have whatever change you made (maybe after a deployment to Test) and have to change it back. Worse yet is you might forget to edit this during a deployment (there's no way to force you to) so the next this is you deploy your Smart Client app with a connection to "localhost". Not cool.
So here's a strategy that might work for you. Create a config file for each environment you have then during a pre or post build step (doesn't matter which) in your main forms build you can copy the appropriate file as needed. This way your App.Config or Web.Config file doesn't change but the right settings are picked up from the file(s) you need.
First create the configurations you need. This is done by right clicking on the Solution and selecting Configuration Manager. Then in the "Active solution configuration" drop down, select "<New...>" to create them. You can accept using the default Debug and Release configurations if you want, but I find that "Debug" isn't very informative as I might want a debug version both on my local machine and my automated test or shared dev server. Here's a configuration I use that might suggest something that works for you:
- localhost - Based on Debug but indicates to me I'm building and running locally
- AutomatedBuild - Based on Debug or Release (your choice) but used for the automated build server. For example you may not want the automated build to deploy any web or report projects so it's good to have a new configuration here.
- Test - Based on Debug and used for your testers. You might want to base this on the Release configuration (depending on how savvy your testers are) and you might want to name this something more appropriate to your environment (like QA or something)
- Production - Based on Release and meant to be the build you deploy to your customer
Note these are all new configurations rather than renamed ones. Why? If you simply rename a configuration that's done at the Solution level. The project configuration names in each project will still be Debug and Release so it's confusing when you're setting up what configuration of a project is matched against the build. Trust me, just create new configurations and you'll be fine.
Now that you have your configurations setup, create a new file for each configuration. This will hold the connection strings for each configuration. Name them using the following convention:
ConfigurationName.ConnectionStrings.config
For example if you had localhost, Test, and Production as your configurations you would have the following new files in your main project:
- localhost.ConnectionStrings.config
- Test.ConnectionStrings.config
- Production.ConnectionStrings.config
The contents of each of these files is dependent on the environment but will look like this:
1 <connectionStrings>
2 <add name="LocalSqlServer"
3 connectionString="Data Source=localhost;Initial Catalog=DatabaseName;User Id=sa;Password=password;"
4 providerName="System.Data.SqlClient" />
5 </connectionStrings>
Finally to make it all work, go into your main project and setup a pre or post build event that looks like this:
copy "$(ProjectDir)$(ConfigurationName).ConnectionStrings.config" "$(ProjectDir)$(OutDir)ConnectionStrings.config" /Y
What does this do? It grabs the configuration file for the appropriate build and copies it to your output directory with a common name. That name is what's referenced in your App.Config or Web.Config as shown above.
Now when you build your system, depending on each configuration, it will copy the appropriate file with the correct settings but nobody needs to edit the main configuration file as it always references a common name (ConnectionStrings.config). Cool huh?
Note you can use this for a variety of sections in config (there are restrictions). Check the API documentation on what you can and can't externalize but connection strings and app settings are one of them which is good enough for 90% of the universe.
Of course, after all this is said and done there is another way to handle your environment issues. Just use NAnt or MSBuild, but then that's a whole 'nuther blog post isn't it?
Enjoy!
-
Back to the Future
Many bloggers these days are writing up their New Years plan. What are they going to accomplish this year. Sounds like a good idea, but I wanted to put a bit of a spin on it. Rather than write out a detailed, technical list of tasks I want to do I thought it would be more effective to write a future letter to myself.
Here's how it works. You write up an informal letter to yourself, to be read by yourself this time next year. In it, you state in past tense what you accomplished the previous year (2007). This time next year, you open the letter, read the email, visit the blog entry, whatever and see how you did. So rather than have a sticky list of tasks, you've got a friendly view of what you accomplished (or set out to accomplish) which hopefully brings more meaning to the meat of things.
As this is my first venture of this type, next years letter will be more detailed and have more meaning than the first time around but overall I think it's a better approach to the whole blogging New Years Resolution that's going around now.
Okay, so here's mine.
Dear Bil,
Congratulations on finally getting the MOSS 2007 version of the SharePoint Forums out there (and killing off those nasty bugs people have been reporting). It's your most popular SharePoint tool to date. Following up with the forums you did a good job with the Knowledgebase as many people found value in that (and you were able to use a lot of code and concepts between the two). And the trifactor was releasing SharePoint Builder which had been lingering for awhile but proved to be a valuable tool for the community.
You finally put to rest a new SharePoint community that needed to get out there and it was a great launch, with updates every few months to keep the community needs met and fresh. All this work was not without benefits as in April you got re-awarded the MVP award in SharePoint for the 4th year running.
It was a busy year travelling as you made your way to the MVP Summit in March, got at least one conference in during the year and then there was PDC. While you didn't present or speak there, it was an important event no matter and you hooked up with a lot of people and showed off what was to come in 2008 with SharePoint. You did manage to make up the year with at least one web cast or user group presentation each month on something new either in SharePoint, Team System, Agile, or Scrum.
Finally, while you were a blogging monster creating many entries all with some content to offer the community, you did find time for the family as that always does come first. Congrats and here's to a great 2008!
Until next year, we'll see how close to the mark I came.
-
SharePoint Builder now setup on CodePlex
Yeah, I'm a CodePlex junkie. First the forums, then the knowledgebase, now SharePoint Builder. SharePoint Builder, my red-headed step-child of a project that spawned from a cigarette conversation with AC (and others, they were doing the smoking) somewhere in Redmond.
I've setup SharePoint Builder on CodePlex and it will be released under the same license the other projects are, namely the Creative Commons Attribution-ShareAlike 2.5 license. Basically, do what you will with the tools. Credit me for any derivitive works and feel free to use it commercially. I'm pretty easy.
As mentioned before, SharePoint builder (very different than the image above right now) is built on top of .NET 2.0, C# (code will be available at release) and uses the Composite Application UI Block (CAB) as well as Enterprise Libraries and a few other Microsoft goodies. You'll need the Guidance Automation Extensions and Smart Client Software Factory installed for the source code release.
No commercial libraries will be used, but I would really like to try building it using a Ribbon control as the paradigm fits well, however I don't want to tie anyone to a library that they have to pay for. Not sure what I'll do there as there are currently no free, open source Ribbon implementations and I'm not about to build one myself.
No date on release yet as I'm wrapping up the forums and knowledgebase now along with another project I promised someone but will be doing small commits of the source over the next few weeks to get things into the system.
Also I'll be setting up the release on a public web server for ClickOnce installs in case you don't want to download and build it yourself but rather just use it.
Hey, I told you it was going to be a busy year. Second day and I've already done 8 posts, tagged 5 people, and updated 3 ongoing projects. Just wait until tommorow :)
-
SharePoint Forums and Knowledgebase Release Date Updates
Just wanted to let everyone know I've updated the plan for the release of the SharePoint Forums and SharePoint Knowledgebase Web Parts. These are the dates as I can commit to them now (crazy holiday schedule and stuff that just prevented me from getting the job done):
SharePoint Forums v2.0.0.0
- Prod: Feb-12-2007
SharePoint Knowledgebase v1.0.0.0
- Beta: Jan-29-2007
- Prod: Feb-26-2007
Not a lot of information on the Knowledgebase Web Part yet (other than this post). Feel free to log your own features/enhancements in the Issue Tracker yourself and vote to shape the feature list!
-
Vote for your most wanted issue on the SharePoint Forums Web Part
The guys at CodePlex updated the site some time ago implementing a "digg" like feature where you can vote for an issue and bump it up in priority. It's really slick and helps keep things in sight and what's important to you. So if you get a chance to visit the SharePoint Forums Web Part site on CodePlex here over the next while, take a look through the Issue Tracker and vote on your favorites. This is for tracking bugs but also includes new features and enhancements.
Now I just need to bust my butt to get this (and other things) done asap (like the long overdue 2007 update and some bug fixing that has to be done).
-
Five degrees of separation
There's a tagging game going on in the blog-o-world. I traced the origins (I think) back to Jeff Pulver here. Basically someone tags and you have to come up with 5 things about yourself that relatively few people know. You then go and annoy the crap out of 5 of your friends who blog to do the same. Glenn Block tagged me. Yeah, it's 2007 and we're practicing digital chain-letters but oh what the heck, it's almost January 2nd and I still haven't finished my blogging day just yet.
Here's 5 completely silly things you may (or may not) know about me (or care):
- I used to be big in graphic design doing movie poster (for movies that would barely show up on IFC), animation (for films I'd rather not admit I was part of), and drawing comic books (indy back when indy was cool, never did the big Marvel or DC titles).
- I was part of a special effects studio based out of Oakville, Ontario where I did matte paintings and special effects. We won an award one year from Much Music for the effects on a music video I did work for.
- I drive the biggest, gas-guzzling vehicle known to man (a Dodge RAM 1500 Megacab) and I'm proud of doing my part for the environment (I also have a Suziki SUV so I generally take up the slack up for the gas quotient per person in Alberta). Go ahead naturalists, have at me!
- I've never broken a bone in my body but did have my appendix removed a few years ago (just before it was about to explode in a rather Stubbs the Zombie like move).
- My name "BIL" is spelled this way because back in the 80's when video games and quarters were all the rage, the games only supported entering three letters when you got a high score. I got a lot of high scores and would only be able to spell "BIL" instead of "BILL" (curse those Atari programmers!). So it just stuck.
There. Tag. You're it. I ceremoniously tag the following people that have crossed my path in the past and will now pay for it, or face the wrath of the broken tagging game:
- Jean-Paul Boodhoo - Developer Craftsman Extraordinary, in any language or tool
- James Kovacs - Intense 64-bit .NET guy and recent Architecture MVP awardee
- Kate Gregory - Awesome C++ skills and a fellow Canuck
- Joel Semeniuk - My Winnipeg Team System guru
- Keith Richie - Former Microsoft SharePoint guy, new Mindsharp SharePoint guy
Go forth you uber-geeks and thou shalt write 5 things about yourself, not 3, and definitely no more than 5, and then tag 5 other people with the same fate.
Who knows, maybe someone can make some money from this silly game then we can talk again. Here's a thought, someone could build a diagram of everyone who tagged everyone else. Then we'll see how close me and Mr. Gates really are.
-
SCSF Community has moved
One of my favorite geek communities (if you want to call it that) is the group out of the Patterns and Practices guys who make the Smart Client Software Factory. This is a great package built on top of the Composite Application UI Block and created using the Guidance Automation Toolkit to create an excellent way to get your Smart Client projects off the ground (I've started 3 Enterprise applications using it so far).
They've moved their site over to CodePlex (hurray!). I really detest (read:hate, scourn, abhorr, loathe, spite) GotDotNet and it's workpaces. I mean, everytime someone sends me a link it's a crapshoot whether or not I'll even get to the site by going to the link. When I go to links on GDN it's tied to Windows Live IDs or something but when I go to these links I end up at the basic page. I have to reload the page to actually get to the real destination after Windows Live logs me in (or something silly like that). The search navigation is confusing and have the time I get lost and end up somewhere I shouldn't be. Yeah, in a word I hate GDN and am very happy these guys are moving to CodePlex.
The new site actually covers the SCSF, CAB, and a few other blocks like the Updater block (which needs to be updated to work with SCSF for example). It's nice to have everything together in one spot and I'm sure they'll add more as they grow. They have locked the forums on the old GDN site (which explains why I'm not getting any new feeds) and have committed to moving all the content over (code, forums, etc.) which is a nice touch for finding information (the search on CodePlex actually works).
You can find them on their new CodePlex home here.
-
Keith, not Dennis
Ritchie. It's a name in the geek world that has deep rooted meaning for those of us old enough. Dennis Ritchie, along with Brian Kernighan created the C programming language way back when.
Anyways, long time SharePoint guy Keith Richie, not to be confused with Dennis (but it can be confusing because Keith; Kernighan; Ritchie; Richie; get it?) announced he would be leaving Microsoft and heading over to the Mindsharp world. Wow, that group just keeps getting bigger and better with Todd, Bill, AC, and now Keith.
Keith is the most excellent author of the SharePoint Utility Suite which I'm sure all of you use on a daily basis (I do).
Congrats to Keith. Microsoft is losing a great resource, but there's balance in the SharePoint universe as he's still out there and will hopefully be producing great tools as usual.
You can find his new blog here with his announcment of his old busted MS departure and new hotness MS arrival here.
-
Stats, stats, stats and more stats
What else would you do on a blog in the new year than to post stats? Here's what this blogs 2006 roundup looked like:
Number of posts in 2006: 262
Number of views on all posts: 1,184,018Over a million views for the year. Not too shabby.
Note: Views are both aggregate views (RSS readers, etc.) and web page views so there might be some duplication but I'm not posting stats for correctness here, just popularity of posts.
Top 10 Posts:
- Folders bad, metadata good! (24,112 views)
- DotNetNuke vs. SharePoint, the big showdown (20,544 views)
- The Big Dummies Guide to setting your SharePoint Virtual Environment (17,560 views)
- Tired of SharePoint Discussions? (announcement of SharePoint Forums Web Part - 11,253 views)
- SharePoint Forums, go get 'em (the release of the Forums Web Part - 8,751 views)
- 3-tier Architecture with ASP.NET 2.0 (8,509 views)
- Composite UI Application Block - Soup to Nuts - Getting Started (8,293 views)
- SharePoint Forums Web Part (8,141 views)
- The Lighter Side of being an Architect (8,051 views)
- SharePoint Forums Language Pack (7,342 views)
While I'm not versed in the fine art of statistical analysis, it doesn't take an Acme anvil to fall on my head and show me the SharePoint Forums Web Part was quite a popular topic. Something (along with other SharePoint Web Parts) that I need to focus on early in the year to finish off the remaining work on it (that 2006 baggage I was talking about earlier).
So not a bad year for me anyways. I'm no Oren Eini (aka Ayende, this guy is a blogging engine unto himself), Hanselman, or Osherove who post like gangbusters and every post is a gem, but I'm happy with the activity I've had and I hope you've had fun reading it all. Here's to a new year of posts that will hopefully enlighten, entertain, and enrage you to no end.
-
Anonymous delegates for event handling
Let's start off the new year with a question. Traditionally here’s how you would code up an event handler for say a button on a Windows form (ignore the fact there are presenters and such and how they got initialized).
56 protected override void OnLoad(EventArgs e)
57 {
58 btnClose.Click += new EventHandler(btnClose_Click);
64 _presenter.OnViewReady();
65 }
67 void btnClose_Click(object sender, EventArgs e)
68 {
69 _presenter.OnCloseView();
70 }
That's all well and fine. The form loads, the event handlers are registered and the view is called. There's a method for each event setup (by default in the form of ControlName_EventName) so you might have dozens of additional methods in your view code depending on how complex the form is.With .NET 2.0 we can use anonymous delegates so the code above can become this:
56 protected override void OnLoad(EventArgs e)
57 {
61 btnClose.Click += delegate { _presenter.OnCloseView(); };
64 _presenter.OnViewReady();
65 }
Just setup the delegate in the load method for the form. Same rules apply as in the presenter method will get called when the button is clicked.I like the second method as in it's cleaner and I don't have to clutter up my view code with lots of methods that only pass thru to a presenter. Even with dozens of events on dozens of controls I would only have one line for each in my OnLoad method. It's not just reducing the number of lines of code but readiblity that's key here.
So any thoughts on these two approaches? Preferences? Ideas? Comments? Small unregistered marsupials?
-
First Post!
It's officially 2007 here in Calgary so here's my first post for the year. Kind of weird as I've been thinking it was 2007 for the last few weeks but then at the end of the year it always slows down and becomes a Christmas, shopping, family, and partying focus. No partying for me this year (maybe I've been too many times around the Sun for that) and I'm starting off the year already with a backlog of things I need to get done from last year. On top of that I'm headed to the office this morning so I don't get slammed tomorrow and have everyone sitting on their hands waiting for the ScrumMaster to finish up organizing the tasks as I have 3 Scrums on the go, 2 projects that I'm serving as lead Architect, and the plethora of other tasks in my inbox.
I'm looking at it as a challenge and something that I'm going to share with you guys every step of the way by moaning and complaining about every little thing. It'll be fun, they'll be a lot of great discoveries along the way, and there's plenty of awesome technologies, tools, and projects that are coming from yours truly so sit back, relax, and watch the screen.
Yeah, it's going to be a busy year.