Edmonton is playing host to the Women's Rugby World Cup from August 30th to September 17th. This will be an awesome tourney and I hope they get great crowds out for all the matches. Edmonton also plays host to the Churchill Cup, a yearly tourney with some great international mens and womens squads. I've heard rumors that Commonwealth Stadium will be changing from natural turf to artificial at some point. I hope that this is not the case. If they do this we (Edmonton) will not be hosting great international events like this. I know they're probably thinking about this when they make the turf decision, but let's face it rugby, and Rugby Canada, don't have enough following in Canada or Edmonton to stop the change if it's going to happen. So folks, just in case the turf does change, get out and see the WRWC and high grade rugby here in Edmonton while you can.
For the first time in a long time today I had a build fail on our automated build machine. So to start investigating the error I fired up the Cruise Control .NET Dashboard and found this lovely error greeting me.
After some searching on the internet I was able to determine that there is a difference in the data type used by the Ticks property in .NET 1.1 and .NET 2.0. This is what causes the problems with CCNet. The solution was to open the ccnet.exe.config and ccservice.exe.config files and change the startup blocks to have the latest .NET version commented out.
<!--<supportedRuntime version="v2.0.50727" />-->
<supportedRuntime version="v1.1.4322" />
<supportedRuntime version="v1.0.3705" />
The next thing I had to do was restart the CruiseControl.NET Server service (you will have to restart the ccnet.exe if you were running this manually).
After all of this I restarted my brower and my page was back running. Now the reason for the build failing was a failing unit test, but we'll get into my thoughts on that another time.
Last night I presented at Edmug on Code Generation using myGeneration. We covered off a basic Business/Domain object creation script and then added some inheritance, interfaces and code retention to it. Most of the concepts that I wanted to discuss have already been posted on my blog here. I've also added the following content for download
- PowerPoint (pretty boring actually)
- Finished myGeneration script (includes a couple of extra goodies -- see below)
- Pascal and camel casing functions that I wrote for the demo
The extra goodies now.
Last night I wanted to show the ease of adding a checkbox to the myGeneration UI that I had prompting me prior to the generation occurring. Unfortunately I forgot how to write the code. If you download the script here you will get it complete with said checkbox.
The second goodie comes from a eureka moment that I had today. Last night I was showing how interfaces could be worked with in the script and I mentioned that I wasn't sure how I could write a Preserve block that would retain custom interfaces added to a class. Well I figured it out for my C# code. You add the Preserve block to the line immediately after the end of the class definition line (after all the classes and interfaces that the generator adds to the class). You end up with generated code like this:
6 public class AspNetMembership : Edmug.Demo.Data.Generated.AspNetMembership
7 //p PRESERVE_BEGIN Interface Def p////p PRESERVE_END Interface Def p//
9 //p PRESERVE_BEGIN Interface Code p////p PRESERVE_END Interface Code p//
When you manually add an interface to the class your code will look like this and both the interface definition and code will be preserved:
6 public class AspNetMembership : Edmug.Demo.Data.Generated.AspNetMembership
7 //p PRESERVE_BEGIN Interface Def p//
9 //p PRESERVE_END Interface Def p//
11 //p PRESERVE_BEGIN Interface Code p//
12 public void CustomMethod()
15 //p PRESERVE_END Interface Code p//
If you have any questions about the downloads leave a comment here and I will get back to you.
I read Software by Rob's article on Personality Traits of the Best Software Developers and I was really intrigued by the Pessimistic trait. Rob (I'm assuming that this is the writer's name) contends that pessimism is a great trait for software developers, but you have to read the section on pessimism carefully to get a good appreciation of what Rob is trying to say.
Pessimism is good as an initial reaction to a situation. At some point optimism must take over from pessimism though. Originally this post was going to be an argument that there were actually three favourable phases that a good developer went through: cynicism, pessimism and optimism. After a number of discussions, I'm no longer sure that cynicism is a positive trait for a developer.
Let's look at the definition of cynicism. Webster's says:
An attitude of scornful or jaded negativity, especially a general distrust of the integrity or professed motives of others
The first word that jumps out at me is negativity. It doesn't matter if you're a McD's drive-thru attendant, a software developer or the head of state, negativity is counter productive. A single person's negativity is like molding peach in a basket. All the other peaches will mold more quickly with it around. On a software development team, one negative member will slowly infect and corrode the rest of the team. We all know that corrosion is bad, but imagine your software development team as a steel girder bridge. Corrosion (negativity) is no longer bad, it leads to failure, destruction, mayhem and death. Okay, maybe death is a stretch, but some marketing people are high strung enough that you can realistically see them walking into a developer pod after a project failure and offing someone.
The second word that I was immediately drawn to in the definition of cynicism is distrust. In my software development experience distrust is a product of the environment (thanks to D'Arcy from Winnipeg for pointing this out to me). The environmental causes of distrust can range from a belief that the business will always impose a deadline without first consulting the technical team to an understanding that the decision maker has no apparent focus or concern for the company / project / team / product. Regardless of the reason for the distrust, it is a gnawing problem that will, like a termite, slowly erode the foundation of the structure you belong to. The thing that we often fail to realize is that this erosion will only take place from the level where the distrust reside and lower. Essentially, distrust at any level will permeate that level and the ones below it, but rarely will it proceed higher.
So where do I end with these thoughts? Cynicism is cancerous. Unlike cancer though, we can determine the root cause of it and attempt, and often succeed at, treatment. Treatment is not easy though. It can be an arduous road that takes a great deal of time. The first thing you need to do is determine the root cause of the cynicism. Rarely will you be able to approach a cynical software developer, ask "Why are are you so cynical?" and get an insightful response. Instead, I think, you need to take your time and listen to the cynic in his/her natural habitat. Don't ask questions. Instead listen to their gripes and try to get an understanding of why they're bitching. Is it just because they don't want to try to do new work or take on a new technological challenge? Maybe it's because they've been burned by the client (who ever that is) enough that they can't see by the "Here we go again" thoughts that they are having.
Regardless of the cause of the cynicism, you need to treat it like a software defect. The sooner you address it the cheaper and easier it is to resolve. There are two difficult things in this. First you have to make sure you're not the cynic on the team. If you are, and you're a team lead, all is lost for your team until you can change your outlook on things. The second is that you have to be able to recognize that a team member is becoming jaded and cynical. This is difficult because the onset of cynicism is slow and gradual. Anything that changes in this manner makes it hard to see that a change is occurring. The best advice I can offer is that, if you're a team lead or senior team member, you should make the time to remove yourself from the work environment and find a place where you can think clearly about the situation and the people. Maybe it's going for a walk around the proverbial block, or maybe it's taking the day off and getting completely away from the environment and team. Either way, you need to make the time to isolate yourself and perform constructive analysis of the team members and their outlook on the software development life cycle. Of course this is no good if you don't listen and talk with your team members, so make the time to do that too. It doesn't have to be formal conversations, but listen to what they say when you drop a bombshell piece of work, or a small change, on their plate. In the end maybe the reason for the cynicism is addressable. Perhaps you can go to the 'boss' and talk about how his way of working is adversely affecting the team. Maybe the issue is with the person though, and this is much tougher to address. If you can't work with the person though, you have to be able and willing to cut rope and let them go where the currents may take them. It's not good to have to do this, but the prospect of amputating a cancerous limb sometimes is better than living with, and fighting, it.
I'm the biggest cynic of them all. Like so may other things in life I think you have to take account for yourself before you work on, or with, others problems.
After some trials and tribulations I have managed to get a post written from Windows Live Writer. Kudos to the MS folks who have worked on this because, for a beta product, the install/uninstall process works very well (three times I tried it). In the end the problems I was having were not because of the installation, but rather the configuration that you are prompted for when you first run the application. At one point you are prompted for the url for the metablog API. I was entering my URL with the full www.igloocoder.com name in it and I would immediately get the following error.
An error occurred while attempting to connect to your weblog:
Invalid Server Response - The response to the blogger.getUsersBlogs method received from the weblog server was invalid.
You must correct this error before proceeding.
Because my site redirects to igloocoder.com, this wasn't working. I had to enter the domain name minus the www portion and then all was good.
So far I've been looking at two different ways of handling custom code. The first is to use the preserve method provided by myGeneration and the second is to use a combination of abstract classes and the preserve function. Here are the arguments that I have been able to pin down so far.
Preserve only method
One of the biggest benefits that I see from this method is that all generated and customized code will reside in one location. This also has the drawback of making it less obvious, but not impossible, to determine where generated code ends and custom code begins. I also believe that this method can spawn the creation of a number of preservation blocks in each class (which myGeneration can handle quite easily) causing some unnecessary clutter.
Abstract classes and preserve method
Unlike the preserve only method, this way of separating generated code and custom code creates two locations of code for each class. The first location is an abstract class holding all of the generated code and never any custom code. Because this class is abstract we need to create a second public class that inherits from it so that we can use the generated structure. All this second class needs to do be is a shell class for the sake of inheritance. The body of this second class then becomes a preserve block so anything that is written in the class is preserved when the generator is re-run.
The benefit of doing this is that you have a complete separation between your custom code and your generated code. When you open one of the two classes you will immediately know whether you are seeing one type of code or the other. One of the best ways I've found to indicate this difference is in the use of namespacing and projects. For example you might have a separate name space and project for the abstract generated classes (i.e. MyCompany.MyProject.Data.Generated) and a second namespace and project for the concrete classes that inherit and extend the abstract classes (i.e. MyCompany.MyProject.Data).
My personal favourite of these is the abstract and preserve method. I like the distinct separation of the type of code. The main detractor in my mind is the need to have two classes for each business entity, but we can generate both of them, so it's really not anymore work up front, just more code to maintain.
Corn on the Cob: I used Taber Corn for this, but any corn will do as long as it has the husks still on it. Pull the husks back (but don't separate from the cob), exposing the cob and the silk. Remove the silk and 're-package' the cob with the husks. Soak in water for and hour or so to get the husks moist and prevent burning on the barbeque. Once the corn has been removed from the water, pull the husks back, again keeping them attached, and dry the cob itself. Cover the cob with a butter mixture of your choice (I've tried butter with garlic and butter with ginger and both are very good) and season with salt and pepper. 'Re-package' the cob with the husks and tie the husks down using butchers twine. Place on indirect heat in the barbeque and cook for 30 to 35 minutes.
Potatoes in a baggie: Create a tinfoil baggie. Cut small baby potatoes into bite sized pieces and put in bag. Add a spoonful of butter, a couple of tablespoons of rosemary, salt and pepper into the bag. Pour a half cup of white wine into the bag. Seal the bag and place on indirect heat in the barbeque and cook for 30 to 35 minutes.
Basil vinaigrette: Put one cup of extra virgin olive oil in a blender. Add a half cup of balsamic vinegar. Add one cup of fresh basil leaves. Add zest and juice of one lemon. Blend until consistent texture is reached.
Green salad: Mixture of butter lettuce, romaine lettuce and watercress. Add basil vinaigrette dressing when served. Top with shaved parmesan cheese and fresh ground black pepper.
Lamb kabobs: Standard kabob recipe here. The only difference is that you use lamb for the meat.
This all worked out fine for me (although we never did eat much salad) and the barbeque even cooperated by waiting for the meal to be cooked before running out of propane.
First the technologies. Today we have a number of technologies that are available to us that make deployment of computers much easier than in the past. Probably the most prominent right now is virtualization. Servers for testing, development and R&D environments are perfect candidates for virtualization. These instances of operating systems are volatile by nature. The operating systems themselves are prone to configuration changes, repetitive installation and uninstallation of software and general abuse by the teams that are controlling them. Because of these things, a fresh start is sometimes required to ensure that the environment is in a state that is helpful and workable for the current tasks. On top of the volatility imposed on the software, testing, development and R&D tasks come and go much more frequently than production environments. If a development project ramps up and creates a small application, or performs enhancements and maintenance on an existing application, the life of the environment might be measured in months, not years. Again, being able to quickly setup environments for short or volatile projects quickly and accurately is a benefit to both the project and the group that provides the environments.
One of the primary themes that flows through a number of different aspects of software development is repeatability. When you are creating software you want to be able to repeat functionality consistently (centralized code), repeat testing in a controlled and explainable manner (automated unit testings, testing harnesses and test scripts) and repeat build processes with the same results (continuous integration). All of these 'repeat' ideas are in place with the goal of consistently creating a high quality product. I would like to see this mantra taken to the networking and server department(s) and used for the creation of environments. Test, development and R&D environments are created often, each time being a repetition of the previous (with a few minor tweaks for things like server names and IP addresses). Why can't this repetition be controlled in a manner similar to the way software development repetition are handled?
There is no way that you can guarantee with 100% certainty that a piece of software created in a one-off environment will function when it is migrated to production. Manually creating environments creates a situation where there is a definite chance that the environment being created is not identical to the one being mimiced. The simple fact that the environment is one-off dictates that failure is not just possible, but probable. With technologies such as virtualization there are few if any valid reasons for this to happen. Environments created today should be identical to those created next month as well as those that were created last year.
I'm the Igloo Coder and I'm going to be there......are you?
I'm the Igloo Coder and this post was brought to you by the makers of <censored>.
Thanks to this blog post at The Road to Know Where for pointing me at the download and over a hundred others.
What I've been thinking about this morning is what requirements do I have for a code generation tool. About 4 years ago I wrote a O/R mapping add-in for the VB6 IDE (if I had it I'd post it for all you hard core VBers, but I don't), that was relatively feature complete, and I'm drawing a lot of my requirements knowledge from that experience. Here's the list of functionality requirements that I have when I look at a code generation tool:
- Multi-datasource support - For me this goes without saying. If a tool can't support more than one major datasource then it's not going to be a useful addition to my toolkit for long term use. Rarely do any of us have the opportunity to work on one project for the duration of our careers and every project move you make is a possible, and likely, datasource move.
- Datasource element transformation - Nothing is worse than looking at database elements, whether they're tables, columns, stored procs or something else, in an environment where some naming standard has caused the true business purpose of said element to be less than obvious. I need a way to convert the RT_EMP_HIST table into a business object that has the name EmployeeHistory (complete with the proper casing if possible). If a tool can't create objects that have meaningful (from a business domain standpoint) names, the benefits of its rapid code generation will be lost in poor readability and higher maintenance costs.
- Repeatability - I'm sure you're thinking that a code generating tool, by nature, has repeatability built into it, and you're right. If I fire up the tool and run it now I will get the same results (assuming the data structure I generating from haven't changed) if I run it in 5 minutes, 10 minutes, 10 days or 10 years. The repeatability that I look for is slightly different. You could argue that its more portability than anything. I want to be able to install the chosen tool onto 1, 2 or 100 different machines and easily execute the generation with the same results on each of the machines. Without this I now have a single machine that uses voodoo to execute the process. Nobody like voodoo in their software development process.
- Templating - This is a no brainer. If you can't customize the look and feel of the end code product, you have been backed into a style and, potentially, architectural corner. This was one of the things that I didn't do in the O/R mapper that I created for VB6. Because that was create for in house use, I only had to worry about one style, one layout and one architecture. By no means was that add-in something that I would feel comfortable forcing onto another project or company. Instead I would hope that everyone would like to make their own choices about these things and get the results that they want from their tool.
- Multi-language support - Different companies and different projects within those companies, choose different programming languages. There's no way around it. If I have a tool that can't switch from VB for the .NET framework 1.1 to C# for the 2.0 framework, or even VB6, I'm less likely to be to take the tool with me from project to project. This doesn't mean that I expect one template to generate code for all of the different languages that my whimsical mind can think of. I'm more than ready to write a new template, or better yet just modify and existing one, for each language.
- Granular generation - There are times when I don't want to generate the O/R or DAL for an entire datasource. Maybe all I'm worried about interacting with in my application is a small subset of the datastore. In that case I should be able to select that subset and have the generation only operate on it. Ultimately I want the tool I'm using to remember what subset I am working with so that I don't have to select 49 of 300 tables every time I want to generate code. This holds true for more than just tables. I want the ability to select subsets of columns as well. Again, there's no reason the tool I'm using shouldn't be able to remember my selections from previous sessions.
- IDE integration - As I said earlier, once upon a time I created an O/R mapping tool for VB6. One of the nicest features of it was the fact that it was an add-in to the Visual Studio IDE. I didn't have to jump windows from one application to another. There was no need to manually add generated files to a project or solution. It all happened automatically (heck, you could even see the files being added as the generation was being performed). One of the best things about it was that after generation was completed, I could immediately compile the application and see any issues that may have been created.
- Custom code retention - Although I like to create templates that create code that encourages placing custom code outside of the generated code, situations do occur where you have to embed your custom code right in the middle of your generated code. The tool that you're using needs to be able to recognize this and retain these blocks of code, in the same locations (from a code standpoint, not a line number) when you re-run the generation. How this is done has to be easy and unobtrusive to the programmer as well as effective. My personal recommendation is to avoid having to do this by designing your code so that you are encouraged to place custom code into non-generated objects.
- Data type mapping - Like data source element transformation, I want to have control over the mapping of source datatypes to programming language data types. Occasionally you will need to map a data type to a non-standard programming type because of database conventions or choices. I will say that I don't expect this mapping to work in one off situations (if it can great). If you choose to use a char(1) datatype, containing 'Y' and 'N' values, to represent boolean values in your database, you should be doing this consistently throughout the database. If you are, then a global mapping from char(1) to bool in C# should be achievable.
- Increase productivity
- Reduced variance errors
If you're in Edmonton on the 24th of August, drop by the Milner Library at 530pm for my presentation. If you don't watch here for the contents.
I'm the Igloo Coder and shouldn't myGeneration be called the lostGeneration?
I also never realized that Justice looked so darn good in green. It really is your color man. And the poker face in this picture is priceless. No more darting eyes for tells, heck no more eyes. And dude, the comb-over is a quantum leap over your tussled (I know for a fact it's not the JF look) doo.