Monday, March 31, 2008

Windows Mobile still a second class citizen in Microsoft's eyes?

I really enjoyed the Heroes Happen Here launch in Birmingham last month. Especially the sessions by Andy Wigley and Daniel Moth.

It's great to see Microsoft including Mobile development along with development for the desktop and the web. (Especially as they are dropping MEDC for the same reasons.) It just seems a bit off that they hold an event to promote it, but then only provide copies of the tools to develop for the desktop and web. (Copies of VS2008 standard were given to attendies, but only VS2008 Professional has the facility to develop for Mobile devices.)

I can see Microsofts argument for not including Mobile support in the standard edition. Not everyone wants it. It's probably not a good idea for any Tom, Dick or Harry to be able to create Mobile apps, as tey probably wouldn't be able to install them. (Most WM devices requiring M2M certificates for installation.) But it feels like Microsoft were saying: You're professionals so you should know about developing for Windows Mobile. But we're not going to give you the tools to do it.

I guess I'm probably just a bit miffed as I was hoping to be able to use VS2008 to develop mobile apps using CF v3.5. Unfortunately I can't afford to buy my own copy of VS2008 Professional 0r an MSDN subscription.

Thursday, March 27, 2008

Trigger without a cursor example

From an example I wrote for someone at work.

ORIGINAL
CREATE TRIGGER S0787_RegionCodes_Insert ON RegionCodes
FOR INSERT
AS
DECLARE @rgnCode varChar(5)
DECLARE InsertedCursor CURSOR FOR
select rgnCode from Inserted
OPEN InsertedCursor
FETCH NEXT FROM InsertedCursor INTO @rgnCode
WHILE @@FETCH_STATUS=0
begin
SET NOCOUNT ON;
Insert InTo S0787_POExportConfig (rgnCode) values (@rgnCode);
Insert InTo S0787_POExportBatchGen (rgnCode) values (@rgnCode);
SET NOCOUNT OFF;
end
FETCH NEXT FROM InsertedCursor INTO @rgnCode
CLOSE InsertedCursor
DEALLOCATE InsertedCursor
GO

This can be rewritten in the following way

NEW
CREATE TRIGGER S0787_RegionCodes_Insert ON RegionCodes
FOR INSERT
AS
SET NOCOUNT ON;
INSERT INTO S0787_POExportConfig (rgnCode)
SELECT rgnCode FROM Inserted
WHERE rgnCode <> ''

INSERT INTO S0787_POExportBatchGen (rgnCode)
SELECT rgnCode FROM Inserted
WHERE rgnCode <> ''
GO

On a single row insertion, the original trigger (according to Profiler) made 285 reads and had a duration of 156. The new trigger made 10 reads and had a duration of 16.

This is orders of magnitude faster.

Don't use cursors, when you don't have to!

Tuesday, March 25, 2008

Manual or unit testing for legacy code

It is often necessary to make changes to a legacy code base. It is also often the situation that no unit tests will exists for this code base.
Unit testing should be part of all code that is written. So, it is, of course, desirable to add unit testing around any code you add or change to the legacy code base. (Working on the assumption that it is not a practical use of time to add unit testing to all existing code.)

Unfortunately existing code is sometimes written in a way that makes unit testing very difficult. (Usually because of a poor object design and a very high number of dependencies.) This means it may be a better use of time to create a test script which can be manually followed, rather than a series of tests which can be automatically run.

But, how do you know when to create an automated test? and when to create a manual script?

Simple. Always create an automated test. Unless creating the automated test will take ten times longer than writing and executing the manual script.

Why ten times?
Because the test will need to be run:
  • Once before any changes are made, to capture current behaviour.
  • At least once while making the change. (probably a lot more!)
  • At least twice during the testing/QA phase.
  • Every time a version of any program using the code is released.
  • Every time any code that the changed code is dependent on is changed.

This will add up to at least ten times very quickly.

Bug management system requirements

A bug/defect/issue tracking system should:
  • Allow you to spend time fixing bugs, not tracking them.
  • Allow you to see the serious of bugs.
  • Allow you to see the reach/scope/extent of the bug.
  • Have the minimum number of compulsory fields (3? 0?) when recording a bug.
  • Only be used by the people whi will benefit from it's use.
  • Be appropriate to the size of project it is being used for.
  • Integrate with the version tracking system being used.
  • Provide useful statistics and reporting.
  • Be fast.
  • Be easy to use.

Software documentation

There are two types of documentation which should be created for software. Those that are used internally within the company, and those that are used externally, by the customer.

Some examples:


Internal

Explanations of software.
  • What it is for
  • Who the intended users are
  • How it works
  • How it is developed
Sales tools


External

User guides

  • System requirements
  • Basic (user guide)
  • Advanced (user guide)
  • Installation
  • Upgrading
  • Troubleshooting
  • Moving an installation between machines

Project management - a beautiful thing!

  • A user will tell you anything you ask, but nothing more. (And often only what they think you want to hear.)
  • What you don't know hurts you.
  • There's never enough time to do it right first time but there's always enough time to go back and do it again.
  • I know you believe you understand what you think I said, but I am not sure you realise that what you heard is not what I meant.
  • What is not on paper has not been said.
  • The more you plan, the luckier you get.
  • A project is one small step for the project sponsor, one giant leap for the project manager.
  • The sooner you begin coding, the later you'll finish.
  • A badly planned project will take three times longer than expected - a well planned project only twice as long as expected.
  • Warning: dates in a calendar are closer than they appear to be.
  • There is no such thing as scope creep, only scope gallop.
  • Activity is not achievement.

Thursday, March 20, 2008

Heroes Happen Here - notes

Quite light on note taking, but...

Regarding compatibility:
  • me.exe for extracting and embedding manifests from/in assemblies
  • IIS7 doesn't have a metabase, so installers which try and use it will fail.
  • The local admin account on Windows Server 2008 has UAC disabled.
  • Don't create programs to manipulate configuration files, create MMC Snap-ins.

Regarding Smart Client development:
  • When adding new functionality (such as WPF elements) interop with existing code, don't rewrite.
  • Build an ecosystem through extensibility (X-ref this post from coding horror.)
  • Embrace the Software plus Services model for occasionally connected apps.
  • Integrate with Office, where possible, rather than make a completely new app.

Wednesday, March 19, 2008

Friday, March 14, 2008

Web developer Vs ASP.Net developer

From Build Your Own ASP.NET 2.0 Web Site Using C# & VB, 2nd Edition
"Web server controls can be seen as more advanced versions of HTML server controls. Web server controls are those that generate content for you—you’re no longer in control of the HTML being used. While having good knowledge of HTML is useful, it’s not a necessity for those working with web server controls."
Hooray, so you don't have to understand what's going on in the actual HTML and HTTP.
I'm certain this leads to more people who know ASP.NET, but can't fix general problems.
"This doesn't display on this browser." or "Such and such data doesn't display right in these conditions." or "Not all the page gets displayed when I click on[X] on a specific version of a browser." How would someone who only knows ASP.NET and not how HTTP and HTML work have a clue at trying to solve these problems. Aah, yes they simply say that that browser is not supported, or it's a problem of the browser, network, PC, anything other than their code. The developer's problem goes away.
Customer/user/person has poor customer service.
Customer/user/person gets upset.
Customer goes away.
Huzzah, problem never gets reported again.
But that's not the end of it because the business loses a customer
Customer starts a negative feedback loop
...

SubVersion Vs Vault

What i miss about subversion (& tortoiseSVN) now that I have to use Vault:
  • Can't do a get latest of everything I haven't changed, out of the box, in one easy step
  • Can't easily see anything that has changed
  • Vault tries, by default, to make everything I haven't checked out read only
  • I have to check things out
  • It's really slow to load (vault client) as opposed to always being there in explorer
  • Client navigation more awkward - than using Explorer
  • Easier to compare to older versions
  • Spell checker when entering comments when checking in
  • Everything was quicker and easier!

Getting Users to Fall in Love with Your Software

Getting Users to Fall in Love with Your Software


  • When developing an application you loose one point for every dialog you add.
    • Users don't read them unless they are expecting them
    • It just anoys them that they have to clear them.
  • Most people look at software development as making trade offs in four areas:
    • Experience vs. Tool
      • A coffee pot is a tool, it gets the job done
      • Starbucks is an experience, the point is more then just the outcome
    • Powerful vs. Simple
      • The more features you add, the more powerful it is
      • Presents the user with fewer choices so it “just works” – more Wizards
    • Automatic vs. Manual
      • Provides automatic solutions without requiring the user to tell it to
      • The user has the option to tweak the settings and make changes through-out the process.
    • Familiar vs. Special
      • Common look and feel using the usual keystrokes, etc.
      • Stands out from other applications and has specialized behavior.

  • Real good software is “both” not a trade off.
    • Tool and Experience
      • Provide the solution quickly and easily, but keep the “ambience”
    • Powerful and Simple
      • Many features, but keep them contextual and focus on the most common features.
      • Don’t punish the “power users” by making the special features hard to find, but at the same time don’t punish the starter users by obsuring the common features with ones they don’t need.
    • Automatic and Manual
      • Offer the most common or most frequent solution by default, and then allow the user to tweak it and make changes. Don’t hide the ability to tweak, but don’t require advanced knowledge to get things done.
    • Familiar and Special
      • Build on the common and familiar. Improve and innovate.

"I don't want to use threads"

"I don't want to use threads"

People seem to say this because either:

  • they don't understand (how to use) them; or
  • they think it will make the code more complicated for them to write.

In reality it will probably end up being simpler (in the long run) to use threads.

Plus doing what's easiest for the developer is normally the wrong approach. They should, instead, focus on what's best for the user.

Programmer Personality - Not an oxymoron

Programmer Personality Test

I'm a PHSB - I think the S comes from working by myself so much over the last few years. My first paid programming role was almost entirely pair programming and I enjoyed that more.

Think I'm tending to more of a C, recently though.

Programmer Personality Test Key

Educating customers

If your customer isn't aware that they have already purchased something from you but have never used it, don't spend time laughing amongst yourselves about them, spend time on how you can make sure that your customers have got what they need and aware how to use it to benefit themselves.
This will make customers happier.

Hiding disabled application functionality


procedure TXXXXXXXXXForm.btnHelpClick(Sender: TObject);
begin
//This button has been made invisible as there is no help yet available for this form
// when help is written/available make the button visible again.

//It is better to hide a feature that doesn't yet exists than post a message
// saying that it doesn't yet exist when the user tries to use it.
end;

Google me

Enso Launcher: some thoughts and comments

I think Enso is brilliant. I think you should get it. It's even now FREE, so you have no excuses.

Unfortunately, I've encountered quite a few errors while using it and my emails to the support address keep bouncing, so I'll share my comments here.

For all it's good points there are a few quirks that I've noticed:

Tab completion:
As a productivity tool, it is great to see that it employs tab completion, to save typing. However, it doesn't work like I expect or want it to.
Let's say I want to open 'SQL Server Management Studio'.
Hold down [Caps Lock], type [O], [Tab], [S], [Q].

I'd expect pressing [Tab] again to complete the word 'SQL'. Like this:
But, it doesn't. It completes the entire selected option.
This behaviour means that (by my reckoning) I end up having to type more that necessary (in some instances) to launch programs.
A word highlighting bug
Because of the above behaviour, I've learnt that the quickest way to launch 'SQL Server Management Studio' is to hold down [Caps Lock], and type [O], [Tab], [S], [E], [R], [V], [E], [R], [space], [M].
Look what happens to the highlighting when I do.
It seems that there is a bug in the word highlighting when you type a word other that the first which starts with some of the same letters as the first (or an earlier) word.


When an exception is encountered it does a good job of capturing information about the problem, so hopefully they can fix it.
It seems strange though (according to the text of the message below) that the script behind the error submission page can't tell if I've filled in an email address though. ('IF' you left your email address!?)

Fewer blog subscriptions

I use Google Reader as my blog aggregator (shared items here)

I'd slipped into a situation where I had a massive number of feeds so that it was becoming a chore to keep up to date.

So I've had a big clear out.

Here's my old OPML, if you're interested.

I've unsubscribed from about half of them now.
Since the purge I've only resubscribed to one of those (Crunchgear)

Tuesday, March 11, 2008

installscript configure website to use specific version of ASP.NET

After managing to register ASP.NET 1.1 the next step was to tell the newly installed website to use version 1.1 of ASP.NET, rather than the default.

This was done with the following function.

function ConfigureAspDotNetOnePointOne(hMSI)
STRING svRootVer, svMajMin, szApplicationPath, szVirtDir, szK, szS;
NUMBER nvType, nvSize, nIsFlag;
begin
//Check the registry to see how/if ASP.NET 1.1 is configured with IIS
//We'll be looking in the HKLM hive
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);

//initialise to be sure of what started with
svRootVer = "";

//Try and read a value from the registry, which will exist if it is installed and registered
RegDBGetKeyValueEx("SOFTWARE\\Microsoft\\ASP.NET", "RootVer", nvType, svRootVer, nvSize);

StrSub(svMajMin, svRootVer, 0, 4);

//If path key does not exists, ASP.NET 1.1 is not registered with IIS
if (svMajMin != "1.1.") then
//Check it exists
nIsFlag = FILE_EXISTS;
szApplicationPath = WINDIR ^ "\\microsoft.net\\framework\\v1.1.4322\\aspnet_regiis.exe";
//Ensure that the path or filename is correctly enclosed in quotation marks,
LongPathToQuote(szApplicationPath, FALSE);
//Check if the exe file exists
if (Is (nIsFlag, szApplicationPath) == TRUE) then
//Get the name of the virtual dir
nvSize = 256;
MsiGetProperty(hMSI, "IIS_VIRTUAL_DIR", szVirtDir, nvSize);
//build command line arguments
szK = ' -k "W3SVC/1/Root/' + szVirtDir + '"'; //must quote as may contain spaces
szS = ' -s "W3SVC/1/Root/' + szVirtDir + '"';

//Register with IIS without script paths
LaunchAppAndWait(szApplicationPath, " -ir", WAIT);
//Remove any script path associations defaulted to new web application
LaunchAppAndWait(szApplicationPath, szK, WAIT);
//Associate new web application with desired ASP.NET version (1.1)
LaunchAppAndWait(szApplicationPath, szS , WAIT);
endif;
endif;

end;


I run this as a custom action in the Install Exec Sequence, after ScheduleReboot and with the condition 'Not Installed',

Wednesday, March 05, 2008

installscript register ASP.NET 1.1 (if not registered)

For some reason, one of our ASP.NET 1.1 based products is often installed on machines where ASP.NET 1.1 is installed on the machine, but not registered with IIS. (They typically have 2.0 installed and registered though.)

To get around this issue, I have created the following InstallScript function.

function RegisterAspDotNet(hMSI)
STRING svPatAddFolderIconszApplicationPath;
NUMBER nvType, nvSize, nIsFlag;
begin
//Check the registry to see if ASP.NET 1.1 is installed
//We'll be looking in the HKLM hive
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);

//initialise to be sure of what started with
svPath = "";

//Try and read a value from the registry, which will exist if it is installed and registered
RegDBGetKeyValueEx("SOFTWARE\\Microsoft\\ASP.NET\\1.1.4322.0", "Path", nvType, svPath, nvSize);

//If path key does not exists, ASP.NET 1.1 is not registered with IIS
if (svPath == "") then
//Check it exists
nIsFlag = FILE_EXISTS;
szApplicationPath = WINDIR ^ "\\microsoft.net\\framework\\v1.1.4322\\aspnet_regiis.exe";
//To ensure that the path or filename is correctly enclosed in quotation marks,
LongPathToQuote(szApplicationPath,FALSE);
//Check if the exe file exists
if (Is (nIsFlag, szApplicationPath) == TRUE) then
//Register with IIS
LaunchAppAndWait(szApplicationPath, " -i", WAIT);
endif;
endif;

end;

I run this as a custom action in the Install UI Sequence after LaunchConditions. (If you're not doing a UI install, you really should check the software requirements first!)

Tuesday, March 04, 2008

Attention to detail: Strange times and pausing.

If the quality of the simple things which are seen is poor, why should I trust the quality of the more complex things which aren't seen.

Up late in the kitchen one night, I noticed the clock on the oven change through the following times:

23:58
23:59
24:00
00:01
00:02

Hmmm. The hour changing 3 times in 3 minutes? I've never seen that on any other clock. While technically you could argue that it's correct, but it just seems wrong.

If you aren't paying attention to small details which I can see. Why should I trust that you are paying attention to the important things which I can't see.

If you press the volume up and volume down button on the radio in my car when a CD is playing it pauses and the display says 'PAUSE'. If you do the same when the radio is playing the radio is muted, but the display still says 'PAUSE', not 'MUTE'.
It's a small thing, but it bugs me every time I see it. Not a good way to build customer satisfaction. All because, hopefully, something was deemed to unimportant to spend enough time on.