Brian Richardson

Coding, traveling, etc.

SD West

I made it home tonight and I have to say this last week has been amazing. I learned a great deal and feel this was probably the best experience of my career so far. Besides being able to attend lectures from some of the top people in the industry who were able to pass on so much valuable information from their own personal experiences, we also had so many top professionals in the audiences of the same talks providing feedback and suggestions at the discussions. To have the ability to get so much information on topics you are interested in from so many top people in the industry from a number of major players is just an experience you can’t get in any other way.

March 9, 2008 Posted by Brian | Uncategorized | | No Comments Yet

Dances With Robots

Mark and I had the chance today to attend a keynote presentation by James McLurkin who is a robotics student at MIT who specializes in swarm behaviour of small simple robots working in groups to complete a task. His presentation was excellent and the demonstration of his robots was a lot of fun to watch.

Dances with Robots

March 8, 2008 Posted by Brian | Uncategorized | | No Comments Yet

IHOP

Mark and I had our last breakfast at IHOP. We are going to miss that place.

IHOP

March 8, 2008 Posted by Brian | Uncategorized | | No Comments Yet

GUI Bloopers

Since I am by no means a UI expert, I am just passing on all the points mentioned in this talk I attended at SD WEST. I enjoyed it a lot.

Grayed out input fields
Don’t used input fields that are grayed out as a way of displaying text. Always use a control that is never editable such as a label.

Negative Checkboxes
Never use a checkbox being checked as a way to say “Do not do the following”. You need to be consistent. Checking means do something, unchecking means do not.

Dynamic Menus
Do not have menus where the content of the drop menu changes based on the current task the user is doing. If you want to make certain items inaccessible at certain times, gray them out so the user knows they are still there, just not accessible at this time or in this context. The reason this is a problem is because users tend to remember where something is, but not always what it is called. Users often scan menus and want to go back to where they remember seeing that feature before. So do not automatically add and remove. Dynamic menus undermines a basic learning strategy.

Popup Not Identifying Itself
The function of the popup is not explained, user may loose what functionality the popup relates to.

Pages Not Identifying Themselves
Simple examples are the menu not highlighting the menu tab that shows the page you are currently viewing, or the page title is not present or clear.

Distracting Off-Path Links and Buttons
Don’t distract the user from their current task by sending them off in another direction mid stream. Use the pattern “Process Funnel”. This means that when a user tells you what they want to do, what their goal is, put them in a funnel with minimal distraction until they have accomplished their goal.

Too Many Levels of Dialogs and Menus
Look for areas in your interface with too much depth and see how it can be flattened. One approach is to optimize for the most commonly used paths.

Inconsistent Text
Same functionality called different things in different areas. This makes it very difficult for a user to learn an application.

Rule:
Same Word, Same Thing
Different Word, Different Thing

Misleading Text (e.g., Erroneous Messages)
A common example is a misleading error message, such as an error message on the page telling the user the “Username entered is invalid” when it is actually the login server that is down and not responding. The problem here is the user will keep retrying because they have not been given a clear message

Easily Missed Information
For example an error message which is placed on the page far away from where the user has entered the data that has caused the error and is currently focusing. Often users will not associate the two.

Burying Relevant Information
Making it difficult for the user to understand what the info is they need to complete their task amongst all of the information being shown. Also avoid too much repetition in naming options such as options that all start with the same name:

How to …
How to ….
How to ….

Color Differences that are Too Subtle
Graphic designers often create this issue by using color pattern with too subtle of differences. This is always bad. Also if a color difference is the only way to tell something apart, that’s also bad. You must also take into consideration people who have color blindness or even bad monitors. One good test is to print UIs in black and white. Use of color should only be used as a redundant emphasis along with another visual hint.

Instructions Disappear Too Soon
Giving instructions in a dialog that then must be followed after the dialog has been closed should always be avoided.

Dialog Boxes that Trap Users
For example an “OK” button that informs you of a problem yet does not allow you to take a step back. It warns you that something you probably don’t want to happen is about to happen, but does not give you an option to not do it, just tells you it is about to happen and waits for you to say “Sure, alright, I guess I have no choice”. The second way to trap a user in a dialog is by having a message on the dialog that does not at all make it clear which options on the dialog mean what. No clear relationship between the text and the options.

So what to do?

Avoid anarchic development.

  • No Design
  • No UI Standards
  • No oversite

User centered design and Agile are definitely compatible.

March 7, 2008 Posted by Brian | Uncategorized | | No Comments Yet

Agile and Object Oriented Principles

In order for a team to really adopt Agile, the project must be structured in a way to allow for small, thin vertical strips of the application to be released independently of any other feature in the application. If we have a story for feature A, then we should be able to implement the story for feature A, test feature A, and release feature A without affecting feature B. If this is not possible in your current project, then you must work to moving in this direction. This division is extremely important at working towards an Agile system that has few bugs and is quick to QA.

For example: I make a change to feature A, well it is not just feature A that needs to have QA look at it, it is now also feature B that needs a complete regression test. But wait, what if QA is unaware that feature B is dependent on code that was changed in feature A, then that testing may get missed. Now, also because we can’t release feature A independently of feature B we now have to release both together. Now, we have created production bugs which are costly to fix in feature B and now we have maintenance tasks which will now take up time in the next sprint, that could have instead been spent on other new development work to add more business value to the product. Also those bugs in feature B will now require testing time in the next sprint and possibly regression testing of feature A or possible breaking feature C, etc. So, as was stressed in the talk, you should always be working towards small applications that can be independently released, if not, you my be stuck in this loop.

March 7, 2008 Posted by Brian | Uncategorized | | No Comments Yet

Developer Bowl!

Mark and I attended the annual SD WEST Developer Bowl. The Developer Bowl is a trivia contest between some of the top brains at some of the biggest technology companies. This year there were teams from Google, Intel, IBM, and CodeGear competing. The questions were ridiculously tough. The winning team was from IBM.

Developer Bowl!

March 7, 2008 Posted by Brian | Uncategorized | | 2 Comments

Testing Legacy Code

So the morning lecture I attended was more a general overview of project with legacy code switching to Agile, while the afternoon talk I attended was a tutorial on writing unit tests for existing production legacy code. This talk was excellent. It was by one of the “Beautiful Code” authors. He has a very practical approach to dealing with adding tests to existing legacy code.

The benefits of TDD are clear and 100% code coverage is always the goal. However, with existing legacy code you need to take a much different approach. When optimizing, or refactoring existing legacy code you can apply TDD and it works very well, however you must give up a few things:

  1. 100% Code Coverage
  2. Unit Tests

Broad Tests

Since you are writing tests for a system that has already been running on production for quite some time, you can assume for the most part it is offering what the user’s want, or there would have already been complaints and issues logged (there will be bugs, but overall it is functioning). So don’t focus on 100% code coverage or unit tests, instead focus on writing broad tests that confirm some functionality that the user relies on is working correctly.

Yes, when you make changes and a broad test does fail, it will not immediately show you the cause of the failure, like a typical unit test will. However, it will still show you that you have broken existing functionality and this is a big improvement over having no tests at all. In a small amount of tests we have been able to at the very least protect some existing functionality. The key is that since we usually have a very limited amount of time to devote to writing tests for legacy code, that it is more important to get broad coverage than targeted coverage.

Just like when using TDD with new functionality, when making any change at all in legacy code, ensure the tests are written BEFORE changing anything, but still in this case broad tests are the place to start. This is not advocating ignoring full coverage for your new code, only the legacy code. If you have time to write full unit tests for existing legacy code, great, but most developers do not. The key is to make sure your broad tests are in place FIRST.

When dealing with legacy code, the fastest gains in code coverage and also the biggest gains in reducing bugs come from starting your tests at the highest level possible. In writing these tests you do not think about the structure of the code, but rather just “What does this application do” and write tests to confirm that functionality and protect it.

Add a New Test and It Fails

Now in TDD when writing new code, the moment a test fails you fix the code until your test passes. However, when writing tests for existing legacy code, if you add a new test to an area that is not currently covered by tests and it fails, but you are confident the test should work, do not stop and fix the code to get the test to pass, this is a common mistake. You are far better off to log an issue for the bug and to continue to write more tests. The reason is because at this stage you do not have enough tests in place to ensure your bug fix will not break another area of the application. So write more tests, leave this test failing, and log an issue for fixing this bug.

Basic Method to Testing Legacy Code

So to get started with writing unit tests for legacy code you:

  1. Look at the existing application
  2. See what functionality it offers to the user
  3. Write tests to cover that high level functionality

Top Down Approach

So for writing unit tests for legacy code, you want to go in the order of what will give you the most gain for the least amount of effort, so go in the following order:

  • Tests for each Package
  • Tests for each Class
  • Tests for each Method (with legacy code, will probably never get this far)
  • Tests for each Line (100% code coverage)

Once again the Michael Feathers book “Working with Legacy Code” was highly recommended. I am amazed how highly regarded this book is as a reference for refactoring and getting code into a testable state.

March 7, 2008 Posted by Brian | Uncategorized | | No Comments Yet

How to be Agile with Fragile Legacy Code

I attended a talk today that had a different perspective on transitioning to Agile. Most discussions on Agile focus on teams in the initial stages of a project, not after several years of code has been written. In the short term the costs of adding legacy code appear cheap, but in the long term become increasingly expensive in terms of maintenance and QA costs. The basic approaches to reducing this cost later on, by investing in your code now is to reduce complexity, increase test coverage, introduce best practices (coding standards for both code and unit tests), and as a result reduce the number of issues that make it to the QA cycle and production.

Unit Testing (Adding tests to legacy code)

So where do you begin? Start by adding tests to cover existing functionality in your product. The product is stable and in production, so start covering it with tests. There are two types of tests

  1. High Level – these are the tests that ensure the system does what it is supposed to, protects the business logic. These tests allow us to confirm that the functionality the user expects from the system has not been broken by any additional changes. These tests cover the bugs that will be the most likely to occur
  2. Low Level – these are the tests that cover individual pieces of logic, the small units that make up the high level tests

You should start with high level tests, these are the tests that offer the most business value. It is important to capture the overall functionality of the system with tests first when dealing with legacy code, since these are the tests that will provide the least hindrances to future refactoring.

Teams need training on Unit Testing and often they demand it (especially when it comes to refactoring existing legacy code to get it into a testable state). Document it on the wiki and update it regularly!!!!! Providing this training early on prevents a mess that needs to be cleaned up later.

Switching to Agile

Switching an existing team with a legacy application over to Agile requires a different approach then starting Agile with a new team working on a new application. It is a mistake to take the “All or nothing” approach to SCRUM, the “We must do it all now”. Agile in this type of environment should be introduced in a slow incremental approach where each new process is brought in one at a time, refined in the retrospective, then as that process stabilizes another is introduced. So the cycle is “Start small, test, refine, add more”. This approach may feel like a slower change, but often can make the transition significantly easier. Switching a teams entire process all at once, can lead to frustration amongst the team and loosely followed processes.

Problems with Large Projects (Code size)

Often developers will change their development process just based on the size of the existing application. For example, you have a very large project, it is very slow in your IDE tool, you want to use a refactoring tool, but are unable to because of the size of your project and how slow the tool runs on the project. So what happens? The team does not use a refactoring tool. This is a mistake that misses focusing on the core issue: The project is too big, it needs to be broken up. It is also a hindrance to TDD. Quick feedback is extremely important for TDD, long build times and slow running unit tests end up hurting this process. Developers do not want to wait for the tests to finish, so will write more and test later.

Regular Software Cleanup

Make time in each sprint to not just write unit tests, but to also remove dead code and duplicate code as part of the step of adding those unit tests.

Testing and QA

Allow automation to happen over time, DO NOT force it. Establish the right processes first, everytime those processes get ironed out, QA will see common areas that can be easily automated, then you can move in that direction.

Piggy Backing

One approach discussed to introducing Agile methodologies into an existing team was called “Piggy Backing”. Do not introduce a new process all at once, just introduce new items to the existing process slowly overtime, piggy backing on what the team is already doing. The team will evolve to where you want them to be and often get their quicker, with far less pain and less resistance from the team

March 6, 2008 Posted by Brian | Uncategorized | | No Comments Yet

SD EXPO – Thursday Morning

This might well by my most difficult day in terms of deciding what lectures to attend. There are more lectures in each time slot that I want to attend, then any other day of the week. I have three lectures for each session marked off, and their are four time sessions today. This will not be easy ….

March 6, 2008 Posted by Brian | Uncategorized | | No Comments Yet

Sharks 3 – Senators 2

My first time attending an NHL game. Hockey fans down here a quite reservered. It was a good game, it was tied 2-2 and the Sharks got a goal three minutes into overtime.

HPPavillion

March 6, 2008 Posted by Brian | Uncategorized | | No Comments Yet