Friday, October 29, 2004

Joel's best articles reviewed

Even though I have a billion other things to do, I couldn't help but get sucked into reading every one of the 112 (as of this writing) articled submitted to Joel's best articles on Software Development. This is a deviation from my normal content, but there is value to be gained for most all readers in the Software industry - designers, marketers, and developers.

Here are my favorites (not necessarily the best of the bunch, but ones that got me to think), I will link to the nomination post, suggest the audience type, and give my .02c. :

Church of XML. If you use XML and like sarcastic humor, this may interest you. At least, I hope it is meant to be sarcastic. XML is great for some things, but it is not the holy grail solution for everything data related. I remember in Y2k working for a company whose directors told the development staff that we must use XML. We quickly coined the phrase "buzzword compliance" to describe the requirement. There was no possible use for XML data in our application where XML was a viable alternative, much less a better one. At a later company, the value of XML as a method of integration with our customer's systems and as a communications mechanism (XML-RPC) was profoundly positive. Members of the Church of XML may want to defect after reading another few nominated articles: ant and XML, and Soapbox: Humans should not have to grok XML.

How many Microsoft Employees Does It Take to Change a Lightbulb. Any developer should enjoy it, but managers (especially ones driving deadlines) need to read it. I am a big fan of Eric Lippert's writing style. This one delves into the cost of fixing a bug. I prefer this one to the main article nominated since it is more to the point. Setup developers may want to read The anatomy of a bug as it deals with an uninstallation issue, and something you may want to think about. Both articles do not mention the cost of fixing a bug in terms of dollars (refer to your copy of Code Complete for more on this). Although you may disagree with Eric's line: "At Microsoft we try very, very hard to not release half-baked software," the point he is trying to make is if you do release bad code, it costs a bunch (in dollars and manpower) to fix it later. Almost on-topic is a 20 minute video of an actual bug triage meeting at Microsoft. Good stuff.

Plus ca change. Reading for anyone interested in how standards can be used to even the playing field for small software vendors. Or perhaps not. While I am not heavy into the web standards discussions today, at one point I was. To quote The Gunslinger, "The world has moved on." HTML's initial purpose (IMHO) was to allow me (the user) to render content as I (the user) wanted to see it. Netscape and Microsoft decided that their extensions to HTML would be the differentiators between their browser products. The content producers decided that web content should be shown to the user the way the content producer wants it to look, and with these extensions, they could. This seriously limits the accessibility of the content for people with disabilities, which was one characteristic HTML was supposed to give content producers (and users) for free. Flash and Shockwave further limited the control of content by the user. My thoughts on this today are for vendors to add their extensions whenever they want. If the extension provides enough value, other vendors will pick up on it and it will become a defacto standard. Today, implementing a standard in a web browser is not good enough to get you lined up at the starting gate. Look at Internet Explorer - massive share and not 100% compliant.

Lean Construction. Audience is general developers interested in planning. If you have read Code Complete, you will notice the use of metaphors throughout, one of which likens software development to a construction project. This article is the result of a software developer attending a class for construction foreman related to project planning. Some of the takeaways trumpet agile development methodologies. I especially like the quote: "master schedules are useless for planning work, contracting practices create islands of optimization, and there are large opportunities for productivity improvement." Is the author referring to current software development methodologies or old construction planning?

The 5 Pitfalls of Estimating a Software Project. Also see "Repeat After Me: I Am Not In the Software Business" in the same nomination. Everyone should read these. I have nothing else to add - they both have excellent points and are short enough to easily grasp it.

In the Spirit of C. Hardcore programmers. This one is fantastic. In the "managed" world of programming frameworks, it is easy to lose important roots in development. I am completely surprised by the number of programmers that do not know C or C++ well enough to code a real application. I've found that the best programmers are ones with roots in C. C developers tend to be able to learn new languages quickly, and pick the best language for any given programming task. Noteworthy quote: "In my experience there is almost no limit to the damage that a sufficiently ingenious fool can do with C++. But there is also almost no limit to the degree of complexity that a skillful library designer can hide behind a simple, safe, and elegant C++ interface. "

Ten Ways to Kill Design. Product managers are a good audience. This talks about new designs and pilots, and how/why they fail (unrelated to the design itself). For more information on the design, spec, and requirements, please check out another nominee On Reqs and Specs.

Hazards of Hiring. For anyone considering beefing up your workforce or looking for a job. It is an Eric Sink article that is very good, as usual. There are more worth reading that are related, such as programmers are not hackers.

Simple is Beautiful. All developers. Quote: "If you manage to write some code that a non-programmer can more or less understand, then you know you're there. The code should be simple and self-explanatory enough that should be a breeze to refactor in the future." Another nice quote is from Brian Kernighan (an inventor of C). I have this quote hanging up by my desk: "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."

We built it but no one came. Product Designers. Quote: "the thing that engineers love most about their technology is precisely what prevents them from making money." I looked at Steve Johnson's blog and he writes lots of great stuff in the development/marketing arena. Subscribed! I recommend anyone in the position of designing a product for the Average Joe to pick up a book Crossing The Chasm by Geoffrey Moore.

Growing, Pruning, spiking an architecture. Designers. Quote:"Good architectures are those in which it is considered easy to create the features desired."

What is a Web Service. Anyone. I agree with the other commentator. This is more of a definition, but summed up well. This allows me to segue into the topic of dynamic vs. loose coupling in typical service oriented architecture, although this latter link is more specific to architects.

Exceptions vs. Status Returns. Developers. The age old debate on the use of Exceptions. My position is contrary to the nominee. If you take the debate further, there is the use of exceptions as flow control. Exceptions are good when used appropriately - for the exceptional case. Too many times I have seen code that encourages or uses exceptions when simply returning a status value would be better. There are some good examples here. An OutOfMemoryException is a valid use of an exception. No matter how deep in my code I am, this is something that is highly unlikely to be handled appropriately or anticipated.

How to tell your personality from your code. Developers. Quote: The Obfuscator: "while(*a) *b++ = (islower(*a))? *a++:*a++ + ('a'-'A');" I have not only worked with each of these coding personality types, but I have been them. I wonder what my code personality type was today?

Choose your competition. Entrepreneurs. Quote: "The existence of a competitor indicates the existence of paying customers." As usual, good stuff from Eric Sink.

State of Affairs in Computer Science Education. Everyone. I was going to write a blog entry about this one. Since I'm trying to get a new sheepskin, one of the classes I am required to take uses a book "Object-Oriented Application Development using Visual Basic .NET" by E. Reed Doke. The book stinks. The fact that I must take and pay for this "capstone" course instead of one where I could actually learn something new is one problem with the system. In this book, the author uses a phone number as the primary key on the Customer table! I guess with phone number portability, this is an acceptable PK! We are teaching people this? The brilliant author creates a method in the Customer class called TellAboutSelf() that returns a string representation of the object. Wouldn't it be industry-standard and expected to override Object.toString()? WTF! This simply adds to the retraining requirement of new grads that enter the workplace. This is another segue into yet another nominee Eric Lippert's Cargo Cult Series. If you are a new or experienced developer, and especially if you are still held captive by academia, this series is a must-read.

Saturday, October 23, 2004

Joel on Software's Best Software Essays of 2004

I noticed in my referral logs that a previous post of mine about Excellence in Software Development was nominated for the "Joel On Software" best Software Essays of 2004. If you haven't read that previous post yet, please do so. I'm impressed that "schmoe" found that post enlightening enough to nominate. It is certainly not the best work on the subject that could be done, rather reflections that came to me at 1:40 AM that evening/morning. Perhaps this is what blogging is about - a slice of time or history that impacted the blogger in some way that he or she felt important enough to share with others.

The nominator mentioned that my post is similar to the "Personal Character" chapter in Code Complete 2nd Edition. Sadly, I have not completed reading that book (including chapter 33) - it keeps getting pushed aside for other books because I read the 1st edition long ago. I'll have to put the book back to the top of the queue to catch this reference. I'm sure that I'd agree with Steve McConnell's philosophy - I have in the past.

Joel publishing a collection of these essays is a good thing, especially since he is so well respected in the community. Hopefully, he will allow some editing if that post is chosen - without having link context some of the points don't make sense, which is typical of a blog entry. If you don't read Joel, you probably should.

I haven't read many of the other ones nominated. I have read Joel's excellent essay on how Microsoft lost the API war. I disagree with Joel on "the new API is HTML" conclusion, but the points that he makes are well done. Perhaps I will blog a review of some of these other nominated articles after I catch up on some now mandatory reading at the expense of Steve McConnell.

Which Keyboard?

Last weekend, I spilled a little bit of coffee in my keyboard. Hey, accidents happen. I had a Microsoft Natural Keyboard Pro. It is a keyboard where the left and right side were split and a bit raised. I loved this keyboard. The feel was more "natural" than a flat keyboard, and I never had wrist fatigue. The keypresses felt perfect. Post coffee, the keyboard began to spit out more characters than asked to. After drying it out, tearing it apart, and putting it back together, I realized how sensitive these things are to manual reassembly. I also realized how much "flat" keyboards suck in comparison by how my wrist is feeling.

Today, I bought a Microsoft "Wireless Optical Desktop Comfort Edition." at Costco. The price was right at $60. I still like the feel of the keys, but this curved thing is making me crazy. I have never hit "backspace" as much as I have in the last two posts. Plus, after typing a bit, my wrist still feels strange, like using a flat keyboard. The "comfort edition" is curved, but not split or raised in the center. This may be the problem. Also, the function keys are shared shortcut keys. I won't get used to that.

Additionally, this duo has a nice "pleather" wrist-rest that I like. The mouse is plain plastic. I'd think they would both be pleather. I was wrong. The scroll wheel moves easily, but almost too easily. I don't get the feedback I am used to. Perhaps I will get used to it. The mouse "feels" right.

I think I am going to return this one and go with the "Wireless Optical Desktop Pro," which is most similar to what I used to have. Best Buy wanted $100 for it. I can get it cheaper online. I really don't care about wireless for the keyboard, but for the mouse it is useful.

Does anyone have other suggestions? I considered Logitech's similar offering, but I just don't know. Microsoft's hardware has always been top-notch.

Friday, October 22, 2004

Raymond is on a roll... (shared files, versioning and setup)

Fellow blogger Raymond Chen has posted yet another blog of note to setup developers. I'm going to use a different example than he did, plus use it as a springboard for yet another rant. If you remember back to Windows 95, especially when configuring network settings, it would prompt for the CD (bad) and then prompt to if you wanted to overwrite a newer version of a file with an older version (even worse). As an added bonus, it asked this question more than once (the absolute worst).

Why did it do this? Read Raymond's answer. For this specific example, most people installed updates to the original TCP/IP stack. Windows 95 wanted to restore the initial version of all files in all cases. This could leave the user hosed if they didn't answer the questions consistently. Microsoft learned from this example. We should, too.

Lets look at how the MSI engine handles patching. OK, maybe that would be too long of a rant:) The essential thing to take away is that a MSI patch (msp file) will not overwrite a newer version of a file with an older version. In the usual case, this is not a problem, since all identically named DLL's are always backwards compatible (in Utopian software development), right? This is a decision the Windows Installer engine designers had to make up-front. And as long as we are in Utopia, it works.

If you recall, many older InstallShield installations also prompted the user on uninstall if they wanted to remove a DLL that is marked as shared, since no other programs claim they are using it. The more modern versions of InstallShield don't. Why? They expect us (setup developers) to get it right. Make sure you are using the appropriate method of installing files that may be shared by other installations. In the MSI world, Merge Modules accomplish this. But especially for non-MSI installations, make sure you are setting the "shared" flag, so the uninstallation of you application does not impact other installed applications by removing files critical to their operation.

As a side note, Raymond links to an older article related to asking useless questions that is quite humorous, yet further proves this important point: If you ask the user a technical question, odds are they they're just going to stare at it blankly for a while, then try to cancel out of it.

Don't make these mistakes.

Thursday, October 21, 2004

Control Panel Items

Since I'm on a roll with configuring stuff, there is a nice article on MSDN about configuring Control Panel Items. If you are a setup developer, this link will take you to the section that you should read.

Some things to note:

  • "...the DLL file must have a .cpl file name extension" - These control panel items ARE DLL's.
  • on "Windows 2000 and later systems, new Control Panel items should be installed in the associated application's folder." - Yep, no installation to SYSTEM like the old days!
  • The placement of a registry key dictates what shows up in the Control Panel. Remember to respect per-user installations! (Yes! it is a bug, a security one, and a bad one)
  • If you must support the "old" pre-Windows 2000 method, only do so on the pre-2000 OS.
  • Yes. you can extend System Control Panel Items.
  • You can also specify a category for the item in Windows XP or better, for users using the default control panel view.
  • For MSI folks, there is nothing in any of the Standard Actions that will help you.

Larry talks HKCR

If you recall, I recently blogged about the fact that HKEY_CLASSES_ROOT key is not a real registry hive. Larry Osterman from Microsoft recently posted a "What is wrong with this code?" series and covers the HKCR issue extremely well in the answer section. If you develop services, this one is worth a read.

Raymond talks about registering shell extensions

As you can tell, I'm catching up on reading some of my favorite blogs... Raymond Chen from Microsoft wrote a really nice article about registering shell extensions. Setup developers should take note of how Windows deals with what you put in those keys.

What is a shell extension (also known as Verbs)? This is what Windows uses to determine what to do (or what right-click options to provide) when clicking on a file with a specific extension. Read this link to find our more. I'll wait...

In the setup world, I believe when you run a program from a setup most vendors use the ShellExecute() API. If this is the case, when you launch a readme at the end of an installation by simply specifying "readme.txt" the default "open" verb (on a fresh Windows installation for a text file this will be Notepad) will be run. If the method of running an application in your authoring tool uses CreateProcess() , it will likely result in an error if you simply give it "readme.txt". For MSI based installations, many people may use the tutorial method described in the Platform SDK. I leave it as an exercise to the reader to see what that one uses! Any guesses based on the specifications for the tutorial mentioned in this document?

If you read the MSDN documentation for these functions - which are linked to above - you will understand this quote from the article: "Consequently, the shell mistakenly believes that the program name is "C:\Program", which it cannot find." This can be a security issue if a malicious program installs itself as "C:\program.exe". Please make sure you are registering extensions correctly - even if the installation design document you are given dictates otherwise.

Saturday, October 16, 2004

Custom Action Tutorial coming soon to a blog near you...

Since I didn't get any responses for suggestions for a C++ custom action, I took a look at the newsgroups and found this post where the author wants to detect if an application is running and prompt the user, close the application, etc. Developing a custom action to handle this would be a good thing for the community, as it is a fairly common request.

This also meets the bill for covering almost every aspect of a robust custom action - user interaction, running in silent mode, custom table, validation, etc. The one thing it does not implicitly have is a rollback action. I will "fake" a rollback action for demonstration purposes.

I also decided on a multi-part series as the best format for this.

  • Part one - describe the specifications and set up the development environment.
  • Part two - create a "Hello MSI" custom action and insert it into a sample MSI.
  • Part three - debugging the "Hello MSI" custom action.
  • Part four - add tables and other required entries to the MSI.
  • Part five - add code to read the tables.
  • Part six - add code to close the application. I'll likely gloss over this pretty fast, as killing an application is not the true focus here.
  • Part seven - testing the custom action.
  • Part eight - creating documentation for other developers.
  • Part eight - Creating validations for the action and tables.
In the process of developing this, I will loosely cover internationalization concerns, Unicode support, MSI Custom Action fundamentals, and more. I will "try" to follow the format of MSDN documentation in the process.

My intention is to complete the series first and post one new part every couple of days to keep the writing style similar and assure completeness. With my current workload, I'd guess part one would be published in late October.

Does anyone have specific feature requests for this Custom Action? Topics not mentioned here that should be covered?

Monday, October 11, 2004

.NET Deployment

I came across this blog entry that talks about this blog entry. So this blog entry is talking about a blog entry that is talking about a blog entry - whew!

The crux of the story is how an application based on the .NET Framework should be deployed. The post goes into adding the MSM for the framework, etc. The killer quote from the first blog entry by Stéphane Rodriguez is "What should I, as a developer, think about a development framework which by design involves hacks only for my app to be deployed?"

Amen, sister!

I blogged previously about how difficult it is to determine the .NET Framework and again when Aaron Stebner produced some sample code to check this. Stéphane hit exactly on what was in the back of my mind: Why is this so hard?

In theory, the .NET runtimes are mostly backwards compatible. The version detection scheme is not future compatible - I have no idea how to detect the .NET 2.0 RTM runtime today as a setup developer. Even if I can detect this, there are no guarantees that "Compatibility and Breaking Changes" haven't affected me. At least if I could detect the version, I could intelligently deal with it. I may alert the user that the framework version installed has not been tested with my application and let the installation continue. Then again, I may choose to have the old framework downloaded and installed. Or really anything.

The problem that exists is (as a commenter to the quoted blog points out) very similar to Java's problems. Microsoft should have learned from this and done a better job. Looks like they haven't - and mostly from a documentation perspective from what I can tell.

Lastly, there is a lack of tools and guidance to setup developers and how they should handle deployment. In an MSI, why can't I simply tell the engine/tools that my application targets one or more versions, and let the engine handle the detection job along with a warning if installed framework version is greater than what is targeted?

Why must stuff that should be so easy be so difficult?