O'Reilly Forums: C# Best Practices - O'Reilly Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

C# Best Practices What best practices do you use on C# projects?

#1 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 19 August 2010 - 08:02 AM

One of our forum members sent me a request for an excellent forum topic:

QUOTE (KClaeys @ Aug 19 2010, 08:23 AM)
This is a request to start a topic that treats "C# Best practices". I'm very interested in learning those.


I think that's a great idea. Off the top of my head, I came up with a small list of best practices that I try to use on my projects, including some of my favorite agile development practices. Here's what I came up with:

Programming
  • Using XML comments to document your code
  • Using a tool like Sandcastle to turn XML comments into HTML help (update: Sandcastle tutorial)
  • Refactoring mercilessly
  • Passing interfaces instead directly referencing concrete objects
  • Paying attention to encapsulation (like exposing IEnumerable<T> instead of specific collections like List<T> or arrays)
  • Object oriented analysis and design
  • Always using a "using" statement with IDisposable
  • Using a profiler like dotTrace to manage memory footprint or performance


Improving Code Quality
  • Using static code analysis tools like FXCop
  • Hold code reviews often (here are some code review best practices)
  • Using unit test frameworks like MSTest and NUnit
  • Doing test-driven development
  • Using integration test frameworks like FitNesse
  • Automating your build with tools like TFS build automation or Ant
  • Doing continuous integration with tools like Team Foundation Build or CruiseControl.NET


Running Projects
  • Using a version control system like TFS version control or Subversion
  • Using an issue tracking system like TFS's work item tracking or JIRA
  • Using user stories to keep track of your users' needs
  • Use a task board to track your project's progress
  • Publishing your assemblies to a dependency manager like Ivy


Another interesting take on best practices is to look at the opposite. Have a look at this previous forum post on C# worst practices and nasty bugs.

What do you guys think? Do you do any of these? What other practices can you think of? Do you have questions about any of these in particular that you want to open up to the forum?
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#2 User is offline   KClaeys 

  • New Member
  • Pip
  • Group: Members
  • Posts: 6
  • Joined: 21-June 10

Posted 19 August 2010 - 08:15 AM

I've got this blog post by Jesse Liberty, talking about comments in your code.

What do you think of this? You're using XML comments. Are these easier to maintain? What are the pro's to normal comments?
0

#3 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 19 August 2010 - 09:15 AM

QUOTE (KClaeys @ Aug 19 2010, 08:15 AM) <{POST_SNAPBACK}>
I've got this blog post by Jesse Liberty, talking about comments in your code.

What do you think of this? You're using XML comments. Are these easier to maintain? What are the pro's to normal comments?


Jesse makes great points, which is unsurprising because the guy's really sharp. I definitely agree that long, descriptive method names could help reduce the number of comments. I like the idea that choosing names that explain why and not just what a member does can make your code more maintainable, and keep you from adding comments that may "rust" with age.

I think this approach could definitely reduce the number of comments, especially inline comments. I don't think it's necessarily an either/or thing -- for example, I'll often have comments that explain how an algorithm works, and it makes my code a lot easier to maintain (especially if a team is maintaining it).

I would not abandon XML comments, however. One reason I really like XML comments in particular is that they make it very easy to create HTML documentation using tools like Sandcastle and Sandcastle Help File Builder.

Question: Have you (or anyone else) used Sandcastle? Would it be useful to see a tutorial on it? If so, I'd be happy to create one as a future blog post.


Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#4 User is offline   KClaeys 

  • New Member
  • Pip
  • Group: Members
  • Posts: 6
  • Joined: 21-June 10

Posted 19 August 2010 - 09:38 AM

QUOTE (AndrewStellman @ Aug 19 2010, 09:15 AM) <{POST_SNAPBACK}>
Question: Have you (or anyone else) used Sandcastle? Would it be useful to see a tutorial on it? If so, I'd be happy to create one as a future blog post.


I've never used it, I'd love to get a first look at it and see how I can fit it into my daily work.
0

#5 User is offline   walbaloushi 

  • Active Member
  • PipPipPipPip
  • Group: Members
  • Posts: 100
  • Joined: 25-July 09
  • Gender:Male

Posted 19 August 2010 - 02:10 PM

Excellent list of best practices. I thought it was very interesting that several of the items you mentioned are part of the Joel Test.

I do agree with you that XML comments are very helpful, especially when it comes to generating a documentation for your code using tools like Sandcastle. You can take this one step further and integrate this into your build server and have the generation of the documentation become part of the build process.
0

#6 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 20 August 2010 - 06:46 AM

Absolutely -- great point! I make that a standard practice on many of my projects.
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#7 User is offline   EderAndres 

  • New Member
  • Pip
  • Group: Members
  • Posts: 9
  • Joined: 10-November 08
  • Gender:Male
  • Location:Tunja - Boyacá - Colombia
  • Interests:C# 3.0 Programming, C# 3.0 Design Patterns, VB 9.0, Software Engineering, UI, UX

Posted 20 August 2010 - 02:39 PM

With respect to good programming practices, I think that the problem is that some developers feel that they can do whatever is possible with a programming language with only taking care of syntax errors. A programming language like C# has many powerful features that are misused, little known or bad understood by the developers. For example, there is a little confusion when overriding comparison methods and overloading operators. In this way, we have a focus of bad practices caused by using the programming language in an improper way at some degree.

Another important best practice is the use of enterprise architecture patterns in the development of .NET applications. For example, I began to read ‘.NET Domain-Driven Design with C#: Problem - Design – Solution’ by Tim McCarthy (Wrox) and I’ve read about the Layered Supertype and Repository Framework patterns which are used in the domain layer. Key terms emerge:

- The difference between Entities and Value Objects
- Application Layer Services, Domain Layer Services and Infrastructure Layer Services
- Aggregates
- Repositories
- Factories

Those terms are familiar for software architects and developers; I’m just beginning.
In conclusion, a best practice is the combination of good OOA&D and enterprise architectures supported by good programming practices and programming language knowledge.

___________________________________________________________________
Now, it’s time for two questions:

1. Do you know how to call the GetHash() method when the inner value is of type Object? Sometimes that inner Object value can be null, so it creates problems at runtime.

2. What metrics can we use for measuring the effort or work of a developer? In the past, the number of coded lines was a metric very used. However, in the present, year 2010, what new metric does exist?
Thank you.

This post has been edited by EderAndres: 20 August 2010 - 02:47 PM

0

#8 User is offline   walbaloushi 

  • Active Member
  • PipPipPipPip
  • Group: Members
  • Posts: 100
  • Joined: 25-July 09
  • Gender:Male

Posted 21 August 2010 - 01:11 PM

Another best practice that you haven't mentioned is catching specific Exceptions in a try catch block rather than relying on the base "Exception" class. Also, remember that you can have multiple catch block in a try-catch, and each can be used to handle a specific exception type.

This post has been edited by walbaloushi: 21 August 2010 - 01:16 PM

0

#9 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 21 August 2010 - 02:44 PM

QUOTE (walbaloushi @ Aug 21 2010, 01:11 PM) <{POST_SNAPBACK}>
Another best practice that you haven't mentioned is catching specific Exceptions in a try catch block rather than relying on the base "Exception" class. Also, remember that you can have multiple catch block in a try-catch, and each can be used to handle a specific exception type.


That's an excellent one. It reminds me of another really good practice: throwing a NotImplementedException as a placeholder for code you plan on filling in later. It goes really well with test-driven development, because when a test fails due to a NotImplementedException you know it's due to hitting a block of code you have yet to build, and the stack trace tells you exactly where.
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#10 User is offline   walbaloushi 

  • Active Member
  • PipPipPipPip
  • Group: Members
  • Posts: 100
  • Joined: 25-July 09
  • Gender:Male

Posted 22 August 2010 - 02:01 PM

Another one that I just though of, but that isn't specific to C# though is:

Look into using IoC containers where appropriate, and this goes really well with your recommendation of working with interfaces. If anyone isn't sure about IoC then the following blog entry might of assistance.
0

#11 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 22 August 2010 - 06:33 PM

QUOTE (EderAndres @ Aug 20 2010, 02:39 PM) <{POST_SNAPBACK}>
Now, it’s time for two questions:

1. Do you know how to call the GetHash() method when the inner value is of type Object? Sometimes that inner Object value can be null, so it creates problems at runtime.


Yes -- and implementing equality using Equals() and GetHashCode() or IEquatable<T> are definitely great C# practices (when used appropriately). Here's an example from Head First C# (page 751 -- second edition only) that shows how to implement GetHashCode() for the Guy class (my favorite general-purpose utility class example):

CODE
/// <summary>
/// Part of the contract for overriding Equals is that you need to override
/// GetHashCode() as well. It should compare the values and return true
/// if the values are equal.
/// </summary>
public override int GetHashCode() {
const int prime = 397;
int result = Age;
result = (result * prime) ^ (Name ! = null ? Name. GetHashCode() : 0) ;
result = (result * prime) ^ Cash;
return result;
}


Notice how it uses the XOR operator to build the hash code. It checks the Name property to see if it's null, and if it is it doesn't change the result by XORing it with 0. That's a pretty standard way of handling null objects when computing a hash code.

There's a little more guidance on this MSDN page: http://msdn.microsoft.com/en-us/library/ms131190.aspx

QUOTE (EderAndres @ Aug 20 2010, 02:39 PM) <{POST_SNAPBACK}>
2. What metrics can we use for measuring the effort or work of a developer? In the past, the number of coded lines was a metric very used. However, in the present, year 2010, what new metric does exist?
Thank you.


That is an excellent question! Jenny Greene and I go into some detail on the kinds of metrics that we can use to measure effort in our first book, Applied Software Project Management. I really tend to measure based on projects, and not individual developers' work, because pitting developers against each other in a battle of metrics tends to do bad things for team morale.

But in general, metrics I've gotten a lot of mileage out of include:
  • % of engineering effort per project phase: we spent 15% planning, 45% developing, 25% testing, and 15% doing deployment and documentation
  • Earned Value metrics -- especially my current favorite earned value variant, burn-down charts, which are used a lot on agile projects
  • Mean defect age



Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#12 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 04 September 2010 - 09:22 AM

QUOTE (KClaeys @ Aug 19 2010, 01:38 PM) <{POST_SNAPBACK}>
QUOTE (AndrewStellman @ Aug 19 2010, 09:15 AM) <{POST_SNAPBACK}>
Question: Have you (or anyone else) used Sandcastle? Would it be useful to see a tutorial on it? If so, I'd be happy to create one as a future blog post.


I've never used it, I'd love to get a first look at it and see how I can fit it into my daily work.


I just posted a tutorial on creating C# API documentation with Sandcastle. It's definitely a really useful practice!
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#13 User is offline   PiterKhasak 

  • New Member
  • Pip
  • Group: Members
  • Posts: 2
  • Joined: 26-August 10

Posted 06 September 2010 - 08:23 AM

I have question on C# Best Practices. I raise events so:

CODE
class Plane
{
public event EventHandler Land;

protected void OnLand()
{
if ( null != Land )
{
Land( this, null );
}
}
}


I am tlod it is event handler best practice to do instead:

CODE
EventHandler temp = Land;
if ( null != temp )
{
temp( this, null );
}


Is that truly necessary? In what case could temp be different from Land?

PK
0

#14 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 623
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 08 September 2010 - 07:08 AM

QUOTE (PiterKhasak @ Sep 6 2010, 12:23 PM) <{POST_SNAPBACK}>
I am tlod it is event handler best practice to do instead:

CODE
EventHandler temp = Land;
if ( null != temp )
{
temp( this, null );
}


Is that truly necessary? In what case could temp be different from Land?


The person who told you to use that temporary variable was right -- that is a good practice for raising an event or using a delegate.

It does seem odd, right? How could it possibly make a difference whether or not you assign the value to a temporary variable?

The reason is that if you try to raise an event or use a delegate if it's null, it throws a NullPointerException. If your code is in a multithreaded application, then there is a very small possibility that the event could have a handler attached to it when you check if it's null, but could actually be set to null on another thread before the next statement is executed.

This is an example of a race condition. If you haven't done much multithreaded programming before, this is a good example of how code that seems perfectly innocuous in a single-threaded environment can be unpredictable in a multithreaded program.

I'll give this some thought and see if I can come up with some code to demonstrate this.

In the meantime, you can learn more about race conditions and how to prevent them on the MSDN Managed Threading Best Practices page.

Also, BackgroundWorker is an easier way to create multithreaded programs in a way that avoids a lot of pitfalls. You can check out leftover #3 in the Head First C# appendix -- or, if you're using the first edition, you can have a look at my BackgroundWorker tutorial.

Update: I thought this would make a really good blog post, so I wrote a new post on raising events in C# using temporary variables. It gives a lot of detail about exactly why you need the temporary variable, including an example of a program that breaks if you don't use it.

This post has been edited by AndrewStellman: 09 September 2010 - 07:38 PM
Reason for edit: Added a link to my blog post about this

Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#15 User is offline   kamlarastogi 

  • New Member
  • Pip
  • Group: Members
  • Posts: 1
  • Joined: 29-March 13

Posted 29 March 2013 - 05:19 AM

Very very Thanks AndrewStellman

I am just beginner in C# so your posting is very helpful to me. Hope you'll continuously post about c#.

Kamla Rastogi
Software Company Lucknow
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users