Wednesday, 19 November 2008

What if they just don't get you?


Experiencing feedback is really like it sounds. You are holding the microphone of life and you turn to face the speakers. They scream and squeal in agony as the sound makes the sound of the sound making the sound.

Feedback is good for me. They all say it is. People who I want to be when I grow up.

Some people put effort in to it and make comments that will haunt but improve you.
Others take the 95% of you what is good and put that aside. Then they take a gigantic magnifying glass and hold it up so the Sun burns the 5%. They want to fix you.

Here is my view of feedback in a formal and informal sense...

  1. Always have real life examples for someone when you stand before them and compliment of condemn them. Both situations require honestly and example to show you sincerly care;
  2. Don't put it in writing if it burns - oh how it burns. People don't need to see something in writing that could have been improved with a conversation. Sometimes, taking the time to sit and drink coffee and talk to someone can mend anything you think needs mending. Remember to tell them that if you didn't care then you would not bother sharing;
  3. Mean well. Always mean to help or improve and share. Otherwise, there is no point in bothering.
How do you see feedback?

Saturday, 15 November 2008

Making your own VS.NET nunit Test Project Template

Returning to .NET has been exciting after a long time away playing in Java and Ruby land. I can't say I'll miss XML config files and all that junk.

First thing I did after creating my first ASP.NET MVC project was to add a template to easily create a project to test it. The new template will create a class library project with MVC, nunit and my mocking framework of choice Rhino included and ready to go.

When you use VS.NET 2008 to create an MVC web application, it asks if you want to add a testing project to go alongside. Unfortunately, the only choice of test project template you get is the Microsoft one and I like nunit much much more.

This is how we do it...

Set the project up the way you want it to appear new
  1. Create a new C# class library project. Give it a general name which will apply to your test project template.
  2. Add a reference to the System.Web.MVC dll.
  3. Add a reference to the nunit.framework dll.
  4. Add a reference to the Rhino.Mocks dll.
  5. Set the Copy Local property for all of the above dll references to True.
  6. Create a Controller folder under the project root.
  7. Add a class HomeControllerTest to the Controller folder.
  8. Add unit tests to cover the About and Index actions.
  9. Build your project to get the binaries.

Export the project template

  1. Go to File --> Export Template and use the wizard to export the template. Call it NUnitTest. You will be told where the zip file is saved to.
  2. Be sure to chose the option to include the icon.
Importing the new template
  1. Move the NUnitTest.zip to %Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\Csharp\Test\1033. This might be different for you.
  2. Quit Visual Studio.
  3. Open a command prompt and navigate to %Program Files%\Microsoft Visual Studio 9.0\Common7\IDE.
  4. Execute devenv /setup and go make a cup of coffee.
  5. If you now open VS.NET 2008 and create a new project, you should be able to see your template show up under the C#-->Test directory.
  6. Add the registry key below by copying the text in to a file and calling it nunit.reg. Run this regfile to add the key. You can add it manually also using regedit.


Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\MVC\TestProjectTemplates\NUnit\C#]
"Template"="NUnitTest.zip"
"Path"="CSharp\\Test"
"TestFrameworkName"="nunit Test"
"AdditionalInfo"="http://msdn2.microsoft.com/en-us/library/ms243147(VS.80).aspx"
"Package"=""

Monday, 3 November 2008

Bar Camp Sydney

Barcamp Sydney is on again...

Details

  • Who? Anyone who is interested in technology, the Internet and related topics. We have room for more than 200 people, so bring your colleagues.
  • What? A good opportunity to share ideas and projects and to work with like-minded individuals.
  • When? 9am-6pm on Saturday 15 November 2008
  • Where? BarCampSydney will be held at the Roundhouse at UNSW, Anzac Parade. See WikiMapia for details about the location.
  • Getting There Lots of buses to & from Central or Elizabeth St (39x, L94). Click HERE for details on busses from the City (QVB) to UNSW to get you to there on time, and see the Univeristy Busses Page for details about getting back to the city. For Parking see the University Parking Map - All day parking is on the upper floors of the Barker St and Botany St Parking Stations and will cost you $12 for the day. Plenty of nearby street parking just over Anzac Pde.
  • Website? The BarCampSydney blog is located at: www.BarCampSydney.org. We'll be posting updated information about the event there.
  • On the day A map of local food, drink and transport here. wino kredyt mieszkaniowy sprzedam mieszkanie sprzedam bilet

Friday, 31 October 2008

Finding our target velocity without black magic

To be in the moment (and I always like to be), here is a post for Halloween that removes the black magic from the estimation process and determines initial velocity.

Photo by euart used under the flickr Creative Commons license

Starting a new project and being around from the beginning is always an eye opener. If you are involved in estimation then it is also like signing a contract. Breach of promise to reach the guessed random number can be punished with overtime and a sense of failure. Heaven forbid a late project especially if it is fixed price.

I've started a new project and we are working out how long it will take and what resources are required. For the first time, estimation seemed more deliberate and less like guesstimation.

This is how we did it...

What you need to start estimating:
  • The latest draft of the master story list - a list of the all the stories known so far, written like "AS a person using the system, I WANT TO do something functional SO THAT business value is achieved";
  • As many members of the delivery team as possible - including engineers, testers (QA), business analysts (BA) and even business;
  • Agree on the length of an iteration;
  • An estimation deck - usually consisting of cards representing the Fibonacci sequence between 1 to 13. If you don't have this then use your fingers with 10 fingers = 13;
  • A willingness to estimate in points and not days;
  • A big table for everyone to sit around and to spread the cards on;
  • Snacks - this can take a while.
Next you get the team to understand what you are building, both high-level technically and what the business wants:
  • Sit everyone down at the table;
  • Have the BA or Project Manager (PM) read through every story;
  • Allow questions to understand what the story means;
  • Rewrite or breakdown stories in to small functioning parts;
  • Write out all stories on 4x6 cards.
Now you start throwing numbers around:
  • Re-read the stories;
  • Get everyone involved in delivery to do min-likely-max estimates and write them on the back of the cards- minimum points if all goes blissfully well, likely points in a realistic situation and maximum points if all hell breaks loose;
  • For each story work out volatility - low, medium or high;
  • For each story work out completeness - complete, incomplete or unknown;
  • For each story work out complexity - simple, medium or complex;
  • Engineers group the stories in to what they think they could complete in one iteration. Use about 5 groups - dependencies and iteration order are not important. Just look at the size of the stories and group an iterations worth;
  • PM secretly adds up the total likely estimated points from the groups and works out average iteration velocity;
  • PM lays out different groups of stories that would fit in to the new predicted velocity - note this is not the teams actual velocity because that isn't known until they actually start banking points;
  • The engineers looks at the groups and decide if they are too big, just right or too small - it's a little like Goldilocks;
  • Rinse and repeat - this can be re-estimated and sorted again to double check numbers.

Monday, 27 October 2008

Don't Embrace Mediocrity

used under the flick creative commons license by caravinagre

I wrote a post a while ago that somehow got on to a few of the IT aggregators and resulted in an influx of readers, many of whom were interested in what was a popular topic at the time. That attention brings out the good, the bad and the ugly on the Interblag.

A friend of mine who regularly blogs about food on our work blog feeder has also recently been attacked by the freak-geek police and told her blog doesn't belong as it isn't technical. Amusingly enough, it wasn't even a work colleague who said this.

After spending an hour listening to Edward de Bono talk about why arguing a point doesn't always produce the best outcome, I'm starting to see that point of view reinforced online. It was probably always there but it seems relevant to me now. So let's discuss it and also annoy the people who think that only code snippets belong in blog posts.

Are any new ideas being added to the blogosphere? Is blogging dead? If it is and there are no new ideas then what or who killed it?

It seems that if you are established, usually not through rising on the Internet but through a more traditional (and rightfully respected) publishing background, then your opinion is rarely knocked online. Social proof or tangible proof. If you are more like the bloggers I see out there with new ideas and different ways of thinking and challenging the established norm, then your words will be hammered. Interestingly enough, it is a small enough group who attacks so it doesn't really matter most of the time. It does however feel like that constant beating at the edges of the blogosphere, is dulling the interesting sparky parts.

It even has the potential to silence any new comers who think they might have something to say and haven't quite found their voice. Instead those who are happy with the way the Internet appears to be to them want to keep it that way. Maintain the average. Silence the creativity. It's an obscure notion to tell someone else not to speak so I will not tell them not to speak as they so happily feel the right to do to others.

Instead, I encourage any of you out there with something to say to stand up and say it. Ignore the push toward mediocrity. I paraphrase the wise and powerful Madonna in saying: Express what you've got, baby ready or not. Express yourself!

This one is better: ruby-net-ldap

After posting a quick how-to about Ruby-LDAP, I received a couple of very helpful comments that pointed me towards ruby-net-ldap. This is a pure Ruby LDAP library that is stable and has good documentation to help you along. It is the best Ruby LDAP gem out there and I've been through almost all of them to get to this point.

Here is a simple search for an organizational unit with the name "marketing"...


require 'rubygems'
require 'net/ldap'

def ldap_search

 ldap = Net::LDAP.new
 ldap.host = "localhost"
 ldap.port = "389"
 ldap.auth "cn=Directory Manager", "password"

 filter = Net::LDAP::Filter.eq( "ou", "marketing" )
 attrs = [ "ou" , "objectClass"]

 ldap.search( :base => "dc=mycompany, dc=com", :attributes => attrs, :filter =>
 filter, :return_result => true ) do |entry|
   puts entry.dn
 end

end


Here is the code to add an organizational unit under the base node...


require 'rubygems'
require 'net/ldap'

def ldap_search

 ldap = Net::LDAP.new
 ldap.host = "localhost"
 ldap.port = "389"
 ldap.auth "cn=Directory Manager", "password"

 dn = "ou=marketing, dc=mycompany, dc=com"
 attr = {
   :ou => "marketing",
   :objectclass =>"organizationalUnit"
 }
 ldap.add( :dn => dn, :attributes => attr )

end



Check out the rest of the documentation for pretty good examples. This is the library I recommend. In my situation, I'm using ruby-net-ldap to import data in to, manipulate and query data in an OpenDS LDAP server.

Sunday, 5 October 2008

Ruby-LDAP

I said it would never happen but here is another Ruby blogpost for the ThoughtWorks pool. In my defense, there really wasn't much help out there on this topic so my pair and I decided this had to be posted. His post on what we tried in order to make Ruby talk to LDAP is over there.

The Bits
OpenDS is Sun's LDAP server. We chose this as our LDAP server because it is the one most likely to sit behind the OpenSSO Single Sign-On implementation we are populating, querying and binding to. It is written purely in Java and provides a bunch of useful shell scripts and a Java API to do the things we want to do. This will allow us to test our Ruby-LDAP implementation independently of our solution.

OpenDS has a nice installer with a friendly setup wizard. If you want to script the install then run this from the root of the installation directory:


>$ './setup --cli --no-prompt -p 1389 -D "cn=Directory Manager" -w "password" -b dc=example,dc=com -a --doNotStart'


Ruby-LDAP was the friendliest and most sensible choice because it was the most pure Ruby choice which allowed us to do things the Ruby way. RJB let us use the OpenDS libraries but was too much like writing Java in Ruby and involved running another JVM on the production server it is destined for. If we were to go that far then we'd have opted for JRuby to do the bridging. After ActiveLDAP flat out refused to acknowledge OpenDS and would only play well with OpenLDAP, that was written off. Ruby-LDAP is a written in C so it isn't a nice gem install but instead takes a bit of making and shaking to get going.

Here is how to install it from the command line once it is downloaded and unzipped:

>$ ruby
ruby-ldap-0.9.7/extconf.rb "."
>$ make
>$ make install

The Required Basic LDAP Knowledge
LDAP is like a very simple and slightly stupid database for storing Identity information. It does not have transactions. You can't query it with SQL. It is a tree. It does have a schema.

Understand your LDAP schema. You can customise it. It is made up of nodes that are defined by object classes and attributes. These include but are not restricted to: Organization; OrganizationalUnit; and Person.

Distinguished Name (DN) appears everywhere when you are dealing with LDAP. It is the unique name given to a node in the LDAP tree and describes the exact path from the node to the root. A DN starts at the node and walks up the tree. It looks like: uid=damana,ou=australia,dc=mycompany,dc=com

This is an LDAP glossary that was useful in deciphering the LDAP maze and nomenclature.

Adding an Organizational Unit
To add an organizational unit:


#/usr/bin/ruby -w

require 'ldap'

connection = LDAP::Conn.new('localhost', 1389)
connection.bind('cn=Directory Manager','password')

record = [
LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['organizationalUnit']),
LDAP.mod(LDAP::LDAP_MOD_ADD,'ou',['australia
']),
]

connection.add("ou=branches, dc=
mycompany, dc=com", record)

connection.unbind


Adding a User
To add a user to an organizational unit:


#/usr/bin/ruby -w

require 'ldap'

connection = LDAP::Conn.new('localhost', 1389)
connection.bind('cn=Directory Manager','password')

record = [
LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['person']),
LDAP.mod(LDAP::LDAP_MOD_ADD,'cn',['Damana Madden']),
LDAP.mod(LDAP::LDAP_MOD_ADD,'cn',['dmadden']),
LDAP.mod(LDAP::LDAP_MOD_ADD,'sn',['Damana Madden']),
]

connection.add("cn=Damana Madden ou=australia, dc=mycompany, dc=com", record)

connection.unbind


Deleting a User
To delete a user:


#/usr/bin/ruby -w

require 'ldap'

connection = LDAP::Conn.new('localhost', 1389)
connection.bind('cn=Directory Manager','password')

connection.delete("cn=Damana Madden ou=australia, dc=mycompany, dc=com")

connection.unbind

Acknowledge Me

Apple started a user experience trend many iOSes ago when it accepted Settings changes and did not ask for confirmation. Once the chang...