Book Image

Visual Studio 2010 Best Practices

By : Peter Ritchie
Book Image

Visual Studio 2010 Best Practices

By: Peter Ritchie

Overview of this book

When you are developing on the Microsoft platform, Visual Studio 2010 offers you a range of powerful tools and makes the whole process easier and faster. After learning it, if you are think that you can sit back and relax, you cannot be further away from truth. To beat the crowd, you need to be better than others, learn tips and tricks that other don't know yet. This book is a compilation of the best practices of programming with Visual Studio. Visual Studio 2010 best practices will take you through the practices that you need to master programming with .NET Framework. The book goes on to detail several practices involving many aspects of software development with Visual Studio. These practices include debugging and exception handling and design. It details building and maintaining a recommended practices library and the criteria by which to document recommended practices The book begins with practices on source code control (SCC). It includes different types of SCC and discusses how to choose them based on different scenarios. Advanced syntax in C# is then covered with practices covering generics, iterator methods, lambdas, and closures. The next set of practices focus on deployment as well as creating MSI deployments with Windows Installer XML (WiX)óincluding Windows applications and services. The book then takes you through practices for developing with WCF and Web Service. The software development lifecycle is completed with practices on testing like project structure, naming, and the different types of automated tests. Topics like test coverage, continuous testing and deployment, and mocking are included. Although this book uses Visual Studio as example, you can use these practices with any IDE.
Table of Contents (16 chapters)
Visual Studio 2010 Best Practices
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface

Beyond practices


Some methodologies from other disciplines have recently begun to be re-used in the software industry. Some of that has come from lean manufacturing, such as kaizen, and some from the martial arts, such as katas. Let's have a brief look at using these two methodologies.

Using katas

In the martial arts, students perform what are known as katas. These are essentially choreographed movements that the student is to master. Students master these katas through repetition or practice. Depending on the type of martial art, students move through dan grades through judgment of how well they can perform certain katas.

The principle behind kata is the muscle memory. As students become proficient in each kata the movements become second nature to them, and they can be performed without thought. The idea is that in battle the muscle memory gained from the katas would become reflexive and they would be more successful.

In the software development communities, kata-like sessions have become common. Developers take on specific tasks to be done in software. One way is to learn how to do that task, another is to repeat it as a way of remembering how to implement that specific algorithm or technique. The theory is that once you've done it at least once you've got "muscle memory" for that particular task. Worst-case is that you now have experience in that particular task.

"Kata" suffers slightly from the same syndrome as "best practice", in that "kata" isn't necessarily the most appropriate term for what is described previously. Getting better at a practice through repeated implementation results in working code. Kata is repeating movement not necessarily so the movement will be repeated in combat/competition, but so that your mind and body have experience with many moves that it will better react when needed. Software katas could be better viewed as kumites ("sparring" with code resulting in specific outcomes) or kihons (performing atomic movements like punches or kicks). But this is what coding katas have come to signify based on a rudimentary understanding of "kata" and the coding exercises being applied.

At one level, you can view practices as katas. You can implement them as is, repeating them to improve proficiency and experience, the more you practice. At another level, you could consider these practices as a part, or start, of your library of practices.

Reaching kaizen

In the past few years, there has been much in the way of process improvement in the software industry that has been taken from Japanese business and social practices. Much like kata, kaizen is another adopted word in some circles of software development. Originally borrowed from the lean manufacturing principles, lean manufacturing was originally attributed to Toyota. Kaizen, in Japanese means "improvement."

This book does not attempt to document a series of recipes, but rather a series of starting points for improvement. Each practice is simply one way of eliminating waste. At the most shallow-level, each practice illuminates the waste of trying to find a way to produce the same results as the detailed practice. In the spirit of kaizen, think of each practice as a starting point. A starting point not only to improve yourself and your knowledge, but to improve the practice as well.

Once you're comfortable with practices and have a few under your belt, you should be able to start recognizing practices in some of the libraries or frameworks you're using or developing. If you're on a development team that has its own framework or library, consider sharing what you've learned about the library in a series of recommended practices.

How would you start with something like this? Well, recommended practices are based on people's experience, so start with your experiences with a given framework or library. If you've got some experience with a given library, you've probably noticed certain things you've had to do repeatedly. As you've repeated doing certain tasks, you've probably built up certain ways of doing it that are more correct than others. It has evolved over time to get better. Start with documenting what you've learned, and how that has resulted in something that you'd be willing to recommend to someone else as a way of accomplishing a certain task.

It's one thing to accept practices to allow you to focus on the value-added of the project you're working on. It's another to build on that knowledge and build libraries of practices, improving, organizing, and potentially sharing practices.

Aspects of a practice

At one level, a practice can simply be a recipe. This is often acceptable, "Just Do It" this way. Sometimes it might not be obvious why a practice is implemented in a certain way. Including motivators or the impetus behind why the practice is the way it is can be helpful not only to people learning the practice, but also to people already skilled in that area of technology. People with skills can then open a dialog to provide feedback and begin collaborating on evolving practices.

Okay, but really, what is a "best practice?" Wikipedia defines it as:

"...a method or technique that has consistently shown results superior to those achieved with other means...".

The only flaw in this definition is when there's only one way to achieve certain results, it can't still be "best" without being compared to some other means. "...method or technique" leaves it pretty open to interpretation on whether something could be construed as a best practice. If we take these basic truths, and expand on them, we can derive a way to communicate recommended practices.

The technique or method is pretty straightforward (although ambiguous to a certain degree). That really just distills down to a procedure or a list of steps. This is great if we want to perform or implement the practice, but, what do we need to communicate the procedure, intent, impetus, and context?

Evaluating practices

I could have easily jumped into using practices first, but, one of the points I'm trying to get across here is the contextual nature of practices whether they're referred to as "best practices" or not. I think it's important to put some sort of thought into the use of a practice before using it. So, let's look at evaluation first.

Once we define a practice we need a way for others to evaluate it. In order to evaluate practices, an ability to browse or discover them is needed.

In order for someone else to evaluate one of our practices, we need to provide the expected context. This will allow them to compare their context with the expected context to decide if the practice is even applicable.

In order for us to evaluate the applicability of another process, we need to know our context. This is an important point that almost everyone misses when accepting "best practices." The "best" implies there's no need for evaluation, it's "best", right? Once you can define what your context means you can better evaluate whether the practice is right for you, whether it can still be used but with a little evolution, or simply isn't right for you.

Documenting practices

Documenting a practice is an attempt at communicating that practice. To a certain degree, written or diagrammatic documentation suffers from an impedance mismatch. We simply don't have the same flexibility in those types of communication that we do in face-to-face or spoken communication. The practice isn't just about the steps involved or the required result, it's about the context in which it should be used.

I have yet to find a "standard" way to documenting practices. We can pull some of what we've learned from patterns and devise a more acceptable way of communicating practices. We must first start out with the context in which the practice is intended to be used, or the context in which the required outcome applies.

Scott Ambler provides some criteria for providing context about teams that can help a team evaluate or define their context. These factors are part of what Ambler calls Agile Scaling Model (ASM). The model is clearly agile-slanted, but many of the factors apply to any team. These factors are discussed next.

Geographic distribution

This involves the distribution of the team. Is the team co-located or are they distributed over some geographic location? This distribution could be as small as cubes separated by other teams, team members separated by floors, team members in different buildings, cities, or countries and time zones. A practice that assumes the context is a co-located team might be more difficult to implement with a globally-distributed team. Scrum stand-ups is an example. Scrum stand-ups are very short meetings, held usually once a day, where everyone on the team participates to communicate what they have worked on, what they are working on, and any roadblocks. Clearly, it would be hard to do a "stand up" with a team geographically distributed across ten time zones.

Team size

Team size is fairly obvious and can be related to geographic distribution (smaller teams are less likely to be very geographically distributed). Although different from geographic distribution, similar contextual issues arise.

Regulatory compliance

Many companies are burdened with complying with regulatory mandates. Public companies in the United States, for example, need to abide by Sarbanes-Oxley. This basically defines reporting, auditing, and responsibilities an organization must implement. Applicability of practices involving audit or reporting of data, transactions, customer information, and so on, may be impacted by such regulations.

Domain complexity

Domain complexity involves the complexity of a problem the software is trying to solve. If the problem domain is simple, certain best practices might not be applicable. A calculator application, for example, may not need to employ domain-driven design (DDD) because the extra overhead to manage domain complexity may be more complex than the domain itself. Whereas a domain to manage an insurance domain may be so complex that using DDD will have partitioned the domain complexity and would make it easier to manage and understand.

Organizational distribution

Similar to team distribution, organizational distribution relates to the geographic distribution of the entire organization. Your team may be co-located but the actual organization may be global. An example of where a globally-distributed company may impact the viability of a practice could be the location of the IT department. If a particular practice involves drastically changing or adding to IT infrastructure, the friction or push back to implementing this practice may outweigh the benefit.

Technical complexity

Technical complexity can be related to domain complexity, but really involves the actual technical implementation of the system. Simple domain complexity could be implemented in a distributed environment using multiple subsystems and systems, some of which could be legacy systems. While the domain may be simple, the technical complexity is high. For example, practices involving managing a legacy system or code would not be applicable in a greenfield project where there are yet to be any legacy systems or code.

Organizational complexity

Organizational complexity can be related to organizational distribution but is generally independent. It's independent for our purposes of evaluating a practice. For example, in a complex organization with double-digit management levels, it may be easier to re-use hardware than it is to purchase new hardware. Practices that involve partitioning work amongst multiple systems (scaling out) may be more applicable than best practices that involve scaling up.

Enterprise discipline

Some enterprises have teams that drive their own discipline, and some enterprises have consistent discipline across the enterprise, not just the software development effort. Practices that are grounded in engineering disciplines may be easier to implement in enterprises that are already very disciplined.

Life-cycle scope

Some projects span a larger life cycle than others. Enterprise applications, for example, often span from conception to IT delivery and maintenance. Practices that are geared towards an off-the-shelf model of delivery (where deployment and maintenance is done by the customer) and ignore the enterprise-specific aspects of the project, may be counterproductive in a full life-cycle scope.

Paradigm

Finally, when attempting to evaluate practices, the development paradigm involved should be taken into account. For example, on an agile project, best practices around "waterfall" paradigms may not be applicable.

Regardless of the team factor, it's important to not discount practices just because factors may be different or opposite. Just because the context is different doesn't mean that the practice is completely incompatible.

One way of viewing a context is as a requirement. There are various practices for eliciting, documenting, and engineering requirements that we can inspire our method of documenting the context. Practices are a behavior, or an action. Behavior-driven design (BDD), although completely orthogonal to documenting the context of a practice, builds on the fact that users of software use the software's behavior. In order to better describe their requirements so that the correct behavior can be discovered, the concept of "specifications" is used.

Specifications in BDD are a more flexible way of specifying requirements. One form of documenting these specifications is using the Gherkin syntax. This syntax is basically Given X [and X2] When Y [and Y2] Then Z [and Z2]. Building on that type of syntax, we can simply re-use Given to document our context.

For example, with the canonical source code control example, we could document our context as follows:

Given a multi-person, collaborative, software project
And the software evolves over time
And may change concurrently for different reasons
When making changes to source code
Then use an off-the-shelf source code control system

But, there's no reason why you should limit yourself to re-using existing documentation semantics. If something is clearer to read and easier to follow, use that method.

Categorization

There is not much documented on categorizing practices. For the most part, this can be fairly obvious. We could have procedural practices (using source code control), design practices (employing authentication to ensure correct access to private data), and so on.

Starting out, building a practices library may not need much, if any, of categorization. As you build on your skill set, and increase your knowledge and experience with more practices, you may find that certain degrees of categorization for you and your team may be necessary. It's one thing to have your own knowledge and experience with practices, but if you're trying to mentor a team and help the team improve as a whole, then categorization can begin to prove its worth.

This is another area which we can draw upon how structured patterns have become in their proliferation and dissemination. Patterns too have somewhat ambiguous recommendations for categorization, but to build on something already in place requires less reinvention, learning, and a broader audience.

Although categorization is useful for organizing practices, you might also want to consider aggregating certain practices into one practice, and detailing the different steps involved in the different contexts. Performing lengthy operations on a background thread, for example, has many different contexts, and each context may have a specific way of implementing the practice (WPF, WinForm, WCF, and so on).

Just because we use the term "category" doesn't mean membership in this category is mutually exclusive.

Patterns are generally pre-categorized as "design," but some categories are often used to group patterns. These categories are discussed next.

Creational

Patterns that apply to the creation of objects. Probably not something you'd normally classify a practice under.

Structural

Structural patterns are patterns involving specific ways to design or manage relationships between classes, objects, or components in a code. Could be used as a subcategory of architecture practices.

Behavioral

Technically, this category involves patterns that relate to designing how classes, objects, or components communicate between one another, but it depends on your interpretation of "behavioral." Stands well enough alone.

Integration

Practices involving integration of systems or subsystems.

Procedural

These are generally business procedures. While most of what this book discusses is not business procedures, there are some really good business practices in the software development industry that I'd recommend, for example, agile practices.

Anti-patterns

There's much written on ways not to write software. We could go out on a limb and do the same thing with practices. But, for the most part, there aren't anti-practices. Almost all practices should be considered useful. It's mere context that defines where the practices are useful. I wouldn't suggest building a category of anti-practices as much as spending time improving how contexts are described in practices. However, would include invalid contexts (contexts where the practice is not recommended) when documenting the context of a given practice.

Practices are generally less focused than patterns so their categories can include various other categories, such as:

  • Security: Practices involving improving or retaining security of data could be grouped here. This can be topics like authentication, authorization, encryption, and so on.

  • Architectural: This always ends up being a broad and subjective category, and can end up being a catch-all for practices that just don't fit anywhere else. However, we can use this category to subcategorize other categories. For example, a practice may be tagged as security and architectural, for example, a practice to keep private data within its own database and on a separate server.

  • Quality: To a certain extent all practices have something to do with quality. The mere use of a practice implies that someone else has implemented and worked out all of the kinks, just improving the quality of your software over having to invent the practice yourself. However, some practices are specifically geared towards improving the quality of your software. The practices of using unit tests or using test-driven design (TDD), for example, are practices specifically geared at helping improve quality.

  • User experience: I'm sure on any given day you can find dozens and dozens of practices around user interface (UI) design, user experience (UX) design, and so on. There are lots of UX practices out there. An example of such a practice relating more about software design than UI design could be: perform lengthy operations on a background thread.

  • Application health: This category deals with the dissemination and reporting of application or system health. In simple applications, this may deal with informing the user of errors, warnings, and so on. These are fairly simple practices that can often be covered under UX. In larger, more complex, distributed systems, or systems with components without a UI, it's vital that problems with the system, such as being able to perform its intended tasks (health), be communicated outside of the system. For example, given a Windows service when errors are encountered then log the error to Windows Event Log.

  • Performance: Performance practices are a bit tricky because performance improvements are always something that need to be observed and evaluated, for example, premature optimizations. But there are some practices that programmers can use that are known to be faster than other types of implementations. Picking the fastest algorithm for a given situation (context) is never a premature optimization.

  • Scalability: Practices involving the ability for a system to scale, either horizontally (out) or vertically (up) can be categorized as scalability practices. Examples of such practices may involve things like breaking work into individual tasks that can be executed concurrently, or employing the use of messaging.

  • Language: Some practices can get down to a much lower-level, such as the language level. Practices about using language features in a specific way could be categorized here, for example, avoiding closures within loops. Many such practices in this category can be monitored and/or evaluated through static code analysis. Tools such as Visual Studio Code Analysis can be used to monitor compliance with such practices.

  • Deployment: Deploying systems and applications in and of itself can have many practices. There are many tools that basically implement these practices for you, but some complex situations require their own practices relating to deployment, for example, preferring WiX over Visual Studio deployment projects.

In this book

For the purposes of this book, I'll keep it simple. Practices in this book will be documented as follows:

Context: In the context of X.

Practice: Consider/do Y.

Context details the situation in which practice should apply.

Evolving practices—a collaborative effort

We don't really want to reinvent the wheel, and neither do most other people. But, as we create, communicate, and evolve practices we often begin a dialog. We interact with people on practices involving frameworks and libraries that they also have had experience with. Their experiences may have been different than yours. Collaborate with team or community members to evolve and improve practices so that other, less-skilled people can write software concentrating on the value to be added quicker, and with higher quality.