I'm sure that just like me you often need a bit of software to help you out with a particular task. Last week I wanted something that would help me find album cover art for my MP3 collection; it just makes flipping through music with iTunes a better experience.
A few minutes with Google and I found a likely candidate; after navigating to the parent site I was asked to register my details before downloading the utility. This annoys me! After all, I took the time to find the utility in the first place and registered an interest by wanting to download a trial version. If the software did what I wanted then I would have been more than happy to pay the license fee. If it didn't then no amount of email marketing would have changed my mind. The decision is made in the first few minutes and having to spend a couple of those minutes registering my details (or Mickey Mouse's if I'm feeling particularly mischievous) does not get the vendor off to a good start.
It's a little like walking into a Virgin Megastore and not being able to look around without first filling in an application form - great marketing...for HMV!
So site registration is not my favourite exercise but it registers a poor second to functionally restricted software. Why on Earth would anyone want to provide trial software that is not 100% complete in every way? First impressions count and if my first view of an application leaves me thinking that it could do more then it is highly unlikely that I'll pay good money for it. Knowing that additional features exist in the full version does not sway the argument.
It's a little like taking a new car out for the day on a test drive only to find that the performance has been limited or the air conditioning disabled. It doesn't create a good impression.
So please software vendors, wherever you are. Don't make us register with your site, don't restrict your trial downloads (except by time) and trust your development and design skills to win us over. I, for one, would be a happier shopper and a happy shopper spends more than a disgruntled one.
:-)
Thursday, 18 October 2007
Trial software on trial
Posted by Wibbo Labels: Restricted download, Site registration, Trial software 0 comments
Wednesday, 17 October 2007
Part 4: Implicit types
With C#2, a variable's type must be explicitly declared, some simple examples are:
int clientAge; |
Notice that we do not have to specify a value for the variable at the point at which it is declared, in the example, clientAge will be assigned a value of zero by the compiler. In C#3, variables may be declared with the var keyword in which case the compiler infers the variable type from the value it has been assigned...but it does this at compile time!
So var is not a variant (it's just a keyword that's not named particularly well) and it's not an object type either.
The following constraints apply to the use of the var keyword:
- var can only be used within a method and not at the class level
- Any variable created with var must have a value assigned as part of the declaration
Please see the following code for examples:
class VarSamples |
The invalidDeclaration variable will not compile because it has been declared at the class level. This is not allowed for variables declared as var.
The streetName variable will not compile because any variable declared with var must be initialised when it is declared. Otherwise, the compiler is not able to determine an actual type for the variable when it is compiled.
So why do we need var at all?
The var keyword was introduced to support anonymous types that are also a feature of C#3. Anonymous types are described in the next article.
Posted by Wibbo Labels: .Net3, C# tutorials, Implicit types, Learn C#3, Programming, Software, Visual Studio 2008 0 comments
Part 3: Initialising objects
Consider the following simple class definition:
//Simple client class used to demonstate |
A constructor has not been explicitly created for this class so the compiler will generate a default, parameterless one for us. This means that an object can be created and properties assigned inthe way that we are currently used to with C#2
//Create a client object using the default constructor Client firstClient = new Client(); //Assign values to the class properties that have public set methods firstClient.Name = "David"; firstClient.Age = 32; firstClient.Height = 124; |
However, with C#3, we are now able to create an object using any of the following methods:
//Construct the object by supplying the client Name Client secondClient = new Client { Name = "Matthew" }; //Construct the object by supplying //the client Name & Age Client thirdClient = new Client { Name = "Sarah", Age = 21 }; //Construct the object by supplying //the client Name & Height Client fourthClient = new Client { Name = "Daniel", Height = 131 }; //Construct the object by supplying //the client Height only Client fifthClient = new Client { Height = 108 }; |
This is essentially identical to creating a client object with the default constructor and then calling each property set method as appropriate. Looking at the disassembled code shows us what isactually happening for these client objects.
Client <>g__initLocal0 = new Client(); Client <>g__initLocal1 = new Client(); |
As the code above shows, each client is constructed using the default constructor and then the property set methods are called as necessary. Of course, we cannot specify a value for IsCurrent when creating a client object because the set property is marked private (as shown in the first code snippet). Trying to do so will generate a compile time error of something like: The property orindexer ‘Blog.Client.IsCurrent’ cannot be used in this context because the set accessor is inaccessible.
Part 4: Implicit types
Posted by Wibbo Labels: .Net3, Automatic properties, C# tutorials, Initialising objects, Learn C#3, Programming, Software, Visual Studio 2008 0 comments
Part 2: Automatically implemented properties
C#2 provides the ability to create properties that encapsulate class member variables; the following code provides a simple example:
//Private member variable to store the client name private string name; //Read-write property for the client?s name public string Name { get { return name; } set { name = value; } } |
The idea here is that the property prevents the class variable from being accessed directly. A property can be made read only as follows; this is simply a property that does not have a set statement.
// Read only property that returns the client?s name public string Name { get { return name; } } |
C#3 provides a shortcut syntax for creating class variables and associated properties; the first code example can be shortened to:
// Shortcut syntax for creating properties //and underlying member variables public string Name { get; set; } |
And of course, the principle of read only (or write only for that matter) properties is also supported using this new syntax:
// Shortcut syntax for creating properties and underlying //member variables (this time ClientName is read-only) public string Name { get; private set; } |
For this shortened syntax, the compiler actually generates all of the required code behind the scenes. So in effect, you end up with exactly the same code that you would have got if you had written it using the available syntax of C#2. The code below shows the MSIL that is generated from the source code; note the use of the [CompilerGenerated] attribute that decorates the code.
[CompilerGenerated] private string public string Name { [CompilerGenerated] get { return this. } [CompilerGenerated] set { this. } } |
Automatically implemented properties provide a way to quickly expose class member variables; we will examine this feature more in the next article.
Posted by Wibbo Labels: .Net3, Automatic properties, C# tutorials, Learn C#3, Programming, Software, Visual Studio 2008 0 comments
The newbie guide to C#3, Part 1: Overview
This short series of articles gives you an overview of the new features provided by C#3. The articles are peppered with simple code examples that you can copy directly into a C#3 editor to try them out for yourself. At the end of each article, a link is provided to a standalone class that contains fully commented examples of the features that have been discussed.
The information presented here won't make you a C# guru but they will give you an appetite for the new features that have been added to the language.
Part 2: Automatically implemented properties
Part 3: Initialising objects
Part 4: Implicit types
Posted by Wibbo Labels: .Net3, C# tutorials, Learn C#3, Programming, Software, Visual Studio 2008 0 comments
Saturday, 16 June 2007
Smaller steps, greater strides ... revisited
I often see colleagues of mine struggling to add new features to our software; I often see workmates struggling to rectify the existing features of our solutions. Frustrated managers wonder why code that only took 2 or 3 months to write has stagnated in an endless UAT cycle with little hope of breaking free. Small change requests end up taking 3 times longer than the estimates that helped justify the change in the first place. Customers, initially used to timely releases grow increasingly impatient as release periods are extended or bug littered deployments are made on schedule.
Why does this happen? Optimism play a small role in this predicament; as software developers we almost always underestimate the tasks that we are given. Pick up any Steve McConnel book and look at the graphs - it's an industry wide phenomenon. Although this plays a contributory role, it is by no means the root cause of the problem. I rarely see developers having difficulty putting new code together; I guess there's no getting away from the fact that software is easy to write but difficult to maintain. There is also the question of motivation, nobody likes to work with scrappy code; as Pragmatic Programmers we shouldn't have to live with broken windows.
So why do we write poor, complex, undocumented code when we know it will eventually come back to haunt us (or more likely someone else on the team). Sometimes it's laziness but I think there is an inherent trait that developers possess - we are always keen to see the results of our ideas. We start with the best of intentions but as we gain momentum we see the outcome beginning to materialise. We write code more quickly, absolutely determined to come back and add the comments and write the unit tests. It's not true TDD anymore but the result is almost tangible now, just a few more lines and we'll be home and dry. Sure we have some tidy up code to complete, exception handling needs to be incorporated and then there's the diagnostics namespace to worry about...but just a few more lines and the refactoring can begin...just a few more lines...
And so the problem begins. before we get chance to paint over the cracks a system bug is reported, the requirements change and a different solution is screaming for attention. We no longer have time to commit to our solution, there is no longer an end point to reach for - just boring changes and bug fixes. The momentum disappears and we move on to a newer, brighter challenge vowing never to cut corners again. Somebody else is assigned to the project, sees all the broken windows in the neighbourhood and continues to break a few of their own. Which leads us back to our frustrated managers and impatient customers.
There are many methodologies that address these issues and offer a strategy for preventing them. Personally I think the methodology we need is a simple injection of discipline. After all, if you can't be bothered to add a single function header now, will you really come back and add 100 once your class is complete? If the code seems to work ok will you really find the time to go back and write the unit tests. Even if you do, the opportunity to confirm your understanding of the problem before the coding started disappeared when the TDD process stopped.
As with any habit, good or bad, it can take a lot of discipline and effort to stop. The same is true, in my opinion, with software development practises. Jumping ahead may seem to shorten the journey but smaller steps really do lead to greater strides especially in a well disciplined environment.
Posted by Wibbo Labels: Development process, Programming, Software engineering 0 comments
Wednesday, 6 June 2007
It takes time to make a decision
Some people describe software development as a manufacturing process. Basically you take a recipe, try it out a few times and once you are happy with the ingredients and the cooking process you write it down and pass it on to your eager coders. Over time you collect a whole book of recipes that can be easily followed, producing code that is both repeatable and reusable. Software restaurants announce ticker tape openings around the globe to serve up cheap and reliable cookie cutter software solutions. Recipe for success? Actually, past experience tells us that more often than not it is a recipe for disaster.
The manufacturing process needs to guarantee repeatable results and this is very difficult given the amount of human intervention that programming typically involves. Of course, there are now many utilities that generate, parse, check, analyse and generally prettify source code but it's still essentially a solo practise between the developer and the IDE (apologies to all you XP pair programmers out there). There is also the issue of code maintenance to consider, generated code is not the prettiest of creations and, whilst it's fine when it works, any subtle imperfections are often very difficult to isolate and rectify.
Some people describe software development as an artform. Each contributor adds their own creative interpretation of requirements, applies keyboard brushstrokes to their electronic canvas and steps back to admire yet another unique creation. No two pixel paintings are the same; programmers the world over write different code to achieve the same objective. Even individual coders write the same routines differently, with or without varying degrees of standards and procedures, many times during their illustrious careers. An artistic masterclass? Very often this approach generates code that may be inventive but is seldom practical and rarely maintainable.
The problem here is consistency; code is produced that can be difficult to maintain where the layout of each class looks very different to its neighbours. There are a number of architectural decisions and considerations that a developer has to make that exist outside of what is generally perceived as the 'system design'. Does a particular piece of logic sit in the database layer or the business layer? How are exceptions handled? Should a method be instanced or static? Do you choose an interface or an abstract base class? In reality your code is simply a string of statements, loops and conditions but the potential number of combinations are astronomical even within a relatively small code base. Coding standards and recommended practises can help to reduce the confusion, code generation can produce generic classes and components and design patterns provide some level of guidance but dividing a limitless number of possibilities by any given factor still leaves a limitless number of possibilities.
So should we strive for a repeatable and consistent, painting by numbers development process where creativity and initiative are completely removed from the programming equation? Or do we promote flexibility and encourage our development teams to express their creativity and inventiveness in new and inspiring ways? Is there some magical, middle ground that satisfies the developer's creative aspirations whilst still adhering to repeatable templates, design patterns and agreed best practises?
This blog is littered with questions but unfortunately devoid of answers; each question corresponds to at least one, and often very many decisions. It is ironic that the decision making process is a key factor in making programming an interesting practise. It is also a subtantial contributor to the problems and complexities that lurk beneath the surface of even the most trivial of solutions.
Decisions take time ... so less choice, less freedom and fewer choices must surely facilitate a better programming environment...or do they?
Posted by Wibbo Labels: Development methodology, Programming, Software, Software engineering 0 comments