Neil's Place

The Twelve Days of Software Development

Previous Page

9. Portability

Portability is about ensuring your application will run on multiple platforms. It is also about architecting your application in such way that it is easier to move to other platforms. Usually this will involve quite a lot of work, more so than most other work. It is almost always the case that the application, or particular components of it, will need to be architected to be portable from the very start. Having your application portable doesn't mean that it runs on several platforms, instead it means that it is designed to be moved to other systems easily. Some applications which are available on multiple systems aren't necessarily portable. Chances are that this is the case if releases for other platforms appear four months after another.

It is very easy to make your application non-portable by using platform specific functions. Of course, you will need to use these platform specific functions if you expect anything to work. You also need to ensure you use platform specific conventions for your user interface, keyboard shortcuts, and the manner in which you interact with the system and other applications.

Portable applications tend to deal with different platforms by building a series of portability functions that abstract out specifics such as the reading and writing files, drawing graphics and reading from the keyboard. There are numerous implementations of such functions, since every application has their own set. Developers have created 7000 different variations of 'typedef int Int32'.

Many programming langauges and toolkits are avilable nowadays that provide such abstractions for you. They provide rich libraries of types, and file and graphics handling functions.

Unfortunately, all of the toolkits fall short of true portability. This cannot be solved as true portability is impossible. Languages, like Java, are marketed as portable languages, designed to allow you to write code on one platform and run it on all other platforms without changes. Be careful about making this kind of claim though on your own product though; since you cannot attain true portability, people will question this claim if something doesn't work exactly as excepted.

This isn't a problem with the languages or toolkits themselves. This comes from a misunderstanding by many developers of what portability actually means.

First, there will always be differences in the implementation of the toolkit from one system to another. This will either be due to bugs in the implementation, or due to technical details that are difficult or not possible to work around. For example, on Windows, hidden files are indicated by a flag on the file, whereas on Unix systems, the name of file begins with a period. It's possible that the language you're using abstracts this out in some manner, however there are thousands of these little differences that the language won't handle. Instead, they will expect you to deal with these details yourself.

In many cases, if a developer only has access to one platform, it's likely they won't have significant knowledge of how other platforms work. The developer will end up making incorrect assumptions when writing their application. In some cases, the development language may handle certain details for them, but in other cases in won't. For instance, on most systems you can refer to a file using a path like '/main/docs/readme.txt', but on a Macintosh, you cannot do this accurately. If you assume you can, your application might not work. This is one reason that languages provide a File class that is created by constructing one from each parent directory successively. Another Mac example would be thinking you could copy a file by reading the data from the file and then writing the data to another file. This isn't the case on classic Mac OS, as it stores files in two pieces (called the data fork and the resource fork).

If you don't know about these kinds of details, you will end up with an application that doesn't work on other platforms, and you won't know why. Many developers will end up blaming this problem on the toolkit itself.

Don't assume that when you use a 'portable' langauge or toolkit, that it will handle all of the portability for you. The toolkits do some of the work for you, but they don't magically do appropriate translation for you if you make incorrect assumptions about how other platforms work. They won't prevent you from doing something that doesn't make sense on other systems.

An example would be the differentiation between text files and binary files. Some systems do not make a distinction while others do. If you assume wrong, you will break one platform but not the others. Thus, you should always test your application on as many platforms as you need to. Don't assume that the operating system is the only difference either. There may also be issues with specific revisions of an operating system. For example, I once worked on an application that worked fine on most platforms except a particular version of Windows 98. (there is a Windows 98A, Windows 98B and a Windows 98C) It turned out that a text configuration file had a line with a Macintosh line break in it. The file was shared between the Windows and Mac versions, and had last been edited on a Mac editor. This problem caused the application to crash on one particular version of Windows.

Thus, if you decide to focus on portability, know that it will be a lot of work. Don't stress the fact that it is portable too heavily and don't assume that you be able to make portable applications magically. Take some time to learn about your target platforms first, and test your application on a wide range of systems.

10. Compatibility

Compatibility is about several things -- ensuring that your application is compatible with previous versions, ensuring that it is compatible with future versions, and ensuring that it is compatible with competing products. One or more of these may be important to you, or none of them may be important.

If you are introducing a new product designed to compete with an existing well-established product, compatibility with that product may be a high priority. This means that files created with the other can be used with your product, and perhaps vice versa. In addition, it may mean that you need to create your user interface in such a way that people migrating to your application will understand how to use it. If your application to too different, or if it involves a lengthy process to import data, users will be turned away. Many users will only be evaluating your product. This evaluation period, usually lasting several days or weeks, is critical to ensuring that users stick with your application. Making the migration process simple is important.

In other cases, you may not have significant competition, or the field has lots of competitors. Compatibility with many other competitors may be difficult so you may wish to focus on particular targets. You may wish, for example, to focus on the weaknesses on one product, and make these features better in your own product.

After you have had several releases of your product, backwards compatibility is important. This means that newer releases need to be able to read files created by earlier releases, and users can import their settings seamlessly. Ideally, when a user upgrades, the user will not be required to modify the application, for example, to change their personal preferences, as these settings will be available from a previous version. This is true even if you change the manner in which you store information for whatever reason.

When creating a new release of a product, avoid changing it too drastically. Users will get confused if every version is radically different from previous versions. Instead, make changes incrementally. This isn't always possible though. For example, you might redesign a feature after feedback from users suggests it is too difficult to use. To some extent, an upgrade is just like using a competing product. The more difficult the new release is to evaluate and use, the fewer users will use it.

It is also important to ensure that your application is forward compatible if possible. This is a very difficult task. When creating a product, you will only be able to anticipate the kinds of features you will want to add in the next couple of releases. You won't be able to predict a feature that you'll need to add five years from now. This means that you may not have been able to architect your application in such a way to make implementing that feature easier. When Netscape first created the first version of their browser, they were able to plan for adding features that they would need soon, such as secure connections, scripts and plugins. Thus, they could plan for these features earlier. The need for style sheets wouldn't appear for a while yet, so they didn't anticipate them, and versions 4 couldn't support them very well. Microsoft, Opera, and later versions of the Netscape browser had anticipated these features since the produced their browsers later when the need could be better determined.

Often, your development time will be limited due to costs or because you need to release your product quickly for competitive reasons. This means that you won't have time to plan ahead for future versions. You will end up with features that are poorly designed. If you are building a development tool or programming language, you will end up with poorly defined interfaces, that will need to be overhauled in later releases. For example, Java has had numerous significant changes to its API, although backwards compatibility has always been maintained. Expect to have numerous poorly designed features in your product.

If your product is customizable and extensibile, you will also need to ensure that any components third parties have created to use with your product still work with each release. The isn't entirely possible and you won't be able to test all of them. You won't even know about the majority of extensions, since they will have been created for a specific usage of a certain company by that company. The more extensible your application, the more difficult it will be to maintain compatibility.

People have a tendency to find a solution to a problem that have the desired result, rather than finding a good solution. For example, someone might have created an extension to your product that does something when the user prints a file. It does this in a strange way, by listening for when the user clicks the Print button on the toolbar. If you release a new version of your product and you decided to take the Print button off the toolbar, or move it somewhere else, the extension crashes. This isn't something you can do much about, since the 'strange way' described above isn't a method you endorse.

Be prepared for this kind of thing. Even if you provide the best documentation in the world about what to do and what not to do when creating an extension, developers will find a way to do the wrong thing. Take a look at the way web pages are created. Most web page devlopers just modify a page until it looks the way they want it, rather than making it the way it should be.

Compatibility is a challenge. You have to balance between adding new functionality and maintaining existing features. Every time you add a new function, you risk breaking an existing one.

11. Security

The wrong way to handle security is to release a product and wait for someone to find security problems. Instead, you need to evaluate designs from the start for potential security issues. If you find an issue, you will need to go back and make some changes to the design. In some cases, it may be worthwhile to release a product with restrictions on what can be done, limiting the possibility of a security problem occuring. Later, when you are more satisfied with the safety of your product, remove the restrictions or place more friendlier restrictions in place.

Some security problems in products are the result of bugs in the product. These kind of problems aren't really avoidable; you just have to ensure you perform a careful code review of both new features and changes to existing ones. This is something that should be done in more detail for code that deals with security than for other sections.

Sometimes, however, a feature is flawed by design. The implementation is sound according to the design, but the design has some inherit problem with it. This isn't always intentional. Sometimes a great new feature is designed for one purpose, but can easily be exploted for other purposes. Allowing people to send and receive files through email as attachments may seem like a good idea, but too much automation in this process and we've seen what happens as a result.

Security is important to protect users from both malicious usage but also to protect user information. If you are dealing with personal information, you need to be especially careful about how you use this information, how you store it, and how you transfer this information from one location to another.

Our society's fear over privacy concerns has grown stronger over time, especially as viruses continue to attack us and web sites collect more and more information from us. It's possible that much of this fear is unfounded and has only grown stronger as issues arise over time. In reality, the information most web sites collect, such as our name, email address, age, browsing habits and so forth, isn't any real threat to our safety. Yet, many people are reluctant to enter their age or even their gender on a web form, for example. This is true, even despite that one can usually determine this information or approximate it by looking at you as you sit down on the bus. And someone sitting on the bus is far, far more likely to cause harm to you than Yahoo's database administrator living 2000 miles away ever could.

Still, our society has grown accustomed to the idea that certain information is our personal property. So you need to be careful about what kind of information you ask the user for. Each peice of personal information requested means a drop in the number of users who will continue using your product. You should certainly consider making some fields optional.

These kinds of security may not be important in some kinds of applications however. For example, an application built to control equipment in a factory doesn't generally need to be as concerned about malicious code entering the system. The overall factory might be concerned though, but this kind of issue would be handled at a network or system level rather than at the application level.

For applications that use the Internet however, this becomes more of a concern. You need to ensure that the application doesn't allow remote content to be executed. One thing to be careful of is that users won't really read a confirmation dialog. If that's all the protection you provide, you may wish to rethink the design.

End users understand the implications of security problems, but usually just assume that they are safe in what they do. They will just blindly click through dialogs without any concern. Some bank web sites try to force you to accept security by preventing a user who doesn't have some particular level of security or browser they happen to have tested from using the services. This may sound suitable to a bank but technical users who know what they are doing get annoyed.

It is a tough decision whether to improve functionality at the risk of security or to limit your new features in order to limit potential security issues.

12. Marketability

Sometimes, you might design a product in such a way so that it is easier to sell. For instance, I've noticed that some products have a name which seems to have been selected just so that it can have an interesting ad on television.

When looking at features to implement in a new product, you will need to look at existing competitors. If you can identify a particular weakness in a competing product, you will want to ensure that you focus on correcting that weakness in your own product. Don't concern yourself over a weakness that users don't seem to have noticed. Instead, try to determine what users are saying are the faults of the competitor's products.

If users keep complaining about a particular aspect of a competing product, they will likely welcome a new product which fixes this problem. This will often convince people to switch to your product even when your product has other disadvantages. If your product doesn't solve the defects of a competitor, people are unlikely to switch.

In some cases, a competitor won't have any significant defects that you can solve. This will make your job more difficult. Users are satisfied with the current product they are using so they won't actively be looking for a replacement, and there is no reason why they would have a desire to use your product. When this is the case, you will need to find ways to convince users of the defects they don't know about in your competition. You do this by pulling two socks out of two baskets and showing how one has grass strains on it, and the other sparkles. No one noticed that problem before, but they might notice it if you point it out to them.

Many products are produced and sold at little to no cost in order to help increase the usage of another product. For example, selling nails cheaply in order to sell more expensive hammers. Software is often like this. Some software is given away or sold at low cost in order to sell more hardware, accompanying server-side tools or support for the product. This encourages a larger number of users to use your free product, which in turn causes more people to use your additional 'money-making' products. Sometimes this is done by adding features designed to work better in tandem with other products.

Know your target users when trying to build an application. If your target user is a person that isn't very technical, you need to make your product easier to use, and simple to get started with. Then, tell people how easy it is to use.

If your target user is a user in an office, you will likely need to target the company support staff. These people will tend to select products that they think are easier to maintain and administer. This won't necessarily correlate with which products actually are easier to maintain and administer, nor will it correlate with the products that actually are better. The average office worker isn't very technical and will just assume that whatever is installed on their system is the best choice. Cost will usually be a significant factor here.

Getting a good review in trade magazines is important. Unfortunately, people who write reviews in magazines and web sites aren't your target user. You may get a bad review if your product doesn't meet their qualifications, regardless of whether it would meet those of your users. The reviewers don't tend to spend very much time using your product. In fact, some will just rephrase your press release into a review.

Since the reviewers will spend so little time with your application, they will often highlight very different features than you would. Often, a significant amount of the review will focus on the flaws in your installer, as that's the first thing the reviewer will see. Another common thing you'll see if a variety of unscientific graphs showing performance of your new product with competitors. And no discussion of reviewers would be complete without the Item of Bad Press. If you get some bad press for something, expect it to be mentioned in every article about you for the next few months or years, no matter how relevant it is.

If selling your product to users through reviews in important to you, take steps to ensure that reviewers are reviewing the right aspects of your application. You might consider writing documentation specifically geared towards them.

People usually select products based only on a tiny selection of criteria. As long as those criteria are met, they will use your product. You need to identify which criteria are important to the users you want to target.

Conclusion

When building a software application, decide which of the above twelve categories, or others not listed, are important. Don't base this decision based on your personal preferences, base it on your target user. Make sure that your view of your target user isn't clouded by other users that have louder voices but who you don't target. Since you don't target them directly, you will be unable to tailor your application just for them.

You won't be able to control who uses your product. Learn to expect that a noticable number of users won't like it. You won't be able to please most of the users of your product. In subsequent releases, you'll have a better idea of the kinds of users who are using your product, and you will be able to focus on those aspects which will be better for them.

Page 1  Page 2  Page 3