What is a standard? The term is used in this book to mean "a way of doing things that is agreed to by all (this is very important) and that is generally regarded as a best practice within the industry." An important part of this working definition is that the entire team needs to buy in to whatever standards are set down. It is confusing and ineffective if only a few developers conform to the team standards and the remainder bail out with excuses such as "It will slow me down" or "We were close to the deadline, so I have to get this code into the build." If the whole team doesn't conform voluntarily, the senior developers, or even management, need to step in and enforce standards for the good of the project. Standards are much like a "pay me now or pay me later" proposition, and, as often happens, the "later" is much more expensive. I have seen projects in which a few hours spent on inspections would have avoided multiple builds caused by simple errors found in QA testing.
The other part of the definition I need to mention is best practice. Not only does a team need to hold its own members to the agreed-on standards, but also the standards themselves should be based on generally agreed-on best practices. Otherwise, the standards could be followed, but still result in inferior or hard-to-debug code. It's better to be the fourth-best team in the country instead of the first-best team in West Nowhere, Montana (apologies to Montana). The following sections explain the types of standards outlined in the Microsoft exam guidelines. Documentation StandardsMinimum standards for solution documentation are important. A standard format for headers and footers, revision tracking, and use of styles, for example, can make documents easier to read down the road.
If most of the team uses Microsoft Word for the documentation, but one member includes all her documentation as code comments and another team member uses shareware word processing software from his home PC, recovering all the design documentation will be difficult a year from now. Reviews for key documents (such as design documentation) should also be considered. Remember to document "why," not just "what" you did. Often, decisions made earlier in the cycle get called into question because no one can recall why the decision went the direction it did. Rethinking decisions can cause extra work or, even worse, can cause teams to go back and get caught by a bullet they already dodged earlier. Coding StandardsAlthough detailed coverage of coding standards could be quite lengthy, I have focused on moving efficiently through the highlights of the Microsoft coding standards that you might expect to see on the exam. As Microsoft itself points out, rules were made to be broken. These coding guidelines are in place to make sure developers break them for a valid reason, not just because they are in a hurry. I usually suggest that any time a team breaks a standard for a valid reason, the developer should document the reason in the code so that the team doesn't have to rely on memory during later inspections of the code.
Naming GuidelinesTwo main capitalization styles are recommended: Pascal case and camel case. Pascal case capitalizes the first letter of each word, including the first, as in "PascalCase." Camel case capitalizes the first letter of every word except the first, as in "camelCase"a style that might be more familiar to C or Java programmers. Microsoft has laid out specific recommendations for the use of each style. Again, what you do on your own team is not as important as the entire team agreeing on a style. However, for the exam, I would suggest remembering the following standards. Use Pascal case for the following:
Use camel case for the following:
For the most part, if it is exposed as part of the public interface, use Pascal case. Do not create methods, properties, class names, or parameters that differ only by case. Although this method works in C#, it is difficult and confusing to maintain. It does not work in Visual Basic .NET at all. Follow this simple rule for abbreviations: Don't use them, or at least use them rarely. Only widely accepted abbreviations should be used (for example, HTML, ODBC). Avoid using abbreviations such as "Cd" for code or "Nbr" for number. With the "auto-complete" feature of the Integrated Development Environment (IDE), longer names are not the issue they were in the old days. As they say in football, go long. Avoid creating your own class names or method names that conflict with keywords in the language. For example, avoid using names such as "System" or "Collection." Try to name classes by using a noun (or noun phrase) for the class name. No underscores or Hungarian notation, please.
When naming methods, use the VerbNoun format. In other words, use ClearGrid instead of GridClear. Better yet, use a more generic name, Clear, to set the stage for inheritance and polymorphism. Names should be meaningful within the context of the solution. For example, GetPersonCount is a more meaningful name than GetCounterValue. Likewise, UpdateUsers is more meaningful than Go. When naming event handlers, use the suffix EventHandler. Class Member Usage GuidelinesWhen naming properties, try to use nouns or noun phrases. You should be able to set properties in any order, in relation to other properties. Be sure you know when to use a method instead of a property. If the order of execution is important, if successive calls would return different results, if you are returning an array, or if the operation is expensive, consider making it a method call. Use read-only properties if the user cannot change the data behind the property. Avoid write-only properties. For methods, consider overloading when you would have used optional parameters or default arguments in the past. When overloading, keep the order of the parameters consistent. Extend the parameters to the right, but attempt to keep reoccurring parameters in the same location. Also, try to keep methods to a page of code or less. Avoid constructors that do a lot of work. Use parameters in constructors as shortcuts for setting parameters. These two guidelines are new in the .NET world:
One final guideline that Microsoft recommends is checking each parameter value for validity, throwing exceptions where necessary. This is known as defensive programming, and although it's more expensive in terms of performance, it leads to fewer runtime errors because more errors are caught during testing. Type Usage GuidelinesMicrosoft's definition of a type is a class, a variable, or an interface. Microsoft recommends using classes over interfaces in the .NET platform. Classes can contain implementation code, and this implementation can be inherited and extended. Interfaces, on the other hand, require all implementation to be created. Interfaces do not support implementation inheritance. If you do create interfaces, the common practice is to precede them with an uppercase I (for example, IPerson). For types that are primarily containers for primitive data types and have no logic, Microsoft recommends using the struct type (Structure in Visual Basic .NET). Enums are recommended as a way to strongly type parameters (versus static constants). Guidelines for Exposing Functionality to COM.NET was developed to interoperate with COM. For classes that will be consumed by COM, use the ComVisible() attribute. Be aware of when you want your object to be marshaled by value (serialized) or marshaled by reference (proxies). Error Raising and Handling GuidelinesTry to use the predefined exception types when possible. When creating new exception classes, developers should always inherit from ApplicationException, not SystemException. Do not use exceptions to catch normal or expected exceptions or to influence flow control. Exceptions should be focused on unexpected errors. Throwing exceptions is recommended over returning an error code (as in old application programming interface [API]style exception handling). For performance reasons, choose your exception "throwing" strategy carefully. Remember that .NET will "bubble up" an exception until it finds a handler (a Catch statement). Briefly, this means the .NET Framework will continue to trace backward through the call stack until it finds a "Catch" error trap or until it reaches the beginning of the application, in which case it will throw its own error. Your code should be designed so that this never happens. Array Usage GuidelinesUse a collection instead of an array when Add or Remove methods are supported. Conversely, do not support "collection-like" features, such as Add, Remove, Item, or Count methods for non-collection types. Never return Null from a Collection or Array property. Return an empty collection (or array) instead. Finally, use collections when it will prevent the calling code from having to scan the entire structure looking for a value. Operator Overloading Usage GuidelinesConfine yourself to the conventions outlined in the Common Language Specification (CLS). Remember, Visual Basic .NET does not support operator overloading (at this time). Guidelines for Implementing Equals and the Equality OperatorSee Microsoft's documentation for this design specification on implementing equals and the equality operator. The guidelines are complex, related to operator overloading, and this specification is unlikely to be on the exam. Guidelines for Casting TypesDo not lose precision in implicit casts. Do not throw exceptions from implicit castsit is difficult for the developer to interpret what went wrong.
Common Design PatternsMicrosoft recommends a few basic patterns, described in the following sections. The Finalize and Dispose PatternBecause of the difference between COM's instance count and .NET's garbage collection, releasing object or resource references in a more predictable way might be necessary. This topic normally consumes an entire chapter in an average book, but suffice it to say that you can use the Finalize method for implicit, but indeterminate, cleanup, or you can use the IDisposable interface and the accompanying Dispose method so that your object's client code can force a cleanup of resources. Just make sure to call the SuppressFinalize property if your Dispose method is called. In general, code in the Finalize method is considered suboptimal from a performance standpoint. The Equals PatternThe Equals method is used to see if two "objects" are the same. Sometimes, this might mean they have the same "value." In other instances, it might mean they point to the same address (object). The Equals method is one you will likely override with your own code if your goal is different from the built-in behavior.
The Callback PatternUse events instead of callbacks if the calling code "signs up" for notification in advance or if there are multiple objects consuming the method. Another option is to use Delegate. The Timeout PatternAllow the calling code to specify the maximum time it will wait for a response (for either synchronous or asynchronous calls) with a property setting or an extra parameter in the method signature.
If your favorite pattern wasn't listed, fear not. It is probably somewhere on the MSDN site, or soon will be. See the Note box in this section for a few links. Other well-known patterns throughout the industry, such as Factory, Singleton, and Observer, can be found in the MSDN Library under .NET Development > Building Distributed Applications with .NET > Architectural Topics. Security in Class LibrariesClasses that need to be secure cannot assume that whoever calls them has permission to do whatever they request. There are two dimensions to class security:
Threading Design GuidelinesStatic state must be thread safe. Design away from the need for thread synchronization, if at all possible. Use the lock statement with care and as infrequently as possible. Guidelines for Asynchronous ProgrammingAsynchronous programming is much more prevalent (and easier) in the .NET arena than it was in the "classic" days. With much more emphasis on Web applications, disconnected data sets, and .NET Remoting, using asynchronous programming is one way to improve the solution's performance, as perceived by the user. On the MSDN Web site, Microsoft has included sample code, treating asynchronous programming as an additional design pattern. I won't go into the details, beyond stating that asynchronous programming is often a good way to improve scalability. Give users just enough to satisfy their immediate needs and go get the rest behind the scenes. Well, that was the lightning tour through coding standardsit's time to move on to other standards. Code Review StandardsCode reviews, part of any best-practices development methodology, are done so that others can search your code for logic defects, adherence to standards, and readability. The most straightforward approach is printing out or distributing the code to be inspected in advance, scheduling the review with at least one other person (usually more) on the team, and inspecting the code, often line by line. Many teams use a checklist reflecting their agreed-on standards, and an issues log is often used to track items found during the inspection and ensure that they are resolved before going forward. Until each item on this log has been resolved, the review is not considered "signed off on." As mentioned before, any variance from standards should be documented.
FxCopOne last side topic is an automated tool for reviewing code against the Microsoft published standards: FxCop. You can download FxCop free from the GotDotNet Web site at http://www.gotdotnet.com/team/libraries/. It runs against compiled assemblies (DLLs, EXEs) and looks for anything that does not conform to the Microsoft published ".NET Framework Design Guidelines." As you can see in Figure 11.1, FxCop sweeps the code and flags any areas that are not in compliance. Although not a substitute for human inspection, it works well as a first-pass review so that the actual code review goes much more quickly. For each violation, you can get details (see Figure 11.2). Of course, I had to go back into my code and manufacture these errors for purposes of demonstration. Figure 11.1. Screenshot of FxCop results.Figure 11.2. Details of a specific standards violation.User Interface StandardsIf coding standards were difficult to cover in just a few pages, UI standards are downright impossible. First, there is a difference between the standards your team would enforce in a Web application and those for a Windows Forms solution. There should be some sort of document that lays out standards for the team, even down to which font and color scheme (important for corporate identity) should be used and how user prompts should be displayed (for example, "This is not a valid value for the Zip Code field. Please use the 9-digit xxxxx-yyyy format, in which all numbers are numeric."). These are a few areas that you might want to consider when constructing your User Interface Standards document:
Another tactic now available because of the .NET Framework is using inheritance to enforce UI standards. Because everything in .NET is a class, even WinForms and WebForms, your team can create a base form with the aspects that must exist in all forms (color scheme, buttons, logos, methods, and so forth), and then all forms in the application can inherit from that customized base rather than from the .NET Base Class Library. Testing StandardsThe various levels of testing should be included in any process standards you establish. Although testing is discussed later in this chapter in "Testing Processes," I suggest the following standards, based on research from people who do this for a living:
Now that you have looked at what standards you might consider, you can move on to everyone's favorite topicprocesses. |