Today I extended our Bushfire/Wildfire External Water Spray System (EWSS) to the back decking. I finally found an elegant solution to wet down the decking by having sprays protrude up through the decking just under the side railing. this means that the spray are inconspicuous safe from damage. First tests show a good throw of water, I'm experimenting with both 360deg and 90deg sprays. The 90deg sprays throw water out at a low angle so they seem more reliable in high winds expected during a bushfire but the 360deg sprays are good on the far corner which has some ferns up against the decking.
The photo shows one of the 90deg sprays.
Rob Smyth
Thursday, 27 December 2007
Open Design And Collaboration 'Win Win' $$
Just recently I purchased a Topfield PVR (Personal Video Recorder). One reason I went for a Topfield was the TAPs. TAPs are C++ applications that run on the PVR to do ... well, whatever you like. The thing that makes the TAPs exciting is that Topfield has made the PVR's operating system kinda 'open' so that anybody can write TAPs, and yep the community jumped in a many free innovative TAPs are now available. I can now download TAPs to change PVR skins, display EPGs (Electronic Program Guides), change how the PVR responds to the remote keys, and even change how the box 7 segment display works!
The thing is that the community comes up with more ideas than the original manufacturer could ever do and provides them for free. The manufacturer ends up with a more valuable product due to community support and the community ends up with more choice and functionality due to collaboration.
What a great example of the 'win win' of collaboration and open system design. Hey, it sold me the product.
The thing is that the community comes up with more ideas than the original manufacturer could ever do and provides them for free. The manufacturer ends up with a more valuable product due to community support and the community ends up with more choice and functionality due to collaboration.
What a great example of the 'win win' of collaboration and open system design. Hey, it sold me the product.
Sunday, 23 December 2007
iTunes Could Do With A Bit Of Tuning
Having recently got a new IPod Nano (3rd gen) I've been using iTunes 7.5 software for the first time. The iPod is great, and while the iTunes software is 'adequate' I'm surprised with then number of rough edges it has. I'm disappointed that it does not have the quality I did expect from Apple. Mind you, I still like it and will continue using it.
I'm running Windows XP Pro.
The rough edges I've hit are:
Still, I really like my iPod and find iTunes 'OK', but I no longer think of Apple software as being high quality. A shame.
I'm running Windows XP Pro.
The rough edges I've hit are:
- Register iPod feature does not work
- Rating settings made while ripping are lost
- Column widths are not persisted
- iTunes crashes
- iPod detection can get 'confused'
- Contacts sync from Windows Address Book does not work
- Ratings column changes dodgy
When you first install iTunes it auto starts when the iPod is connected and presents a register iPod page. It just does not work. It seems that everybody is having this problem. The software locks up for a minute or two and then continues without any error message. Next time you will see the same register page. The only solution seems to be to click the 'Never Register' button. Such an obvious fault that hits users on first use and first screen it is hard to understand how Apple let it though.
While transferring a CD to iTunes (Ripping) iTunes plays the tracks automatically. So I figured this would be a good time to listen to them and rate them. I right mouse clicked on the column header area and selected the 'Rating' column. I then set the rating of each track as it was ripped. But when all were done and I went to the 'Music' page I found that my rating settings were lost. Darn.
The default columns widths are less than ideal. If I manually adjust column widths these widths are lost when I return to that page. Rather ordinary for a Windows app.
I cannot explain why but it has locked-up on me a few times now. I guess about every several times I use it. Each time I've had to use task manager to shut it down.
Once when I had iTunes up and then connected my iPod, two iPods appeared in iTunes. iTunes started an auto-sync and after some time reported that my iPod was possibly corrupted. When I pulled the USB cable out both iPod icons disappeared and when I reconnected all was well.
Not a confidence builder.
I have contacts held in Windows Address Book using a local WAB file (not using Outlook). iTunes only imports the first one or two contacts correctly and then misses most others and those others it does import are missing the name, the email address is used in place of the name. I've tried clearing the WAB file and importing all again from a CSV file, which I checked, but the results are the same. Looks fine in the address book but not on the iPod.
The work around is to export each contact separately as a vCard file directly to the iPod's Contacts folder. That works fine but the Windows Address Book software cannot export all contacts at once.
Setting a rating, in the music view, by clicking on the rating column often requires you to move the mouse over another control before it works.
Click on 'Music' in the left pane, then right mouse click on the column headers and select 'Ratings'. The Ratings column is now shown. If you have not set a rating you will see five dots. You can click on one of these five dots to set the rating from one to five. But ... double click the track and then immediately move your mouse over a rating dot (as if you are listening to rate it). Typically I find I can click all I like but the rating is not set until I move my mouse from one dot to another and then back to the one I want. After this move it works immediately.
Still, I really like my iPod and find iTunes 'OK', but I no longer think of Apple software as being high quality. A shame.
Tuesday, 18 December 2007
Importing gmail contacts to my iPod Nano
I've been trying to import my gmail contacts to my iPod Nano and have found that this is not exactly straight forward. It seems that if you are not using Outlook or windows contacts then you need to create a vCard (vcf) file of contacts and copy this manually to the iPod's Contacts folder.
First up I tried exporting the contact to CSV (gmail's only option) and then convert to vCard (vcf) using a CSV to vCard on-line converter here. Worked, but the results were a bit disappointing with a few '&' characters appearing on the iPod. Usable but not as convenient as I would like. I would like to be able to view the edited data is a grid before saving to the iPod.
I found GreySquare Blog which shows how to use the Windows Address Book as an intermediate contacts store. Works well.
In summary:
Other iPod related tools I found while doing this:
First up I tried exporting the contact to CSV (gmail's only option) and then convert to vCard (vcf) using a CSV to vCard on-line converter here. Worked, but the results were a bit disappointing with a few '&' characters appearing on the iPod. Usable but not as convenient as I would like. I would like to be able to view the edited data is a grid before saving to the iPod.
I found GreySquare Blog which shows how to use the Windows Address Book as an intermediate contacts store. Works well.
In summary:
- Export outlook CSV file from gmail.
- Import the CSV file into Windows Address Book.
- Configure ITunes to auto sync contacts from the Windows Address Book.
Other iPod related tools I found while doing this:
Sunday, 2 December 2007
The 'Best' Revison Control Software
One of the teams at work is currently evaluating which revision control software (RCS) product to use as we are moving away for their preferred choice of ClearCase. I've never understood ClearCase and have, in a couple of companies, been perplexed by the strong passion for ClearCase that some teams have had. But, after observing the guys at work evaluating different products the penny has dropped for me on how ClearCase can, truly, be the best RCS software.
There are many revision control tools like subversion (SVN), ClearCase, Perforce, etc, and their functionality varies greatly. No one product that I know of does everything. Interestingly when I worked at a GE company one team used SourceSafe, another used ClearCase, and the other used (I think) Perforce. I've tried to use ClearCase and found that it greatly reduced my productivity. But yet, others insist it is an enabler. How can this be so, we are all software developers, right?
Taking ClearCase as the example here, at my current work we have a team that sees ClearCase as important to their success while others see it as a blocker. I think I can explain this from why I find it a blocker and from what I've learnt as to why this other team sees it as an enabler.
I like to work in an agile fashion and in particular in a eXtreme Programming (XP) style. It suites me, I perform my best this way. So the style that works for me includes the attributes of:
This translates to a process of:
ClearCase is very feature rich. Trouble is that these features make the process above impossible. The features are actually detrimental to this way of working. The fundamental problem is that ClearCase, one way or the other, enforces a level of isolation so that each commit requires multiple steps. The end result is that it takes minutes to do a simple merge and commit with ClearCase. If CI is being used the superior merging capabilities offered by ClearCase's process have no benefit as the merges are always small.
So I find that for an XPish way of working ClearCase's features do not translate to benefits.
The other team, I mentioned at the start, however considers ClearCase's features to be important enablers to their work. I admit that at first I did think that were a 'crazy' but I've come around and recon they are right. After all, they are a successful team so how can they be wrong!
I see them as agile as they are collaborative but their work style is nothing like XP. The style that works for them includes the attributes of:
This translates to a process of:
So, interestingly, SubVersion's (my favourite) features do not translate to benefits for them just like ClearCase didn't for me. For example, SubVersion is fast but they do not really need speed. The big blocker for them is that SubVersion does not currently (scheduled for ver 1.5) record merge history. That is, when a branch is merged to trunk. This is their basic work practice!
So, for them, ClearCase is the best as it matches a work style that works for them.
I really should have known better, people always trump process. People and environments are different so there is no one right way of working.
My spin on this: Now that agile software development is proven and wide spread, Agilists are at risk of now becoming the ones that say 'one size fits all'.
There are many revision control tools like subversion (SVN), ClearCase, Perforce, etc, and their functionality varies greatly. No one product that I know of does everything. Interestingly when I worked at a GE company one team used SourceSafe, another used ClearCase, and the other used (I think) Perforce. I've tried to use ClearCase and found that it greatly reduced my productivity. But yet, others insist it is an enabler. How can this be so, we are all software developers, right?
Taking ClearCase as the example here, at my current work we have a team that sees ClearCase as important to their success while others see it as a blocker. I think I can explain this from why I find it a blocker and from what I've learnt as to why this other team sees it as an enabler.
ClearCase as an blocker
I like to work in an agile fashion and in particular in a eXtreme Programming (XP) style. It suites me, I perform my best this way. So the style that works for me includes the attributes of:
- Continuous Integration (CI)
- Ruthless refactoring
- Teamwork
This translates to a process of:
- Commit code to the repository about every 30 minutes (average on a good day).
- Merge from the repository every 15 minutes (keep up to date with the rest of team's commits).
- Do not work on branches.
ClearCase is very feature rich. Trouble is that these features make the process above impossible. The features are actually detrimental to this way of working. The fundamental problem is that ClearCase, one way or the other, enforces a level of isolation so that each commit requires multiple steps. The end result is that it takes minutes to do a simple merge and commit with ClearCase. If CI is being used the superior merging capabilities offered by ClearCase's process have no benefit as the merges are always small.
So I find that for an XPish way of working ClearCase's features do not translate to benefits.
ClearCase as an enabler
The other team, I mentioned at the start, however considers ClearCase's features to be important enablers to their work. I admit that at first I did think that were a 'crazy' but I've come around and recon they are right. After all, they are a successful team so how can they be wrong!
I see them as agile as they are collaborative but their work style is nothing like XP. The style that works for them includes the attributes of:
- Non-CI. Each developer works in a branch with, what I consider infrequent (but that is qualitative) merging.
- Up front design approach (I think).
- Teamwork.
- Little or no refactoring. (Refactoring is seen as a result of failure as opposed to my style of it being an enabler.)
- Low requirement churn.
This translates to a process of:
- Infrequent commits. I'm guessing an average of once every 2 days.
- Careful merging (essential with infrequent commits).
- Detailed history records of merges to trunk as this is the 'delivery' and work is usually on a branch.
So, interestingly, SubVersion's (my favourite) features do not translate to benefits for them just like ClearCase didn't for me. For example, SubVersion is fast but they do not really need speed. The big blocker for them is that SubVersion does not currently (scheduled for ver 1.5) record merge history. That is, when a branch is merged to trunk. This is their basic work practice!
So, for them, ClearCase is the best as it matches a work style that works for them.
Conclusion
I really should have known better, people always trump process. People and environments are different so there is no one right way of working.
My spin on this: Now that agile software development is proven and wide spread, Agilists are at risk of now becoming the ones that say 'one size fits all'.
Saturday, 1 December 2007
Outdoor Web Cam
I got my first camera installed on the house today but the results are somewhat ordinary. I've posted sample images on my wiki here. The image quality is not good enough for us to view conditions at home. We want to use to see if there is smoke or embers in the area.
I will probably end up getting another camera, but in the meantime it gives me something to use to get the rest of the bushfire fighting system going. Something is better than nothing :-).
I will probably end up getting another camera, but in the meantime it gives me something to use to get the rest of the bushfire fighting system going. Something is better than nothing :-).
Wednesday, 28 November 2007
My Read/Listening List
I've created a "to do" read/listening list on my wiki here. This is new for me. I have a long drive to work so I'm thinking of using the time to listen to podcasts with an iPod Nano Sue is giving me for Christmas.
Saturday, 24 November 2007
A Melbourne Spring Day To Live For
Sue and I have been on holidays the last week and we have been busy around the house doing our bushfire clean-up. It has been a wonderful week, I just love pottering about the house with a dog or two in tow. Melbourne has lived up to its reputation of one day hot, next day cold, and the next day perfect. Today was one of those Melbourne springs that you just live for.
I took the picture on the right late in the day from the side of the house. Gosh I love living here.
I took the picture on the right late in the day from the side of the house. Gosh I love living here.
Friday, 23 November 2007
Golly's First Clip
This week golly got his first clip. A big thing with our Airedale's as they suddenly change from being a black puppy (kinda fox looking) to an Airedale. For a couple of days it was like having another dog in the house!
My clip is rough, but gosh he is a good looking dog. The photo shows him standing and Violet in front.
He is also maturing, in the last two weeks he has changed to really enjoy and seek out a cuddle.
My clip is rough, but gosh he is a good looking dog. The photo shows him standing and Violet in front.
He is also maturing, in the last two weeks he has changed to really enjoy and seek out a cuddle.
Thursday, 22 November 2007
Home Bushfire EWSS
Today I was able to do a quick test of the first installed sprays of the External Water Spray System (EWSS). Very impressive.
I've also integrated the rainwater system and garden sprays into the system. All water supplies (town, fire tank, and rainwater) now all feed into the one manifold so that the fire system can use the garden sprinklers. The fire hose lines still come straight off the pump for absolute reliability.
I've also updated the system documentation including the hydraulics diagram on my wiki here.
I've also integrated the rainwater system and garden sprays into the system. All water supplies (town, fire tank, and rainwater) now all feed into the one manifold so that the fire system can use the garden sprinklers. The fire hose lines still come straight off the pump for absolute reliability.
I've also updated the system documentation including the hydraulics diagram on my wiki here.
Tuesday, 20 November 2007
Accelerating VS Build and Test Times
The latest CodeProject newsletter has an advert for a product that accelerates Visual Studio builds by using distributed computing. Cool. I wonder if it can be used to run the automated tests?
I expect that as a project proceeds the automated User Acceptance Tests (UATs) will take longer and longer. They currently take about 5 minutes in my current team. Even 5 minutes is an inhibitor, we do not always run all the UATs before committing. Especially for those who commit frequently (15-60 minutes). As they take longer this will affect productivity.
So ... can this tool, or another, use distributed computing to run the UATs? If so then perhaps they can run continuously with a dashboard showing current status. Stop typing and then watch them go green. Now that would be cool.
The product advertised is here.
I expect that as a project proceeds the automated User Acceptance Tests (UATs) will take longer and longer. They currently take about 5 minutes in my current team. Even 5 minutes is an inhibitor, we do not always run all the UATs before committing. Especially for those who commit frequently (15-60 minutes). As they take longer this will affect productivity.
So ... can this tool, or another, use distributed computing to run the UATs? If so then perhaps they can run continuously with a dashboard showing current status. Stop typing and then watch them go green. Now that would be cool.
The product advertised is here.
Friday, 16 November 2007
How Often Do You Commit?
When talking "Continuous Integration" (CI) just what is "Continuous"? I've often had this discussion where one person considers continuous to be once a week while another is thinking every few minutes. The perception difference is based on their experiences, nature, and the environment in which they work. I do not think there is any wrong answer except one that excludes all others.
So I'm wondering what is the practice out there so I've added a poll on the right sidebar of this blog to get an indication from actual practices. Regardless of what you think CI is or would like it to be, what is your current practice.
Take a few seconds and record your actual (average) commit rate. This is nothing to do with agile development or the like, just an indicator of practice.
So I'm wondering what is the practice out there so I've added a poll on the right sidebar of this blog to get an indication from actual practices. Regardless of what you think CI is or would like it to be, what is your current practice.
Take a few seconds and record your actual (average) commit rate. This is nothing to do with agile development or the like, just an indicator of practice.
Wednesday, 14 November 2007
Build Box Lights
Yesterday our Varian Australia software team got a USB indicator light which was quickly hooked up to our build box (CruiseControl). These lights are great. We are using cctray to play music on build pass and fails but we have found that sometimes we do miss the sound or it just gets ignored for a few hours. The light we got is programmable for a mix or read, blue, green with different intensities and flash rates. The cost was around $100.
Check them out here. Google with "usb indicator light".
It comes with a driver DLL but info to write your own is available here.
Nigel's post here.
Check them out here. Google with "usb indicator light".
It comes with a driver DLL but info to write your own is available here.
Nigel's post here.
NCoverCop - A Must Have Team Tool
A little while back I mentioned how at Varian Australia the software team has developed a tool that check our code coverage on every commit (each time the build box runs) and fails the build if the coverage falls. Now Nigel is publishing the tool to SourceForge. You can find it here.
This has proven to be very effective. Even with well intentioned TDD it is surprising how easy it is to miss one functional point. As the tool only allows the coverage to go up or stay the same the coverage must, and does, increase with time. It has made a real difference to the team. All code now committed must be 100% tested by unit tests or the fail music will sound within just a few minutes :-).
This has proven to be very effective. Even with well intentioned TDD it is surprising how easy it is to miss one functional point. As the tool only allows the coverage to go up or stay the same the coverage must, and does, increase with time. It has made a real difference to the team. All code now committed must be 100% tested by unit tests or the fail music will sound within just a few minutes :-).
Tuesday, 13 November 2007
VS Like Docking Framework - DockPanel Suite
I've been using the DockPanel Suite framework in a little home application I'm working on. I like it. It provides Visual Studio like window docking for very little effort.
It is an open source project on SourceForge. It could do with better C# 'Getting Started' guide but it is simple to use and the separately downloaded VB documentation gives enough clues to get started. Lot of 'here are what you can achieve stuff', but a bit short on 'here are examples to get you started'.
To use, place a DockPanel filling your window client. This will be the parent for all docking windows. Or if like me you like the programmatic injection approach:
private DockPanel CreateDockPanel()
{
DockPanel dockPanel = new DockPanel();
dockPanel.ActiveAutoHideContent = null;
dockPanel.Dock = DockStyle.Fill;
dockPanel.Font = new Font("Tahoma", 14F, FontStyle.Regular, GraphicsUnit.World);
dockPanel.Name = "dockPanel";
return dockPanel;
}
:
MainForm mainForm = new MainForm(mainFormController, dockPanel);
:
public MainForm(IMainFormController controller, Control dockPanel) : this()
{
this.controller = controller;
Controls.Add(dockPanel);
dockPanel.BringToFront();
}
Your docking windows must all be UserControls that inherit from DockContent (which inherits from UserControl).
An example from some of my code adding a docking window:
propertiesView = new PropertiesView();
propertiesView.ShowHint = DockState.DockLeft;
propertiesView.Show(dockPanel);
A gotcha I found was when passing the DockPanel be sure to reference it as a DockPanel type and not just as a Control. It seems to make a difference.
It is an open source project on SourceForge. It could do with better C# 'Getting Started' guide but it is simple to use and the separately downloaded VB documentation gives enough clues to get started. Lot of 'here are what you can achieve stuff', but a bit short on 'here are examples to get you started'.
To use, place a DockPanel filling your window client. This will be the parent for all docking windows. Or if like me you like the programmatic injection approach:
private DockPanel CreateDockPanel()
{
DockPanel dockPanel = new DockPanel();
dockPanel.ActiveAutoHideContent = null;
dockPanel.Dock = DockStyle.Fill;
dockPanel.Font = new Font("Tahoma", 14F, FontStyle.Regular, GraphicsUnit.World);
dockPanel.Name = "dockPanel";
return dockPanel;
}
:
MainForm mainForm = new MainForm(mainFormController, dockPanel);
:
public MainForm(IMainFormController controller, Control dockPanel) : this()
{
this.controller = controller;
Controls.Add(dockPanel);
dockPanel.BringToFront();
}
Your docking windows must all be UserControls that inherit from DockContent (which inherits from UserControl).
An example from some of my code adding a docking window:
propertiesView = new PropertiesView();
propertiesView.ShowHint = DockState.DockLeft;
propertiesView.Show(dockPanel);
A gotcha I found was when passing the DockPanel be sure to reference it as a DockPanel type and not just as a Control. It seems to make a difference.
Tuesday, 6 November 2007
No Protection from Retalitory Feedback on eBay
I've just found that eBay is a bit more lawless than I thought. In a couple of recent purchases with one HK company (partneringco) the wrong item was sent and the other was not as advertised. So, after the seller was less than helpful, I left a neutral feedback on one and negative on the other. The the seller then left me negative feedback on both. The seller's reason given in the feedback is because I left negative feedback! How blatant retaliatory feedback is that?
I could point out that one was not negative but was neutral but then in the wonderful world of eBay feedback I've learnt that truth is not important. eBay's support info states that they will not remove untruthful feedback and they seem to avoid making any statements about obvious retaliatory feedback.
I'm really stunned by this. How can a seller give you negative feedback stating that they are doing because you gave them negative feedback? How can a buyer ever give negative feedback?
The lessen to me is no matter how bad the seller is, if you leave neutral or negative feedback there is nothing to stop them leaving retaliatory feedback against you! Kinda puts the feedback rating system in a different light.
I could point out that one was not negative but was neutral but then in the wonderful world of eBay feedback I've learnt that truth is not important. eBay's support info states that they will not remove untruthful feedback and they seem to avoid making any statements about obvious retaliatory feedback.
I'm really stunned by this. How can a seller give you negative feedback stating that they are doing because you gave them negative feedback? How can a buyer ever give negative feedback?
The lessen to me is no matter how bad the seller is, if you leave neutral or negative feedback there is nothing to stop them leaving retaliatory feedback against you! Kinda puts the feedback rating system in a different light.
Monday, 29 October 2007
Visual Studio Style Docking For Windows Applications
I'm currently using the DockPanel Suite in a little application I'm writing to give Visual Studio style panel docking. Really cool.
It is, free, open source, and easy to implement. My only critism is that the documentation is a bit fragmented. A quick starter (for C#) on the project web site would be good. Currently you need to download the separate documentation files.
So far I'm really impressed.
It is, free, open source, and easy to implement. My only critism is that the documentation is a bit fragmented. A quick starter (for C#) on the project web site would be good. Currently you need to download the separate documentation files.
So far I'm really impressed.
Using Continous Integration To Raise Code Coverage
I'm constantly amazed by what I learn working in a team, somebody is always coming up with something real useful. This last couple of weeks it was a simple extension to our continuous integration (CI) build box that measures the code coverage of the build and compares it to the highest recorded code coverage. If it is less the build fails, yep fails. If it is higher then the highest recorded is automatically updated with the builds coverage. Being a CI environment any build box failure must be fixed immediately. As a result the code coverage can only go up.
So far this has been amazing successful, but then our team does practice TDD (well mostly).
The implications are that if you are committing new code you are responsible to ensure that your code is covered by unit tests (code coverage is only calculated from unit tests). This is something of a subtle move in responsibility as before it was acceptable to 'think' that the code was covered now we must 'ensure' that it is covered or the build will break within minutes of the check-in.
For this to work developer boxes were set-up so that each developer can run their own code coverage (before check-in) and view the added code for coverage (using NCoverExplorer) quickly and easily. I think that things being easy is really essential.
Like many things I've blogged about I'm really recording great ideas from the team or others. This is no exception (credit here to Nigel Thorne ... a wickedly good idea Nigel).
So far this has been amazing successful, but then our team does practice TDD (well mostly).
The implications are that if you are committing new code you are responsible to ensure that your code is covered by unit tests (code coverage is only calculated from unit tests). This is something of a subtle move in responsibility as before it was acceptable to 'think' that the code was covered now we must 'ensure' that it is covered or the build will break within minutes of the check-in.
For this to work developer boxes were set-up so that each developer can run their own code coverage (before check-in) and view the added code for coverage (using NCoverExplorer) quickly and easily. I think that things being easy is really essential.
Like many things I've blogged about I'm really recording great ideas from the team or others. This is no exception (credit here to Nigel Thorne ... a wickedly good idea Nigel).
Coding Standards Without Having Coding Standards
Every developer likes a coding standard, so long as it is the same as theirs. :-)
Coding standards have benefit but only if accepted by the team. When I worked at Citect they had a strict published coding standard that had been in place for many years. It worked well and every developer complied. In other companies I've worked in have either not had a coding standard, I've implemented a documented coding standard, or the standard was 'copy the standard of the file you are working in'. But in the team I'm working in I've recently realised that a coding standard has been adopted by the team over the last few months without any documented standard, meetings, or negotiations. It just evolved effortlessly and has been accepted by all. The trick was automating the coding standard via Resharper's reformat code command. Nobody, well at least everybody but the implementer, even thought of it as a coding standard!
I can not take credit for this. In fact I was oblivious to it until I realised that we had a coding standard. Being automated meant that any/all files can be formatted with just a context menu command click. So easy, that it is attractive to everybody so everybody uses it. Resharper provides both a hint and positive feedback by a small indicator next to the editor window that goes green when the file is formatted to the rules you have set. It gives markers to lines that do not comply. So easy it is attractive and the good old green positive reinforcement.
Hmm ... are developers becoming conditioned to the green colour (red-green-refactor). Kermit was wrong, it is easy to be green.
Coding standards have benefit but only if accepted by the team. When I worked at Citect they had a strict published coding standard that had been in place for many years. It worked well and every developer complied. In other companies I've worked in have either not had a coding standard, I've implemented a documented coding standard, or the standard was 'copy the standard of the file you are working in'. But in the team I'm working in I've recently realised that a coding standard has been adopted by the team over the last few months without any documented standard, meetings, or negotiations. It just evolved effortlessly and has been accepted by all. The trick was automating the coding standard via Resharper's reformat code command. Nobody, well at least everybody but the implementer, even thought of it as a coding standard!
I can not take credit for this. In fact I was oblivious to it until I realised that we had a coding standard. Being automated meant that any/all files can be formatted with just a context menu command click. So easy, that it is attractive to everybody so everybody uses it. Resharper provides both a hint and positive feedback by a small indicator next to the editor window that goes green when the file is formatted to the rules you have set. It gives markers to lines that do not comply. So easy it is attractive and the good old green positive reinforcement.
Hmm ... are developers becoming conditioned to the green colour (red-green-refactor). Kermit was wrong, it is easy to be green.
Tuesday, 16 October 2007
Web Cam Software
I'm looking for web cam software as part of our bushfire system. The idea is to enable us to view conditions at home from work. It would be great if we could view images via our phones.
I keep coming back to this so I created a wiki page to keep my notes here.
I keep coming back to this so I created a wiki page to keep my notes here.
Sunday, 14 October 2007
Cheap 1000L Tank Under The House
Bought a used 1000L water tank on eBay this week for $235 delivered. $0.23 per litre is cheap and it is just a perfect size to fit under the house. The photo shows the tank being pushed under the house.
I've positioned it so that the top of the tank is level with the overflow level on the existing barrels I have collecting rainwater (you can see one in the photo). So I only have to hook them up and they all act as one tank.
These tanks feed into a small automatic pressure pump which feeds a garden tap and a sprinkler via a solenoid controlled from the home control system. I put a float switch in one barrel just below the overflow level. This is also wired to the home control system so that when the tanks are full a garden sprinkler is turned on for five minutes. The idea is that if we do not have the capacity to store the water we might as well divert it onto the garden. Hence dry spots in the garden get a higher monthly rainfall. Since Melbourne gets rain every few weeks in summer I recon this will help the garden a lot.
I've positioned it so that the top of the tank is level with the overflow level on the existing barrels I have collecting rainwater (you can see one in the photo). So I only have to hook them up and they all act as one tank.
These tanks feed into a small automatic pressure pump which feeds a garden tap and a sprinkler via a solenoid controlled from the home control system. I put a float switch in one barrel just below the overflow level. This is also wired to the home control system so that when the tanks are full a garden sprinkler is turned on for five minutes. The idea is that if we do not have the capacity to store the water we might as well divert it onto the garden. Hence dry spots in the garden get a higher monthly rainfall. Since Melbourne gets rain every few weeks in summer I recon this will help the garden a lot.
Sociable Golly
A few weeks back Golly became the escape artist and kept finding ways next door to play with their new puppy. They got on so well that Golly is now in demand next door so the two puppies can play for hours. We took him in at about 8am this morning and picked him up at about 1pm. Apparently they just ran, rolled, and generally played for all that time!
Proud of him. He is a gentle but confident dog. Sue ought to take a lot of the credit. She insisted he go to puppy school and has also taken him to a nearby training school. The socialization is good, we can see the difference.
Proud of him. He is a gentle but confident dog. Sue ought to take a lot of the credit. She insisted he go to puppy school and has also taken him to a nearby training school. The socialization is good, we can see the difference.
Wednesday, 3 October 2007
Sue want a Mini Cooper
Sue brought a demo Mini Cooper home today. I took it for a drive up and down the mountain. While it is not a car from me (I do not like it) I can see why Sue loves it. It has an amazing safe feeling on the Mount Dandenong Tourist Road, it takes the bends with amazing confidence. Mind you, I've not a new car for some years but it does feel like it is stuck to the road.
What I did not like was the delayed power when using auto but when you do take the plung to manual it is much better. Thing is manual in the mini is kinda auot-manual as there is no cluch, the gear changes are via steering wheel pads, and the engine does take a fairly wide rev range. Manual mode is easier than it sounds. I also found it a bit noisy and rough, but then it seems to be designed for a more 'sporty' feel. Sue loves it.
So I can see the attraction ... but not for me thanks.
What I did not like was the delayed power when using auto but when you do take the plung to manual it is much better. Thing is manual in the mini is kinda auot-manual as there is no cluch, the gear changes are via steering wheel pads, and the engine does take a fairly wide rev range. Manual mode is easier than it sounds. I also found it a bit noisy and rough, but then it seems to be designed for a more 'sporty' feel. Sue loves it.
So I can see the attraction ... but not for me thanks.
Friday, 14 September 2007
Virtual Build Box Lava Lamps
Continuous Integration is the blood supply of an XP style team. The visibility of build box failures and time broken is important. It helps the team focus on keeping the build pristine. The team I'm working with uses CruiseControl to fire a warning audio and to change the state of a tray icon. This is great, particularly the audio, but it does not give us indication of how long it has been broken. So come back from lunch and not notice, or we loose the plot for a few hours and forget it.
One solution is to use Lava lamps. As they need to warm up their activity gives a nice feedback of just how green or how read we are. But they need power wiring (You could use the CruiseCotnrol X10 interface) and control and how do you handle multiple builds and multiple boxes?
The other option is to dedicate a screen on a wall. One company I worked with displayed the state of all builds on all boxes as a grid on this screen. It could be seen across the floor and worked well. But it does require a dedicated box and screen etc.
So what about the new digital picture frames now on the market. One from ThinkGeek looks interesting as it can be updated my email so a build box only needs to send an email. This means that a more informative and dynamic display in a team pit without the overhead of computer. I like the idea.
My thoughts of an ideal virtual lava lamp set-up:
One solution is to use Lava lamps. As they need to warm up their activity gives a nice feedback of just how green or how read we are. But they need power wiring (You could use the CruiseCotnrol X10 interface) and control and how do you handle multiple builds and multiple boxes?
The other option is to dedicate a screen on a wall. One company I worked with displayed the state of all builds on all boxes as a grid on this screen. It could be seen across the floor and worked well. But it does require a dedicated box and screen etc
So what about the new digital picture frames now on the market. One from ThinkGeek looks interesting as it can be updated my email so a build box only needs to send an email. This means that a more informative and dynamic display in a team pit without the overhead of computer. I like the idea.
My thoughts of an ideal virtual lava lamp set-up:
- Audio play on build failure and on build fixed (as provided by CruiseControl tray tool).
- Screen in team pit displaying status as colour and animating time broken.
- Tray icon access for build box details (e.g. CruiseControl tray tool).
- Screen displays a history graph one or two (only) metrics like build time, code coverage, or number of unit tests. Whatever the team feels helps them at that time.
Wednesday, 5 September 2007
Dependency Injection - Ninject
To evaluate Ninject I downloaded the binaries and created a VS project to play with. First question was how to use it. I could not see any doco in the downloads (I only downloaded the binaries) and the web site gave a nice intro but no setup info I could immediately see (I'm impatient). So I tried adding a reference to Ninject.Core.dll. This worked well with the simple web guide.
My test was to implement a dog owner (John Smith) with two dogs. John is a singleton and he names his dogs. Each dog has tail and a mouth that can bite. Pull the tail and he bites! This is designed to test a singleton object with multiple instances of another object. Those objects (the dogs) do in turn have other objects with circular references (dog has tail and tail is attached to dog).
This was easy except that Ninject was unable to resolve a circular dependency (using a constructor and method injection combination). I had hoped that the instances would be created and then the method injection done.
Note: Comment from Nate (see comments below) points out that Ninject does resolve circular dependencies. Looks like my test was wrong, I will retry it again in the next couple of days.
Here is the code:
I've not published the interfaces to save space. I used interfaces to support TDD.
My test was to implement a dog owner (John Smith) with two dogs. John is a singleton and he names his dogs. Each dog has tail and a mouth that can bite. Pull the tail and he bites! This is designed to test a singleton object with multiple instances of another object. Those objects (the dogs) do in turn have other objects with circular references (dog has tail and tail is attached to dog).
This was easy except that Ninject was unable to resolve a circular dependency (using a constructor and method injection combination). I had hoped that the instances would be created and then the method injection done.
Note: Comment from Nate (see comments below) points out that Ninject does resolve circular dependencies. Looks like my test was wrong, I will retry it again in the next couple of days.
Here is the code:
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new RunTimeIoCModule());
IJohnSmith johnSmith = (IJohnSmith)kernel.Get();
johnSmith.PatDog("Rover");
johnSmith.PatDog("Rex");
johnSmith.ChangeDogsName("Rover", "Spike");
IJohnSmith johnSmithAgain = kernel.Get();
johnSmithAgain.PatDog("Rover");
johnSmithAgain.PatDog("Rex");
johnSmithAgain.PullTail("Rex");
System.Threading.Thread.Sleep(3000); // just time to see the output
}
}
public class RunTimeIoCModule : StandardModule
{
public override void Load()
{
Bind().To ();
Bind ().To (); Bind ().To (); Bind ().To ();
}
}
[Transient]
public class Dog : IDog
{
private ITail tail;
private IMouth mouth;
private string name;
[Inject]
public Dog(ITail tail, IMouth mouth)
{
this.tail = tail;
this.tail.SetDog(this);
this.mouth = mouth;
}
public string Name
{
get { return name; }
set { name = value; }
}
public void Pat()
{
Console.WriteLine("Dog '{0}': Pat - thank you", name);
tail.Wag();
}
public void Ouch()
{
Console.WriteLine("Dog '{0}': Ouch!", name);
mouth.Bite();
}
public void PullTail()
{
Console.WriteLine("Dog '{0}': Pulling tail - watch out!", name);
tail.Pull();
}
}
[Transient]
public class Mouth : IMouth
{
public void Bite()
{
Console.WriteLine("Bite!");
}
}
[Transient]
public class Tail : ITail
{
private IDog dog;
public void Wag()
{
Console.WriteLine("Tail Wag");
}
public void Pull()
{
Console.WriteLine("Tail Pull");
dog.Ouch();
}
public void SetDog(IDog dog)
{
this.dog = dog;
}
}
[Singleton]
public class JohnSmith : IJohnSmith
{
private IDog dog1;
private IDog dog2;
[Inject]
public JohnSmith(IDog rover, IDog rex)
{
Console.WriteLine("Hi, my name is John Smith.");
this.dog1 = rover;
this.dog1.Name = "Rover";
this.dog2 = rex;
this.dog2.Name = "Rex";
}
public void ChangeDogsName(string oldName, string newName)
{
IDog dog = GetDog(oldName);
if (dog != null)
{
dog.Name = newName;
}
}
public void PatDog(string name)
{
IDog dog = GetDog(name);
if (dog != null)
{
dog.Pat();
}
}
public void PullTail(string name)
{
IDog dog = GetDog(name);
if (dog != null)
{
dog.PullTail();
}
}
private IDog GetDog(string name)
{
IDog dog;
if (dog1.Name == name)
{
dog = dog1;
}
else if (dog2.Name == name)
{
dog = dog2;
}
else
{
dog = null;
Console.WriteLine("I do not have a dog called '{0}'.", name);
}
return dog;
}
}
I've not published the interfaces to save space. I used interfaces to support TDD.
Tuesday, 4 September 2007
.Net Dependency Injection Frameworks - Part 2
Searching for a Dependency Injection Framework (IoC) my first pass has narrowed the contenders down to:
For my criteria and a list of other frameworks see the 'Part 1' post.
Note: Above chart updated following Nate's comment (see comments below).
I eliminated MicroKernel as I could not find focused documentation (not related products) and what I could find turned out to be links to Porn site adverts. I gave up on Puzzle.Net as I could not find any documentation web pages.
So I'm down to Ninject & StructureMap and wondering if I ought to take a closer look at Spring.Net as it mentioned often on the web.
I will continue to update this another night. Looks like the next step is to try some sample code.
For my criteria and a list of other frameworks see the 'Part 1' post.
Ninject | StructureMap | MicroKernel | Puzzle.Net | Importance | |
License | Apache 2 OSS | essential | |||
C# | 5 | 5 | 4 | ||
Doco | 3 | 4 | X | X | 4 |
XML config | 0 | 4 | 2 | ||
Programmatic config | 5 | 4 | 10 | ||
Constructor injection | 4 | Y | 20 | ||
Method injection | 4 | ? | 4 | ||
Private field injection | 4 | ? | 3 | ||
Setter injection | 4 | 4 | 3 | ||
Singleton activation | 4 | 4 | 10 | ||
Transient activation | 4 | 4 | 10 | ||
Other activation | 4 | 5 | 3 | ||
Simple to use | 4 | ? | 20 | ||
Multiple configs | 4 | 5 | 5 | ||
Contextual binding | 4 | 5 | 4 | ||
Generic types | 3 | 4 | 2 | ||
NMock injection | 3 | 4 | 4 | ||
Maturity | 5 | 4 | |||
SCORE | 58 | 57 | X | X |
Note: Above chart updated following Nate's comment (see comments below).
I eliminated MicroKernel as I could not find focused documentation (not related products) and what I could find turned out to be links to Porn site adverts. I gave up on Puzzle.Net as I could not find any documentation web pages.
So I'm down to Ninject & StructureMap and wondering if I ought to take a closer look at Spring.Net as it mentioned often on the web.
I will continue to update this another night. Looks like the next step is to try some sample code.
Monday, 3 September 2007
.Net Dependency Injection Frameworks - Part 1
In recent work I have been finding dependency injection (Inversion of Control, IoC) very helpful to enable TDD. While in early development object assembly was relatively simple it is now becoming more complex making me think more about using an IoC framework. This post documents my progress in looking at frameworks and I hope will be updated as I learn more.
The nature of the application is that it will have a long lifetime and will need to be expandable. Overall project complexity is medium.
Requirements:
I've done a quick look at the documentation. My first impression is good. I noticed a feature suggesting support for mocked object injection. I've not looked further but this is interesting as I do spend time most days creating mock objects for injection.
MicroKernel
First glance is good. Looks simple to use. I want to come back to this one later for a closer look.
ObjectBuilder
The documentation page shows 'under construction ...'. Not a good sign. The site was not first time visitor friendly so I reckon I will revisit this one only if I get desperate.
PicoContainer .Net
Nice documentation, looks cool, but it is really focused on Java. I get the feel that while .Net code is available it isn't really a prime focus. So I will skip this one.
Puzzle.Net
Looks interesting but difficult to find documentation. I noticed another project NPersist on the site that I want to look at later. This one is worth another look later.
Ninject
Looks real good for what I'm looking for. Lightweight. It uses a service binding concept so I need to check if a single interface can be 'bound' to different implementations for different targets.
Links:
The nature of the application is that it will have a long lifetime and will need to be expandable. Overall project complexity is medium.
Requirements:
- .Net C#
- License suitable for commercial use
- Require constructor injection (for readability) and setter injection to support circular dependencies
- Runtime creation of object sets
- Plugin support ... I'm not sure
- Suitable use in a TDD environment with mocking
- Code readability and simplicity
Spring.Net
The documentation introduction starts by describing Spring as being for 'enterprise applications' and goes on to talk about much more than IoC. So my first impression is that this may be too heavy for my liking.StructureMap
A dependency injection framework, nothing else. This I like.I've done a quick look at the documentation. My first impression is good. I noticed a feature suggesting support for mocked object injection. I've not looked further but this is interesting as I do spend time most days creating mock objects for injection.
MicroKernel
First glance is good. Looks simple to use. I want to come back to this one later for a closer look.ObjectBuilder
The documentation page shows 'under construction ...'. Not a good sign. The site was not first time visitor friendly so I reckon I will revisit this one only if I get desperate.PicoContainer .Net
Nice documentation, looks cool, but it is really focused on Java. I get the feel that while .Net code is available it isn't really a prime focus. So I will skip this one.Puzzle.Net
Looks interesting but difficult to find documentation. I noticed another project NPersist on the site that I want to look at later. This one is worth another look later.Ninject
Looks real good for what I'm looking for. Lightweight. It uses a service binding concept so I need to check if a single interface can be 'bound' to different implementations for different targets.Links:
Sunday, 2 September 2007
A 1930s Barrister-In-Law Recommendation
I was browsing through the October 1930 issue of Homes and Gardens (UK) , as you would on a fine Sunday, and found an important message I must bring to your attending. It is a customer testimonial from 'A Barrister-in-law' in an advertisement (page xiv) proudly titled 'Sewage Purification'.
"... Your sewage installation has given entire satisfaction. I take every opportunity of showing and recommending it to my friends .... it would be a public benefit if your system could be adopted everywhere in lieu of cesspools."
Well done Tuke & Bell, Ltd (London).
I also found advertisements for bird baths, dog beds, stools, rugs, etc just like those around our house and available at K-Mart. Hmmm.
"... Your sewage installation has given entire satisfaction. I take every opportunity of showing and recommending it to my friends .... it would be a public benefit if your system could be adopted everywhere in lieu of cesspools."
Well done Tuke & Bell, Ltd (London).
I also found advertisements for bird baths, dog beds, stools, rugs, etc just like those around our house and available at K-Mart. Hmmm.
Wednesday, 29 August 2007
Agile Adverts
These YouTube adverts are a hoot. Targeted at attracting software developers to agile companies.
This one is my favorite: My Favorite Things ... go ThoughtWorks!
Others here: AgileAdvert
Have fun.
This one is my favorite: My Favorite Things ... go ThoughtWorks!
Others here: AgileAdvert
Have fun.
Monday, 20 August 2007
Snippet - Sizing Text Controls Without OnPaint
We so often avoid considering font, screen resolution, etc when sizing a text control we often set a minimum size that looks good on our screen. For example, you need to display a value that may vary from say 1.1 to say 8,888,888.88 and need to set a width that will allow the value to be visible for all values.
Not hard, I just keep reinventing the wheel finding the how to. So having done this yet again today here is the tell all code snippet:
Not hard, I just keep reinventing the wheel finding the how to. So having done this yet again today here is the tell all code snippet:
Graphics graphics = control.CreateGraphics();Proudly simple (Nigel - I did originally type 'embarrassingly simple', but you are having such an effect on me!).
SizeF size = graphics.MeasureString(text, font);
Saturday, 18 August 2007
Pair Programming - Old Style Stations Still Sold
I've found a company that is selling pair programming work stations in the old, pre-XP, style here. I do not know the price. They even sell team clothing here. Maybe XP would be more effective with team clothing, the safety offered by this clothing seems to have been overlooked.
They even have an office suite available for a customer team that in true XP style speak with one voice here.
Just goes to show what is old is new.
They even have an office suite available for a customer team that in true XP style speak with one voice here.
Just goes to show what is old is new.
Wednesday, 15 August 2007
When To Use .Net Events
I've been a long fan of .Net events and have had great success with them. I like an event driven model. But recently I've been wrestling with code in which events seem to cause more complications than they solve. Today in discussion with colleagues about implementation of undo/redo in an application the penny dropped. Using events within presentation layers is good but not in domain (model) objects as they greatly complicate object persistence.
The undo/redo is a great example, if an object that is being deleted has subscriptions to events on other objects and the subscriptions are deleted how do you restore the object? If you do not delete them then your inactive object is now being modified by events from the still active objects. Besides, is it a code smell if domain objects are notifying each other of changes? Does that imply poor encapsulation?
It seems to be lifetime issue. UI components typically sit in a child-parent relationship were all are created and discarded together so the need to manage event removal is not as critical.
The undo/redo is a great example, if an object that is being deleted has subscriptions to events on other objects and the subscriptions are deleted how do you restore the object? If you do not delete them then your inactive object is now being modified by events from the still active objects. Besides, is it a code smell if domain objects are notifying each other of changes? Does that imply poor encapsulation?
It seems to be lifetime issue. UI components typically sit in a child-parent relationship were all are created and discarded together so the need to manage event removal is not as critical.
Tuesday, 14 August 2007
Should Unit Tests Share A Bed With Production Code?
I'm wrestling with the question of why not place unit tests in the production code assembly? Perhaps even in the same file as the class under test. When I first started doing unit tests this is how I started as it allowed testing protected and even private methods. But now I feel this is a code smell but I'm unable to quantify as to why (which is a smell in itself).
I'll probably end up editing this post as this is really a thinking exercise. I do feel that tests ought to be in a separate assembly and ought to only test public behaviour.
In support of in assembly/file unit tests:
I'll probably end up editing this post as this is really a thinking exercise. I do feel that tests ought to be in a separate assembly and ought to only test public behaviour.
In support of in assembly/file unit tests:
- Easier to find the tests
- Enables testing of internal and protected methods.
- As the tests reside in the production assemblies it means that a deployed application can be unit tested.
- TDD makes us use our code before writing it and as a result makes us think about its design. The public behaviour of a class is all that is important.
- Testing protected or internal members means we are testing aspects not visible to users of the class. Therefore it allows poor encapsulation (my opinion).
- Unit testing is about code development not end user functionality which are covered by user acceptance tests (UATs). So unit tests are useless on a deployed application as they inherently will behave the same (pass). If not, they are not unit tests.
Private Methods Can Be A Smell
When using TDD we write tests that give us a reason to write the production code we believe we need. The end result is that we end up with executable code specifications and an inherent 100% code coverage. But, if we find ourselves refactoring the code into private members for reuse then doesn't that mean that we have some duplicate test? That is, the same functionality is required by more than one public method.
This is not always the case, we could be calling the private method multiple times from the one public method. But if there are multiple public methods calling it then doesn't that mean that the tests on each of those public methods must each test all aspects of the private member? Duplication which is a smell.
The smell is that probably the tests for the following public methods are assuming that the first method's test test the private functionality. But this assumes that the code is not going to change (he he). So, I'm thinking that private methods that are invoked by calls to multiple public methods are a stench and ought not be allowed. In such cases refactor the code to extract the private method as a separate class or find a way to use one public method only.
Is this also a good example of why unit tests ought only test public behaviour. I'm wondering if the UT code was in the same assembly the private methods would be implemented as 'internal' or 'protected' methods and tested directly. I can see the attraction but it means that embedded classes remain hidden. The advantage of TDD in highlighting such cases is diminished.
I wonder if somebody has written a tool to detect such a code smell?
Links:
This is not always the case, we could be calling the private method multiple times from the one public method. But if there are multiple public methods calling it then doesn't that mean that the tests on each of those public methods must each test all aspects of the private member? Duplication which is a smell.
The smell is that probably the tests for the following public methods are assuming that the first method's test test the private functionality. But this assumes that the code is not going to change (he he). So, I'm thinking that private methods that are invoked by calls to multiple public methods are a stench and ought not be allowed. In such cases refactor the code to extract the private method as a separate class or find a way to use one public method only.
Is this also a good example of why unit tests ought only test public behaviour. I'm wondering if the UT code was in the same assembly the private methods would be implemented as 'internal' or 'protected' methods and tested directly. I can see the attraction but it means that embedded classes remain hidden. The advantage of TDD in highlighting such cases is diminished.
I wonder if somebody has written a tool to detect such a code smell?
Links:
Monday, 13 August 2007
A Pattern To Help Introduce Unit Testing?
Today I heard that our CEO saw some of our automated user acceptance tests (UATs). These are tests written from the user's perspective. You can see the screens flashing by. The impressive thing is that the CEO immediately saw the business value and commented on how they would lead to cost and time savings at the end of the project and beyond.
While this did puff up our pride it also made me realize that the value of UATs is self evident to our managers while unit tests are, rightfully, seen as 'secret developers business'. After all unit tests are about writing code and our users are not interested in code, they are only interested in working features.
So, I wonder if UATs can be used as a first step in introducing automated developer testing into an organization. That is, UATs first and then unit tests. If management needs to be convinced of the value this may be a good approach.
While this did puff up our pride it also made me realize that the value of UATs is self evident to our managers while unit tests are, rightfully, seen as 'secret developers business'. After all unit tests are about writing code and our users are not interested in code, they are only interested in working features.
So, I wonder if UATs can be used as a first step in introducing automated developer testing into an organization. That is, UATs first and then unit tests. If management needs to be convinced of the value this may be a good approach.
Saturday, 11 August 2007
EWSS Wikipedia
Today I found that the Wikipedia did not have any entry for External Water Spray Systems (EWSS) so I added one. The entry can be found here.
Monday, 6 August 2007
Achieving 'Flow'
In a conversation today it came up how high performance teams thrive on challenges. Well that was the opinion (which I do tend to agree with) and this reminded me of the concept of 'flow' that I once read about but could never find the reference to. But as Google would have it today I did find the magic words to find an article about flow.
As defined by Mihaly Csikszentmihalyi:
The conversation lead me to wonder if there is a relationship between high performance teams and flow. I wonder if the collaboration within the team with the various skill sets facilitates flow. Is collaboration a flow enabler?
To put it in other way, in a team members help each other and function as a unit. So does this enable each member to achieve their best ... that is, achieve flow?
Whatever the case I love flow. :-)
Other links:
As defined by Mihaly Csikszentmihalyi:
"... a state of deep focus that occurs when people engage in challenging tasks that demand intense concentration and commitment. Flow occurs when a person’s skill level is perfectly balanced to the challenge level of a task that has clear goals and provides immediate feedback."
The conversation lead me to wonder if there is a relationship between high performance teams and flow. I wonder if the collaboration within the team with the various skill sets facilitates flow. Is collaboration a flow enabler?
To put it in other way, in a team members help each other and function as a unit. So does this enable each member to achieve their best ... that is, achieve flow?
Whatever the case I love flow. :-)
Other links:
Sunday, 5 August 2007
Team vs Group Profitability
"Team" is most often used to describe any group that works as a group with a common project. But if the group is managed, or choses to work, as a group of individuals its effective output must become less than the sum of the individual capabilities. If a team implies a collaborative group that achieves an output greater than the summation of the individual capabilities then overuse of "team" hides what is possible.
The chart top right is a fabrication to illustrate my opinion (that is hopefully the result of my experiences). The assumption here is to compare two groups with members of the same expertise and expertise mix. The group either chooses to or is managed as individuals. The classic smell of this approach is assignment of areas of functionality to individual developers, or silence in the team's pit. A team is characterized by team ownership of tasks, integrity, frequent discussion, healthy conflict, and collaboration.
While interesting the chart is not surprising. The important thing is the ratio of effective output of the two groups charted. That is just how much more, in comparison, a team is more profitable than just a group. A kind of opportunity cost approach. The difference is large. My observation is that for a group of about 5 members, a team is typically twice as effective. If we factor into this the concept of a high performance team and member skills, much larger profitability can be achieved.
The definition of a high performance team that fits for me is:
It seems to me to stay in business there is no choice but to employ the best and insist on teamwork. The critical success factor is management. As a team can only foster if management makes the environment and mix of developers happen.
"A group is a team, but a team is more than a group."
- My assertion.
- My assertion.
The chart top right is a fabrication to illustrate my opinion (that is hopefully the result of my experiences). The assumption here is to compare two groups with members of the same expertise and expertise mix. The group either chooses to or is managed as individuals. The classic smell of this approach is assignment of areas of functionality to individual developers, or silence in the team's pit. A team is characterized by team ownership of tasks, integrity, frequent discussion, healthy conflict, and collaboration.
While interesting the chart is not surprising. The important thing is the ratio of effective output of the two groups charted. That is just how much more, in comparison, a team is more profitable than just a group. A kind of opportunity cost approach. The difference is large. My observation is that for a group of about 5 members, a team is typically twice as effective. If we factor into this the concept of a high performance team and member skills, much larger profitability can be achieved.
The definition of a high performance team that fits for me is:
"A high performance team is a team which achieves an output that far exceeds the summation of the capabilities of its members."
- I forget the author's name.
- I forget the author's name.
It seems to me to stay in business there is no choice but to employ the best and insist on teamwork. The critical success factor is management. As a team can only foster if management makes the environment and mix of developers happen.
Home Bushfire EWSS & Fire Hoses
Living in a high bushfire (wildfire) risk area we decided to install a bushfire pump / EWSS / fire hose system when we bought the house. Thing is we both work so we are most likely to be at work on a high fire risk day. Having much loved dogs this meant that we wanted a system that made us feel safe and that we could remotely start to protect our dogs from a surface fire resulting from an ember attack. An ember attack is most likely. The house being almost 100 years old has survived a few ember attacks so that is our focus.
So, I've finally started to document our system. The trouble with bushfire EWSS (External Water Spray Systems) is that there is very little hard research so there are many 'opinions'. I've only found one paper on EWSS but I will blog on that another time.
Given the nature of an ember attack, if we are not home the only proper home defense would be a full deluge system that would need to run for hours as detecting spot fires is not practical as the amount of water required would be huge (town water may not be available). Also, the CFA tells us that fires start from inside a house. How can we detect a broken window and deluge a room?
So the objectives of the initial system are:
The attached diagram is my first attempt at documenting our system. We chose a Davey Firefighter 5 pump as the Honda engine is very reliable and this version provides a flat pressure curve over a wide flow rate (up to about 500L/m) which means that we can use it drive hoses and sprinklers at the same time. We got the electric start model as we want to remote start it and in any case we do not want to fighting a recoil start when stressed out.
The remote start system is bases around a low power 12VDC computer system and our home internet connection is also powered off the battery backed 12V supply which is real convenient as we often loose power in this are. More about that later.
More photos of the system here.
So, I've finally started to document our system. The trouble with bushfire EWSS (External Water Spray Systems) is that there is very little hard research so there are many 'opinions'. I've only found one paper on EWSS but I will blog on that another time.
Given the nature of an ember attack, if we are not home the only proper home defense would be a full deluge system that would need to run for hours as detecting spot fires is not practical as the amount of water required would be huge (town water may not be available). Also, the CFA tells us that fires start from inside a house. How can we detect a broken window and deluge a room?
So the objectives of the initial system are:
- Protect the dogs from a surface fire during an ember attack. We can keep this area wet for about 6 hours with available water so this is 'possible'.
- Run fire hoses to make home defense easier.
- Independent water supply (25,000L) as town water may not be available.
- Run without mains electricity as history shows that the power goes early in a bushfire.
- Remote start from work.
The attached diagram is my first attempt at documenting our system. We chose a Davey Firefighter 5 pump as the Honda engine is very reliable and this version provides a flat pressure curve over a wide flow rate (up to about 500L/m) which means that we can use it drive hoses and sprinklers at the same time. We got the electric start model as we want to remote start it and in any case we do not want to fighting a recoil start when stressed out.
The remote start system is bases around a low power 12VDC computer system and our home internet connection is also powered off the battery backed 12V supply which is real convenient as we often loose power in this are. More about that later.
More photos of the system here.
Monday, 30 July 2007
Serial Protocol Driver Stack
The static structure diagram shown to the left is a typical protocol driver stack.
This static structure provides:
This static structure provides:
- Support for both Multi-drop or Point to Point communications protocols.
- Protocol abstraction to facilitate multiple protocol implementations.
- I/O Device specific façade to the application.
- Simulation capability to enable automated testing of the full protocol stack.
- Port abstraction allowing implementation of a protocol via different port types. e.g USB, TCP, or RS232.
- Dynamic routing or path modelling.
- Redundant paths.
- Host level redundancy.
- Use of multiple port channels (multi-link protocols).
Sunday, 29 July 2007
Serial Protocol Driver States
Many applications require a serial communication protocol to communicate with PLCs, RTUs, instruments, weather station, etc. The implementation is often ad-hoc and often problematic, especially in recovering from fault conditions caused by bit error rates or just tripping over a cable. It seems to me that there is a common design pattern for protocol states which can be implemented in whole or part depending on the domain. I'm hoping that a generic driver can be developed from this to provide a common driver framework.
The advantage of understanding the pattern is to acquire the know how needed even in very reliable communication paths such as over USB.
The state chart above shows the full generic implementation. This state engine provides:
Transitions from this state:
Transitions from this state:
Opening State
The Opening state is a transitional state in which the driver establishes a communication channel with the remote device. This is protocol dependent and may be:
The Opening state is used when trying to open a channel for the first time (from the Started state) and when trying to reconnect a failed channel (from the Failed state).
Transitions from this state:
Open State
Data transfers may occur only in the Open state. The driver is in the Open state when communications with the remote device has been validated.
Transitions from this state:
Failed State
The failed state provides:
The closing state provides orderly communication channel disconnection. Depending on the protocol and application this may include:
The advantage of understanding the pattern is to acquire the know how needed even in very reliable communication paths such as over USB.
The state chart above shows the full generic implementation. This state engine provides:
- Support for control of exclusive system resources such as COM or USB ports independent of the communication channel state control. That is, the channel may be opened and closed without releasing resources.
- Error recovery.
- Transitional states for asynchronous state transitions which also allow for features such as 'back-off' time enforcement on channel shut down.
- Unambiguous states to simplify client use.
- Actions to control state available in every state for immediate execution, including the transitional states.
Stopped State
The stopped state is the initial state. In this state the protocol driver has been instantiated but has not acquired any resources. The driver should be placed in this state before disposing.Transitions from this state:
- On call to Start() transitions immediately (synchronously) to the Started state.
- Re-entrant on a call to Reset().
- A call to any other state interface method will cause a transition to the Error state.
- From any other state, including the Error state, by a call to Reset().
- From the Started state by a call to Stop().
Started State
On entering the started state the protocol driver acquires all required resources. Typically this is opening exclusive resources such as a COM or USB port. High performance drivers may use configuration information to preallocate memory.Transitions from this state:
- On call to Open() transitions to the transitional Opening state. It is possible that the state may also transition to the Open or Failed state prior to Open() returning.
- On call to Stop() transitions to the Stopped state. All resources are released prior to this transition.
- A call to any other state interface method will cause a transition to the Error state.
- From any other state, including the Error state, by a call to Reset().
- From the Stopped state by a call to Start().
- Asynchronously from the Opening state by a call to Close().
- Asynchronously from the Open state, via the Closing state, by a call to Close().
- Synchronously from Failed state by a call to Close().
Opening State
The Opening state is a transitional state in which the driver establishes a communication channel with the remote device. This is protocol dependent and may be:- Protocol transactions to open a session
- A simple poll to establish that the link exists
The Opening state is used when trying to open a channel for the first time (from the Started state) and when trying to reconnect a failed channel (from the Failed state).
Transitions from this state:
- On success, transitions to the Open state.
- On failure, transitions to the Failed state.
- On call to Close() immediately transitions to the Closing state.
- A call to any other state interface method will cause a transition to the Error state.
- From the Started state Open().
- From the Failed state on a call to Open() or by a reconnect timer time out.
Open State
Data transfers may occur only in the Open state. The driver is in the Open state when communications with the remote device has been validated.Transitions from this state:
- On communication failure, transitions to the Failed state.
- On call to Close() immediately transitions to the Closing state.
- A call to any other state interface method will cause a transition to the Error state.
- From the Opening state on successful communications channel validation.
Failed State
The failed state provides:- Unambiguous indication of unexpected communications failure.
- Optional implementation of a driver that can automatically reconnect.
- When conditions for attempting a reconnect (typically a time out) transitions to the Opening state.
- On a call to Open() immediately transitions to the Opening state.
- On a call to Close() immediately transitions to the Closing state.
- A call to any other state interface method will cause a transition to the Error state.
- From the Open state on communication failure.
The closing state provides orderly communication channel disconnection. Depending on the protocol and application this may include:
- Session disconnection transaction with the remote device.
- Flush pending transactions.
- Allow timing for completion of transactions already commenced.
- Implement 'back-off' timing to enforce an idle time between sessions to ensure time-out of any incomplete transactions.
- On completion of channel/session closure, transitions to the Started state.
- On call to Close() immediately transitions to the Closing state.
- A call to any other state interface method will cause a transition to the Error state.
- From the Opening, Open, or Failed state on a call to Close().
- Re-entrant on calls to Close().
Wednesday, 18 July 2007
Snow!
We got a real surprise this morning to wake up to snow. We had a few centimeters of snow on the ground. The place looked great. Driving to work the mountain looked something like a northern hemisphere Christmas card. Quiet a treat.
Sue stayed home and after a little initial hesitation the dogs loved the snow. Violet had great fun jumping in it.
We see snow flakes once or twice each year but it unusual to actually see snow on the ground.
The top left photo shows Violet and Golly running down the back path. The other photo shows the view across the road.
Sue stayed home and after a little initial hesitation the dogs loved the snow. Violet had great fun jumping in it.
We see snow flakes once or twice each year but it unusual to actually see snow on the ground.
The top left photo shows Violet and Golly running down the back path. The other photo shows the view across the road.
Wednesday, 11 July 2007
A Metric To Measure Legacy Code Debt
It is not uncommon for a project to have 'legacy' code. That is, code that has poor health usually due to poor structure. This code makes it harder to add functionality. So if the team is to refactor this code as it goes to improve its health how does it measure its progress? How does the project manager measure the debt? If we cannot measure the benefits how do we justify the cost?
In the project I'm currently on we at least have the luxury of identifying this older code as code written without unit tests (using TDD). So we wonder if we can measure the debt by unit test (not User Acceptance Tests) coverage. This allows us to have a metric to say what % of our code is what we call 'legacy' code so we can then track this against our velocity. We expect our velocity to rise as the % falls. If it does not then we have an early indicator that perhaps our efforts to refactor the code is not productive.
This will be interesting.
In the project I'm currently on we at least have the luxury of identifying this older code as code written without unit tests (using TDD). So we wonder if we can measure the debt by unit test (not User Acceptance Tests) coverage. This allows us to have a metric to say what % of our code is what we call 'legacy' code so we can then track this against our velocity. We expect our velocity to rise as the % falls. If it does not then we have an early indicator that perhaps our efforts to refactor the code is not productive.
This will be interesting.
Saturday, 7 July 2007
Golly and Violet - The Play Team
Golly and Violet continue to really enjoy each other's company. This morning I took a short video of their playing in the lounge room and uploaded it to YouTube here.
Thursday, 5 July 2007
User Acceptance Test Pattern
Automated User Acceptance Tests (UATs) compliment unit tests but are different. Today Nigel proposed a pattern for UATs. The benefit of the pattern is to give clear responsibilities of roles of classes within the UAT code. This is a great benefit.
I expect that he will post the full pattern but the roles were of Context, Tests, Jigs, and Testers. Where:
Context is the context of what is being tests and is implemented as base classes. A context provides actions suitable for the context of the test. e.g. If the UAT is on a UI page displaying a weather forecast then perhaps the base context class will offer methods to read temperature predicted from the page.
Tests are the tests that drive user actions and make assertions. e.g. Open page, get forcaset temperature, assert that forecast temperature displayed is XX.
Jigs are wrappers for user controls, typically UI pages. They encapsulate access to the controls (in a UAT manner) using the testers. e.g. A test jig for the forecast page may have a property to get a tester for the forecast temperature control.
Testers are underlying framework classes for testing UI controls. e.g. NUnitForms.
I expect that he will post the full pattern but the roles were of Context, Tests, Jigs, and Testers. Where:
Context is the context of what is being tests and is implemented as base classes. A context provides actions suitable for the context of the test. e.g. If the UAT is on a UI page displaying a weather forecast then perhaps the base context class will offer methods to read temperature predicted from the page.
Tests are the tests that drive user actions and make assertions. e.g. Open page, get forcaset temperature, assert that forecast temperature displayed is XX.
Jigs are wrappers for user controls, typically UI pages. They encapsulate access to the controls (in a UAT manner) using the testers. e.g. A test jig for the forecast page may have a property to get a tester for the forecast temperature control.
Testers are underlying framework classes for testing UI controls. e.g. NUnitForms.
Sunday, 1 July 2007
Storms Leave Us Without Power
On Wednesday a storm caused lots of damage here on Mount Dandenong. Many trees fell causing damage to half a dozen houses and the nearby school lost a building. Three or four large Mountain Ash trees (20-40 meters) fell on the tourist road between Olinda and Kalorama. We lost power from 9am on the Wednesday through to about Friday 1am.
Coming home on Wednesday night was a bit scary with roads closed. Two roads I tried were closed but I found a third dirt road which was clear. We were lucky with the only damage being from a very large Mountain Ash falling across our far rear fence. A monster of a tree that fell from the other side of the gully, has to be about 40m long. I'm getting quotes for insurance as it is going to be a lot of work to clear the fence and paths.
Next door was not so lucky with one tree falling across their driveway, over the fence, pulled down the street power lines, and blocked the road. But it only took 30 minutes to clear enough for cars to get by. Worse was a neighbor's tree falling and damaging a cottage behind their house.
Fortunately we had bought a generator a few months ago so that allowed us to at least run our gas heating and watch some TV. A good test as this area has been known to loose power for longer periods after bushfires etc. So now we know we need a bigger generator.
But hey, we live up here because we love the trees, so we cannot complain when a tree falls over the power lines.
Coming home on Wednesday night was a bit scary with roads closed. Two roads I tried were closed but I found a third dirt road which was clear. We were lucky with the only damage being from a very large Mountain Ash falling across our far rear fence. A monster of a tree that fell from the other side of the gully, has to be about 40m long. I'm getting quotes for insurance as it is going to be a lot of work to clear the fence and paths.
Next door was not so lucky with one tree falling across their driveway, over the fence, pulled down the street power lines, and blocked the road. But it only took 30 minutes to clear enough for cars to get by. Worse was a neighbor's tree falling and damaging a cottage behind their house.
Fortunately we had bought a generator a few months ago so that allowed us to at least run our gas heating and watch some TV. A good test as this area has been known to loose power for longer periods after bushfires etc. So now we know we need a bigger generator.
But hey, we live up here because we love the trees, so we cannot complain when a tree falls over the power lines.
Tuesday, 12 June 2007
My Firefox configuration
I use multiple PCs each day, the following is a list FireFox add-ons that I use to help me synchronize between the PCs and I just like.
Add-ons I like:
PermaTabs is great for TV guide, weather, build box (CruiseControl), etc. I like the way it only loads the page when the tab is first selected and that you cannot browse from the page. Which pages are made 'permanent' is dependent on the PC as each has a different use (e.g. work or home).
PDF Download
PDF Download is great as I often find viewing PDF documents in my browser crashes the browser. This add-on gives me the choice of view in browser, download, or view using Acrobat external to the browser (my preference).
New Tab On Tab Bar
Because it is just real useful. I use that little button a lot.
IE Tab
Not all pages play fair with Firefox. What I really like about IE Tab is that I can configure it so that those IE preferred pages I visit automatically open in a tab using IE rendering. Cool.
Foxmarks Bookmark Synchronizer
Great for keeping my bookmarks synchronized between my boxes. Useful but not great. I only use this between my home boxes as it has no way of excluding some bookmarks. Its merge is a bit primitive but at least it is conservative so I does synchronize and does not loose bookmarks.
del.icio.us Bookmarks
Yet to figure out why I like del.icio.us. I have visions of one day thinking 'what was that site' and being able to go to del.icio.us from work and find it. I think it is good, but it has yet to prove its value to me.
Add-ons I like:
- PermaTabs
- PDF Download
- New Tab On Tab Bar
- IE Tab
- Foxmarks Bookmark Synchronizer
- del.icio.us Bookmarks
PermaTabs is great for TV guide, weather, build box (CruiseControl), etc. I like the way it only loads the page when the tab is first selected and that you cannot browse from the page. Which pages are made 'permanent' is dependent on the PC as each has a different use (e.g. work or home).
PDF Download
PDF Download is great as I often find viewing PDF documents in my browser crashes the browser. This add-on gives me the choice of view in browser, download, or view using Acrobat external to the browser (my preference).
New Tab On Tab Bar
Because it is just real useful. I use that little button a lot.
IE Tab
Not all pages play fair with Firefox. What I really like about IE Tab is that I can configure it so that those IE preferred pages I visit automatically open in a tab using IE rendering. Cool.
Foxmarks Bookmark Synchronizer
Great for keeping my bookmarks synchronized between my boxes. Useful but not great. I only use this between my home boxes as it has no way of excluding some bookmarks. Its merge is a bit primitive but at least it is conservative so I does synchronize and does not loose bookmarks.
del.icio.us Bookmarks
Yet to figure out why I like del.icio.us. I have visions of one day thinking 'what was that site' and being able to go to del.icio.us from work and find it. I think it is good, but it has yet to prove its value to me.
Monday, 11 June 2007
Rowan Was A Good Friend
After a year of chemotherapy Rowan's time came today. The last year had been good, he has been a happy dog. Today has been very sad and difficult.
We will miss him beside the bed every night, his happy groan when he gets a cuddle, his gentle demeanor, and his chuffed joy whenever he caught the kong. We are missing a very dear and loyal friend.
We will miss him beside the bed every night, his happy groan when he gets a cuddle, his gentle demeanor, and his chuffed joy whenever he caught the kong. We are missing a very dear and loyal friend.
Friday, 8 June 2007
Using Subversion Revision as the AssemblyVersion
Today I spent a few hours configuration our work projects to automatically use the Subversion (SVN) revision number as the assembly version in the AssemblyInfo.cs file in each project.
The motivation was:
The motivation was:
- Give direct traceability from the build number to the SVN revision.
- With Subversion's atomic commits, make it clear which code was used for each debug/release build etc.
- Automatic incrementing of the build number.
- Auto-generate one AssemblyInfo.cs file using Tigris MSBuild community tasks project target for the solution (product).
- All projects include that AssemblyInfo.c file by reference. Hence all assemblies have the same build number.
- To make sure that the AssemblyInfo.cs file is generated first it a "Common" project was added to the solution with dependencies to ensure it would build first. Right now it does not have any source files, it just builds the AssemblyInfo.cs file.
- Added the generated AssemblyInfo.cs file to Subversion's ignore list. This avoids the file appearing as changed in all projects.
Thursday, 7 June 2007
Automated Customer Acceptance Tests - Jigs
Over the last few days at work we seem to have finally succeeded in creating an environment in which we can easily write customer acceptance tests. It is so cool! We are using a combination of NUnit, NUnitForms, and custom "jigs" (thanks goes to Nigel for the guidance and inspiration).
How it works is that NUnit and NUnitForms provide a base framework but the test actually (mostly) use jig classes. That is, a jig for each UI form. The application is one jig and all others are exposed as properties of that jig. Each child control is accessible as a property on the parent control's jig. In each case the jig returns the NUnitForms tester class, not the actual control.
The end result is that the Customer Acceptance Tests (CATs) are simple (usually only half a dozen lines each) and self-documenting. In combination with unit tests they are killers.
Now we have this it is evident that these "jigs" could be auto-generated at compile time by a tool. A jig for each user control in our project. This would also allow us to automatically add code to hide the actual control so that attempts to access (click etc) are only possible if the control is visible. In a CAT we ought to only be able to do what the user can do.
How it works is that NUnit and NUnitForms provide a base framework but the test actually (mostly) use jig classes. That is, a jig for each UI form. The application is one jig and all others are exposed as properties of that jig. Each child control is accessible as a property on the parent control's jig. In each case the jig returns the NUnitForms tester class, not the actual control.
The end result is that the Customer Acceptance Tests (CATs) are simple (usually only half a dozen lines each) and self-documenting. In combination with unit tests they are killers.
Now we have this it is evident that these "jigs" could be auto-generated at compile time by a tool. A jig for each user control in our project. This would also allow us to automatically add code to hide the actual control so that attempts to access (click etc) are only possible if the control is visible. In a CAT we ought to only be able to do what the user can do.
Tuesday, 5 June 2007
Sipura Dial Plan Manager Now On SourceForge
I finally got around to opening a SourceForge project for my Sipura 3000 Dial Plan Manager software I wrote some time ago. It feels good just to upload to their SVN repository as now I know it is safe.
The project URL is http://sourceforge.net/projects/sipuradialplan/. No documentation yet, nor binaries. Just the source code.
The project URL is http://sourceforge.net/projects/sipuradialplan/. No documentation yet, nor binaries. Just the source code.
When I Die I Want These Dogs' Lives
Our three Airedales making themselves at home. That is Golly far top right in the cage (not a great photo so take my word for it). Rowan is resplendent on the bean bag while Violet makes do with her best road kill impersonation (near bottom left).
Golly is doing just fine. He spends most of his time with Violet. Rowan is interested in him, but only on his terms. He is still getting grumpy with a little puppy nibbling on his tail.
Golly is doing just fine. He spends most of his time with Violet. Rowan is interested in him, but only on his terms. He is still getting grumpy with a little puppy nibbling on his tail.
Monday, 4 June 2007
Golly! A New Puppy
On Saturday (today is Monday) we collected our new Airedale puppy Golly and brought him home to meet our other two Airedales Violet and Rowan. He was only frightened of the two big dogs for about 60 seconds and then he was chasing them! The picture was taken about an hour after he met them.
Rowan and Violet were besotted with him. As the day wore on Rowan got a bit grumpy but Violet cannot get enough Golly and has formed a very strong bond.
Rowan is not well, and normally likes to be quiet anyway so we are keeping him separate most of the time which is not hard as he loves to sleep on the carpet at Sue's feet, and Golly and Violet are either asleep or pouncing on each other.
Rowan and Violet were besotted with him. As the day wore on Rowan got a bit grumpy but Violet cannot get enough Golly and has formed a very strong bond.
Rowan is not well, and normally likes to be quiet anyway so we are keeping him separate most of the time which is not hard as he loves to sleep on the carpet at Sue's feet, and Golly and Violet are either asleep or pouncing on each other.
Friday, 1 June 2007
Choosing an open source license
I have an open source project (NXmlSerializer) which I want to use at work. This lead to a good discussion with other developers and managers about open source development, how both the company and the community win, and has made me spend some time taking a closer look at which open source license I use. The selection points I've come up with are:
- Avoid any liabilities
- Allow free use
- Allow commerical use
- Encourage collaboration
Subscribe to:
Posts (Atom)