Worst. Best Practices Book. Ever.

As you may or may not know, I generally critisize things on a daily basis. But this post is much different than my normal (hopefully witty) commentary on bad code. Today I'm pointing out some serious flaws in a book I came acrossed called Practical Guidelines and Best Practices for Microsoft Visual Basic and Visual C# Developers that make the book not only bad (which I can live with) but dangerous for an inexperienced developer. Not only does it fall short of "best practices," but it actually advocates bad practices. In summary, DO NOT BUY THIS BOOK. And if an enlarged & emboldened statement isn't enough, read on ...

Although Balena and Dimauro are MSDN Regional Directors (a prestegious title, I think), they are no where near "IT legend" status (unlike Don Knuth [pdf], Andrew Tanenbaum, Ed Yourdon, etc.). You would think they would supplement their lack of credibility with cold hard facts and research, but no, they just seem to make up arbitrary figures (pp 139, "avoid methods longer than 50 executable statements") and shove them in the book. And what's with 50? Why not 60? Why not 45? Look at a good book (Code Complete by Steve McConnell') and see that Steve backed up his best practice on method length with six different studies. SIX!! You won't find a single reference in this book.

On to the content, the authors use the words "always" and "never" way too much. The architects behind the .NET Framework didn't put in "forbidden fruit" that looks tempting but should never be used. For example, on page 325, they say that you should never catch the ThreadAbortException. What they don't mention is that catching ThreadAbortException (and ThreadInterruptedException for that matter) is the *only* way to gracefully clean up and exit from a sleeping background thread using unmanaged resources. This happens more often than you'd think; if you're interfacing directly with specialized hardware that takes a long time to do process (like a printer), you would put that in a background thread that waits for the printer to finish. If the user closes the application (and the background thread doesn't catch the Thread exceptions), you're hardware could be hung up.

Another example, on page 191: "All events must define two parameters. The first parameter is an Object named sender; the second parameter is an instance of the EventArgs type (or a type that derives from EventArgs) and must be named e." Wrong, wrong, wrong! An event can have any number parameters of any type with any name. That may be the way *most* events are handled, but it's certainly not what you *must* handle events. A lot of times there is no need for a sender reference or event arguments.

They also seem to really like the words "right"/"wrong" and "correct"/"incorrect". Let's take a look at page 140:
  ' *** Wrong: uses incorrect casing, type is embedded in parameter name.
  Sub PerformTask(ByVal UserName as String, ByVal boolIsAdmin as Boolean)
  ' *** Correct
  Sub PerformTask(ByVal userName as String, ByVal isAdmin as Boolean)
Their way is neither correct nor incorrect. It's simply a preference, it also happens to be the same preference that Microsoft spells out in MSDN, but they actually use the term "preference." Ironically, on the very next page (pp 141), they use a class named "frmMain." This is one of many examples where their preference doesn't line up with Microsoft's preference. MSDN prefers MainForm.

Next, the authors focus on "speed and efficiency" as if it's 1963 and a few CPU hours cost as much as a car. In the world of BILLIONS (1,000,000,000's) of cycles per second (Ghz), it really is ok to "waste" a few cycles on making sure your code is easier to read and maintain. You wouldn't get that impression from reading this book as a beginner:
pp 127: "the as operator ... speeds up execution"
pp 149: "Return keyword enables the compiler to optimize your code more efficiently."
pp 251: "language specific functions perform worse"
pp 253: "the ChrW function is faster"
pp 257: "the CompareOrdinal static method ... is typically faster"
They did not drive the point of maintainability over speed. 100 clock cycles will make ZERO difference on a 10 millisecond request.

I've also found that some parts of the book are hopelessly out of date. It would appear that the authors have not yet fully entered the world of .NET themselves. Take for example page 408, where they provide a rather "Classic ASP" method of setting the page title: <title><%=GetTitle()%></title>. The ".NET" way of doing this would be either using a literal <title><asp:literal id=pageTitle runat=server></title>) or making the title tag a server tag (<title runat=server id=Title/>).

It would also appear that the authors have little to no knowledge of relational database design. On page 380 they say "Don't use primary keys that have meaning for the end user, such as invoice number or the ISBN value." This is beyond absurd and defeats the whole purpose of "relational databases". Don't take my word for it, of course; ask any "Database 101" student or read it straight from the creators of relational databases (EF Codd and CJ Date). The authors' technique is as close to a COBOL-mainframe-flatfile method of development you can possibly get and is, ironically, what relational databases were designed to fix.

And on top of all of this, they're inconsistent in following their own "best practices." On page 251 they say "don't use Visual Basic-specific string functions, such as Len, Left, and Mid." Flip the page (pp 253) to another tip and see "favor the ChrW function over the Chr function." No mention about using "Convert.ToInt16," which they suggested as a replacement just on the previous page. And speaking of using "Int16", they didn't follow their own advise of "Use 32-bit integer variables" as suggested on page 240. And why int32? Because they're faster!

I really do hate to be so negative about this book. Yes, it does have some decent tips that will help an inexperienced developer. But at the same time it has some absolutely horrendous tips and there is absolutely no way that an inexperienced developer could distinguish between the good and bad. Stay clear of this book. Buy McConnel's Code Complete instead.

20 Comments

  • I agree with all your criticisms but one. The issue of primary keys being meaningful or meaningless is a real debate and I fall on their side.



    The issue is that ideally, primary keys should be immutable for a record (because it is referenced in many other tables with foreign keys.) If it is meaningless (i.e. a numeric counter), then that should be the case.



    However, if you use a meaningful primary key like SS#, invoice# or ISBN value; it is possible that a user may mistype those values when entering records in the database. At some point in the future, someone needs to go back to that record, and want to correct the mistake. If there are a ton of references to this primary key, that could be a very expensive task (e.g. you have to go through all dependent tables and make the same update.)



    In general, I like to use a meaningless primary key like &quot;BOOK_ID&quot; which is just a sequence type, and have a unique key for ISBN value so that uniqueness is still enforced, but there is no expense of updating that field.



    There are exceptions--so they should not use the word never, but I believe it is good practice.

  • I totally concur with el Nino. I find myself searching for other ideas to back him up, but there is no need. Top notch, el Nino!!!



    Perhaps someone should write a scathing article about the &quot;credibitliy&quot; of this article... :)



  • &quot;Don't use primary keys that have meaning for the end user, such as invoice number or the ISBN value.&quot;



    For relational DBs which are mapped to OO classes with some kind of business object mapping layer, there isn't much value in primary keys with business meaning, while there are drawbacks.



    Business meanings (and codes) can and do change. Depending on what kind of tools you have available to change all your primary keys this may or may not be a big burden.



    Not disagreeing with the overall jist of the review of the book (which I haven't read), just a point to consider.

  • I had received in october a first preview of this book (written in italian language) and what I can say is that the preview I have in my hand is a good book, with lots of useful optimization tips.

    I'm shocked to listen this opinion.

  • I also fall in the 'avoid using natural primary keys' camp, if only because too often natural primary keys often turn out not to be so, or are incorrect and need changing. My, bitter experience, rule here would be to avoid natural primary keys or in the worst case avoid natural primary keys that you do not manage.

  • I haven't seen the book, but this type of stuff really makes my blood boil. Assuming your description is modestly accurate I'm totally with you...

  • +1 on not using PK's that have a business meaning. IMO you always want a PK that doesn't related to the data in the row in any way. Whether you use an int or a GUID is up for debate, but not picking a business value for a PK isn't.



    At the very least, if you are going to use a buisness value for a PK, use it in a compound PK with an arbitrary value.

  • Your comments seem harsh: I haven't seen the book, but I would for example expect a &quot;best practices&quot; book to recommend using the standard capitalization styles and the standard sender/EventArgs pattern for events -I'd interpret &quot;right/wrong&quot; in a &quot;best practice&quot; book as meaning &quot;should/shouldn't&quot;, rather than being dogmatic.

    And I don't see anything wrong with &quot;&lt;title&gt;&lt;%=GetTitle()%&gt;&lt;/title&gt;.&quot; - I've seen &quot;&lt;% %&gt;&quot; recommended by Scott Guthrie as an optimisation technique, and it might save a picosecond here. &quot;runat=server&quot; would be better if the VS.NET designer didn't keep deleting it (fixed in VS 2005 I believe).



    However I won't get sucked into the tired old Surrogate vs Natural PK debate.

  • I find it somewhat ironic that somebody who nitpicks about words like &quot;right&quot; and &quot;wrong&quot; has the cheek to call this the WORST book EVER!



    I thought the book was excellent. Too many shops don't have standards or guidelines and the Microsoft Design guidelines are impossible to print or get in any sort of cogent form.



    The great thing about this book is it explains the reasoning behind its guidelines. It sometimes suggests alternatives that are the opposite of its recommendations, but explains why you should choose one solution over another.



    Having given a guidelines or rule AND explained the reason for it it gives concrete code examples to illustrate (the &quot;right&quot; and &quot;wrong&quot; you so strongly object to).



    I've bought a lot of rubbish books in the past (mainly from Wrox or Microsoft Press) but this is NOT one of them.



    Your personal attack on the authors (are we supposed to think that while they are not in the &quot;IT legend&quot; league of Don Knuth - YOU are???!!!) smacks of some sort of personal grievance rather than an honest review of a book that will prove extremely useful in many shops. It's readable by the average developer (which I would argue Knuth's dry academic work isn't) I don't know the authors and have no idea whether they are industry guru's or not. I DO know that their book will save a lot of people time and effort in drawing up standards. And it's easy to read and reasonably priced too.



    I, too, like &quot;Code Complete&quot; but it, too, can be rather dry at times and is a long read. This book makes a handy read for those trying to get up-to-speed on agreeing standards within a typical .Net shop on tight timescales. I highly recommend it.

  • The title was a bit of a pun, ala Simpons' comic book guy.



    Guidelines are great, but this book falls short of explaining the difference between preference and correctness. And for many explanation, there is a poor reason WHY. &quot;It's optimizes better&quot; is a bad excuse for their belief.



    I did not intend my review to be perceived as a personal attack on the authors. The fact of the matter is they have no established credibility. Nor do you, nor do I, nor do the vast majority of us. This is why most people who write books use references from either people with credibility or from research. The authors did neither.



    The book as potential. But as I see it, it's hardly of &quot;beta&quot; quality. One incorrect paragraph outweighs twenty correct pages.

  • I've attended Balena and Dimauro talks, I've read Balena and Dimauro articles and used Balena and Dimauro sample code and after that can say that I can really trust their work: they are great!!!



    No book, talk, article always tell *all* the true with *all* the details, some semplification is *always* necessary to focus on the main topic and to reach the target readers. Probably you just misunderstand the book topic and just focused on irrelevant details ;-)



    I do not agree with your review and I think that make no sense to compare

  • The world is full of mixed messages.



    I do try to follow best practices but there in no chance I would have bought this book. I use MSDN and FxCop and I try to understand.

    I believe that premature optimization is bad, I think that coding based on what the JIT might optimize is often premature.



    I like my RD a lot, but before he starts telling me what best practices are he better sit down and start working in some projects, not just training and consulting.



    The primary key thing is a burning issue. Burning issues should be expressed as such.



    Just today I caught and swallowed a ThreadAbortException, it was the right thing to do, it was from a response redirect and it was poluting the event log.



    I use the &quot;as&quot; operator all the time. I find it easier to understand and cleaner than catching invalid casts.

  • Dar Alex,



    While I would reserve my judgement about the book and your comments, there is one statement you made which I find rather unfair and unprofessional and crossing the lines of a personal attack



    &gt; Don't let the &quot;MSDN Regional Director&quot; title fool you: it's a volunteer position. You would think they would supplement their lack of credibility



    How (well) an author writes a book is not dependent on his title as such...and vice versa, a person's title/appointment/award is has no bearing on how (well) he writes a book or treats his dogs, etc etc.



    Going by your token, one can easily imply that someone who works in MS is bound to churn out a classic ? How a person carries out his duties should have no relative bearing on what he is awarded or appointed.



    That statement you made is also a &quot;blanket&quot; statement because you are effectively making a public statement against 140+ folks who are appointed their positions based on a number of (selfless) activities they have done that have contributed greatly to the dev communities. Writing a book is one, BUT knowing how to write a good book THAT statisfies everyone is definitely NOT one of the criteria.



    Now, I wonder what kind of flames you would incur if you substituted the Regional Director role with that of a Microsoft Valuable Professional one. (Both are voluntary as well) Now you deal with thousands more people.



    Having said that, my point is that personal statements like that can be sometimes viewed as personal and discriminatory. While I agree that having an appointment or title, regarless whether it is voluntary or not, does hold some weight in the public's eye; it should not be used as part of a basis of attack against someone's work just because you do not like it.

  • &gt; Today I'm pointing out some serious flaws in a book I came acrossed called &lt;



    Just when did you come acrossed this books?

  • Umm, have you ever worked on a website with 15 million members, and an average of 3 million visitors a day, that spend more than 2 hours on average? You see, in situations like that speed is very important. A single try statement, when repeated billions of times, can brake your application.



    When I was working on measly sites back in the day I was thinking the same way about processors and memory... Fortunatly, as I've found out speed and memory is very much important unlike human readibility which doesn't really make a shred of difference once a project is finished and encapsulated in the right way, which seems to be lacking with you.



    As far as 'right' and 'wrong' go... It really is wrong.



    ' *** Wrong: uses incorrect casing, type is embedded in parameter name.

    Sub PerformTask(ByVal UserName as String, ByVal boolIsAdmin as Boolean)

    ' *** Correct

    Sub PerformTask(ByVal userName as String, ByVal isAdmin as Boolean)



    You see, it is wrong because the two parameters have different names. I've never seen a standard or preference where one parameter will be lower case first letter, and the next one upper case first letter. What are you? Retarded? Learn how to critisize, learn how to program, and then make a blog.

  • &quot;You see, it is wrong because the two parameters have different names. I've never seen a standard or preference where one parameter will be lower case first letter, and the next one upper case first letter. &quot;



    True, but these are standards, or preferences. It is not &quot;wrong&quot; to use or not use them, while it certainly is wrong to label them &quot;wrong&quot; or &quot;right&quot;.

  • It's a good thing that they don't engineer bridges the way software is &quot;engineered&quot;, otherwise all the effort would go towards things like inventing the &quot;Gravity Makes Things Fall - Pain Hurts&quot; pattern rather than focusing on keeping the damn thing standing.





    Let's be honest, we are just making this up as we go along - maybe in a couple hundred more years of doing it there will be some 'right' answers, but current &quot;Best Practices&quot; of software development are really more like &quot;Practices That May Lead To Deliverables Other Than Heat, Or At Least Have For Me More Than Once&quot;

  • I'm in the camp of not making the PK meaningful. I was bitten by that one when I was starting out. Suppose the original thought was the invoice number would be the PK and it would just increment up like a checkbook. So you make the PK a int. Then the rule changes and the invoice number now needs to be coded to show the department that it's primarily from. So 1234 now becomes 1234-REC. Trouble. My belief and what I teach people is the PK should never be a meaningful piece of data.

  • I've found out speed and memory is very much important unlike human readibility which doesn't really make a shred of difference once a project is finished and encapsulated in the right way.


  • snowgirl_814@hotmail.com

    I suspect that's thereason general public want to read blog....Internet visitors generally create blogs to declare themselves or their secret views. Blog grant them same matter on the monitor screen what they specifically needed,so as the above stuffs declared it.

Comments have been disabled for this content.