Tuesday, May 27, 2008

Writing for the computer screen

Notes from article in Digital Matrix 131

Gotchas:
  1. Less reading time
  2. On-screen text is tougher for the reader - to read
  3. The computer or reader can alter the format
  4. On-screen text competes with other distractions
  5. The screen can hide errors - things can look finished, even when they aren't

Tips:
Structure
  • Use the inverted pyramid style of writing
  • Provide an overview and signposts
  • Use hyperlinks effectively
Style
  • Use smaller chunks of text
  • Write succinctly
  • Use bullet points and lists
Format
  • Leave plenty of white space
  • Avoid using italics
  • Choose your font carefully
  • Use a sufficiently large font
  • Use simple colour contrasts

Friday, May 23, 2008

Everyone should have business cards

Companies should provide business cards for all members of staff.
OK, so maybe not everyone, but almost all office based staff and plenty of others as well.

If you don't have them and you meet a customer and can't offer them your card, what does that say to the customer?
Does it say you are not very important in/to the company?
Does it say that customers shouldn't be able to contact you? Why would that be?

If you can't give something to a potential customer, how will they remember you?

It's not just in a sales environment that you may meet with people who you may benefit from being able to give a card too. You could meet them anywhere: pub, shops, gym, convention, playground, church, etc...

If everyone has them, there is no segregation of staff - No feelings of being 'important enough' to have them.

having a business card says you're important enough to a company, to spend a small amount of money on you, for you to be able to identify yourself as being part of that company.

They're so cheap it should be no decision at all anyway. You'll probably spend longer thinking about who should have them than the cost they are to manufacture any way.

Thursday, May 22, 2008

How to make Windows better

If another program/window couldn't take focus from the one you are working in, while you are typing.

At some (highly superficial) level, I guess all that it would take would be some kind of time out from when you last presses a key. Say a second or so. This way you wouldn't have focus stolen part way through typing a sentence, or as more often happens with me, a password.

Ironically, it happened to me twice during that last sentence.

At the moment it seems like Windows (just happened again) has no respect for what I'm doing.

(Happened again) Maybe it's me, and I try and do to many things at once. Like start lots of apps and begin using the one that loads first. This kind of thing would sure help me though.

Maybe I just need a faster computer, which can load apps quicker.

Wednesday, May 21, 2008

Designing the obvious

From SitePoint Design View #45

Robert had some wonderful insights and, perhaps most importantly, some excellent principles you can apply to your work every day. The three principles that resonated with me were:

  • Understand users — but ignore them. More precisely, watch and learn for what users do, but don't take what they say as gospel. Users often don't know (or can't explain) what they want or why they want it, so asking them directly isn't useful.
  • Build only what's absolutely necessary. Simple things are the most functionally flexible — whether it's the Google search box or a paper clip.
  • Turn beginners in intermediates immediately. In other words, find a way to give your newest, most anxious users some really easy wins and some warm feelings right from the start.

But there was one of Robert's principles that caused me to raise an eyebrow:

  • Design to support activity, not user groups.

In other words, in Robert's view, you should focus on designing for the activities that link all your users — whether that be reading sports content, managing calendar events or organizing photos.

He believes that if you start crafting your sites in response to specific user groups, you will end up designing overly complex, multi-personality applications that don't really work properly for anyone.

Sunday, May 18, 2008

EDSK ... that they must be involved in implementation

"The designer of a new kind of system must participate fully in the implementation."
"… the designer of a new system must not only be the implementor and the first large-scale user; the designer should also write the first user manual. … If I had not participated fully in all these activities, literally hundreds of improvements would never have been made, because I would never have thought of them or perceived why they were important."

Friday, May 16, 2008

Pre-testing checklist

Testing steps to perform before passing code to 'official' testing.
The intention is to prevent avoidable testing failures. It's frustrating when code fails testing and just makes more work for myself in the long run.

  • Does it do what it's supposed to - basic functionality check against spec.
  • Check code against standards.
  • Check missing, min and max length values.
  • Check for memory and resource leaks.
  • Create unit/automated test cases for all scenarios
  • Check execution against large and small data volumes
  • Check repeated execution in quick succession
  • Check for multi instance issues
  • Check in multiple target environments (DB, OS, etc.)
  • Write test plan

Obviously, some of the above can be performed by tools.


My own personal check-list. subject to change and recorded for reference. Feel free to make additional suggestions.

UI notes

Notes from listening to .NET Rocks! #338 - Mark Miller on the Science of Good UI

UI Metrics
  • No. of click or button presses required
  • Amount of brain power required

Goals of UI design should be efficiency & discover-ability - These can be mutually exclusive

Information can be in serial and parallel - adv & dis of both, based on context

Noise!

contrast should match relevance

use shadonws when stacking items

Setting up a PC - for me

After coming close to having to format a machine today, I thought I should make a list of what I'd want to reinstall in that situation.

General Stuff
  • Activewords
  • Enso launcher
  • Rescue Time
  • TimeSnapper
  • GoogleDesktop
  • UnixUtils
  • Copy as Link
  • Notepad2
  • MS Office
  • Skype
  • filezilla
  • FireFox
  • IE Search Addin
  • IE spell checker addin
  • IE delicious toolbar

Developer Stuff

  • Version control client
  • IDEs
  • SDKs
  • emulator images
  • frameworks (testing, etc.)
  • xml notepad
  • Orca
  • SoapUI
  • FxCop
  • MSIDiff
  • SqlPrompt

Web Dev Stuff
  • Opera
  • Safari
  • Xenu link sleuth

And probably lots more, I've forgotten

broken hal.dll with XPSP3 - will not boot

After spending about 7 hours getting my work machine to boot, I thought I'd make a few notes, in case it help anyone else.

Background:
- Installed SP3 on Tuesday - no problems.
- An auto update installed last night (Thursday)
- This morning, wouldn't boot:
Windows could not start because the following file is missing or corrupt:
\system32\hal.dll.
Please re-install a copy of the above file.
Managed to get everything back by following the excellent instructions at:
http://forums.legitreviews.com/about6705.html

Really needed the restore disk and the dell resource CD. (Note to self, must check where the one for my laptop is.)

Ended up with a machine which has everything SP3, apart from hal.dll, which is SP2 version. But, everything seems to be ok.

Also had to reinstall IE7 as was on originally, but reinstall of OS rolled back to IE6. This was clever as SP3 is supposed to stop moving back to IE6.

This in turn has fixed a broken IE7, which couldn't save settings, after upgrading to IE8 beta and then downgrading.

Had issues reconnecting to domain, but solved these by disconnecting from and reconnecting to the domain.

Leaving my machine dual boot though. just in case.

Wednesday, May 14, 2008

Reading & Writing other application config files

I recently had to write a configuration tool to manage the configuration settings of a bunch of other programs. 
Here's a little snippet, which also shows using XPath to read XML.




using System.Xml.XPath;


private string ReadOtherAppConfigSetting(string fileName, string setting)
{
string result = "";

try
{
XmlDocument exeConfig = new XmlDocument();
exeConfig.Load(fileName);
XPathNavigator xNav = exeConfig.CreateNavigator();
XPathExpression dsExpr = xNav.Compile("//configuration/appsettings/add[@key='"+setting+"']");
XPathNodeIterator iterator = xNav.Select(dsExpr);

if (iterator.Count == 1)
{
if (iterator.CurrentPosition == 0)
{
iterator.MoveNext();
}

result = iterator.Current.GetAttribute("value", "");
}
}
catch {} //Don't care if can't find or doesn't exist as can default to empty string

return result;
}

private bool WriteOtherAppConfigSetting(string fileName, string setting, string newValue)
{
bool result = false;

XmlDocument exeConfig = new XmlDocument();
XmlNode oldNode = null;

if (File.Exists(fileName))
{
exeConfig.Load(fileName);

try
{
oldNode = exeConfig.DocumentElement.SelectSingleNode("//configuration/appsettings/add[@key='"+setting+"']");
}
catch {} //old child or file may not exist

//Delete existing entry (if exists)
if (oldNode != null)
{
exeConfig.LastChild.FirstChild.RemoveChild(oldNode);
}
}
else
{
//If file doesn't exist, create a basic structure
exeConfig.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><configuration><appsettings></appsettings></configuration>");
}

try
{
//add the new setting
XmlElement newNode = exeConfig.CreateElement("add");
newNode.SetAttribute("key", setting);
newNode.SetAttribute("value", newValue);

exeConfig.LastChild.FirstChild. AppendChild(newNode);
exeConfig.Save(fileName);
result = true;
}
catch
{
throw new IOException("Unable to save configuration settings. Manually edit config file or delete it and then try resaving settings.");
}

return result;
}

Tuesday, May 13, 2008

Wednesday, May 07, 2008

Creating links between databases on different machines

Last year I worked on an interface between two systems to synchronize the data. It was specked out so that it was restricted to work with databases on the same machine or on different machines within a LAN, by specifying the machine name.

As it's been sold to a customer trying to connect two machines over the Internet by specifying an IP address. I've got to do a quick change to enable this.

Here's a quick list of situations to test in such a situation:
  • server specified by machine name
  • server specified by IP address
  • databases on the same machine
  • databases on different machines in the same domain in the same LAN
  • databases on different machines in the same domain in the same WAN
  • databases on different machines in different domains, but in the same LAN
  • databases on different machines, connected over a VPN
  • database on different machines, connected over the Internet
  • connections using network/user authentication
  • connections using specified a user name and password

Why does this matter?
Because connection strings may need to be different.

Friday, May 02, 2008

Checking for default constraints on SQL Server 2000 AND 2005 - CORRECTION!

Unfortunately there isn't a simple way to check for default constraints on a column which works on both SQL Server 2000 and 2005. To get around this problem, I created the following function:

CREATE FUNCTION DefaultConstraintExists(@SchemaAndTableName sysname, @Column sysname)
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
DECLARE @columnId INT
--Try and get the columnID - only works on SQL Server 2000
SELECT @columnId = [info] FROM sysobjects
WHERE [xtype] = 'D'
AND [parent_obj] = OBJECT_ID(@SchemaAndTableName)
AND COL_NAME([parent_obj], [info]) = @Column
--If that failed, try and get it in a way that works on SQL Server 2005 (There is no way that works on both)
IF @columnId IS NULL
BEGIN
SELECT @columnId = COLUMNPROPERTY(OBJECT_ID(@SchemaAndTableName), @Column, 'ColumnId')
END
--Now see if the default constraint exists
IF EXISTS (Select * From sysobjects where xtype = 'D' and parent_obj = object_id(@SchemaAndTableName)
and col_name(parent_obj, @columnId) = @Column)
BEGIN
SET @Result = 'T'
END
ELSE
BEGIN
SET @Result = 'F'
END
RETURN @Result;
END
go


The above doesn't work properly on SQL Server 2005, it returns true if there are any constraints on the table, not just the desired field.
The following is simpler AND IT WORKS!


CREATE FUNCTION FDS.DefaultExists(@Schema varchar(10), @TableName varchar(100), @Column varchar(100))
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
DECLARE @default varchar(255)

SELECT @default = COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @Schema
AND TABLE_NAME = @TableName
AND COLUMN_NAME = @Column

IF @default IS NULL
BEGIN
SET @Result = 'F'
END
ELSE
BEGIN
SET @Result = 'T'
END
RETURN @Result;
END
go

Thursday, May 01, 2008