views:

1004

answers:

8

I enjoy and highly recommend Juval Lowy's - C# Coding Standard. Juval explicitly avoids rationale for each directive in order to keep the standard tight (see the preface). However, there are a few directives for which I find myself curious as to the rationale.

What is the specific rationale to the following directives from Lowy's C# standard?
Hopefully there are hard (non-subjective) answers to these.

1.13 Avoid fully qualified type names. Use the "using" statement instead.
Is this a performance issue? Sometimes I only need one instance of the fully qualified name and adding a using seems heavy.

1.26 Use empty parenthesis on parameterless-anonymous methods. Omit the parenthesis only if the anonymous method could have been used on any delegate.
Actually I am just confused by the second sentence. Explanation with example(s) would help, thank you.

2.19 Avoid defining custom exception classes
What are the considerations in minimizing their numbers? (He next gives guidelines if you do define them (in 2.20).)

2.29 Avoid using the ternary conditional operator
Too hard for the reader to digest, or other considerations?

2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.
I don't think I do this, but I am curious...why not?

2.47 Avoid interfaces with one member.
Because it is always/usually more prefereable to do what? One method interfaces work when?

2.53 Prefer using explicit interface implementation
Why? Also, Jon Skeet disagrees here.

Thanks in advance! Robert

A: 

Here are some respones:

1.13 - Probably just for the sake of readability.

2.19 - Often times there is an existing exception that will work fine (especially ArgumentException). If not - then by all means create your own.

2.29 - I personally disagree, but I think the justification is that some programmers don't really understand this. Like ++i vs i++, or ref/out parameters. Again - I personally disagree.

Jon B
+3  A: 

This is my best stab at the questions you've listed. For the ones that I can't really say, I've omitted.

1.13 Avoid fully qualified type names. Use the "using" statement instead.

Readability. It's must harder to read code when you have to read fully qualified type names.

2.19 Avoid defining custom exception classes

The .NET framework comes with a good set of exceptions built into the system. Unless the exception you're modeling is business domain specific, you'll probably be able to use one of the existing exception classes.

2.29 Avoid using the ternary conditional operator

I think this is most likely because he thinks people may not understand the operator, but I disagree.

2.47 Avoid interfaces with one member.

He might be warning people of building interfaces that are too thin. However, I would actual say the converse, warning people of making interfaces too verbose. If you've ever had to deal with ASP.NET MembershipProvider, you know what I'm talking about.

2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.

A couple of reasons I can think of here. Readability. It can make conditional statements hard to understand if you are making function calls in them. Also, it's harder to debug if you're not watching.

2.53 Prefer using explicit interface implementation

I believe his reasoning here is to for brevity. However, I don't actually agree with this assessment. I think Jon is correct, implicit interface should be used when you can, and explicit when appropriate.

Joseph
1.13 - Sometimes I find the fully qualified name useful because I wasn't sure where that method lived and now I don't have to stop reading just to look it up. Assuming it isn't overdone.
Robert Lamb
@Robert That can be true at times, but I think those are Exception and not the Rule.
Joseph
+1  A: 

Here are some of my reactions of which I dare answer them :)

1.13 Avoid fully qualified type names. Use the "using" statement instead. I disagree. It's certainly not performance related. It can lead to improved readability to have var foo = new Foo() instead var foo = new MyCompany.MyNamespace.Helpers.Xml.Foo() but other than that - no.

2.19 Avoid defining custom exception classes This is nonsense imho. You should avoid creating custom exceptions that derive from ApplicationException, but there is nothing wrong with custom exceptions (as long as you're not going to reinvent existing exceptions that is).

2.29 Avoid using the ternary conditional operator I have no idea why that would be a guideline. I have read that not all people use it and may not recognize it, but that is not a valid reason to not use a useful operator.

2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them. This is simply a readability issue in my opinion.

2.47 Avoid interfaces with one member. I also disagree here. You should avoid 'marker' interfaces though - interfaces with no marker, but who just serve the purpose that something is '...ble'. But, one method on an interface seems fine to me.

Razzie
Agree on 2.19: guidance should be: avoid reinventing framework exception classes.
Richard
+3  A: 

1.26 is about pre-lambda delegate { } syntax.

// #1 Empty parenthesis on parameterless-anonymous methods would be:
delegate() { }
// #2 ... anonymous method could have been used on any delegate, is:
delegate { }

Remember, the latter can be assigned to any delegate, regardless of its parameters. The delegate just ignores these using some compiler trickery.

If you define a delegate taking no parameters, explicitly say so using #1. Don't "leave the parenthesis out because your delegate doesn't take any parameters anyway".

Jabe
+2  A: 

A lot of these guidelines speak to the "quality attributes" of good software design (i.e. maintainability, reliability, reusability, testability, expandability, debugability, interoperability, and what other -ilities you can name).

Often people create code that works fine at the time but may not be the best choice when considering all the quality attributes (in the sense of "where can this software go in the future" or "someone else has to use this code, too").

For example:

2.29 Avoid using the ternary conditional operator

I have no problem with ternary expressions, per se, but by writing code such as: int result = CheckMethod() ? OnTrueDoThis() : OnFalseDoThat()... you are saying, "I have a conditional that, if true (or false), you can do one and only one thing." The whole construct discourages expandability. You have to recreate the construct (with an if..else statement).

Similarly...

2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.

You called a function and essentially "discarded" the results for later use. If that information is needed later, either the function would have to be called again or the structure of the code would have to be rewritten. It would also make checking or logging the results (for future debugging) more difficult.

Enjoy,

Robert C. Cartaino

Robert Cartaino
2.29: The conditional operator is easy to misuse, but sometimes convenient. I wouldn't hesitate to use it where appropriate. 2.31: The rationale you gave looks like a classic case for applying YAGNI.
David Thornley
+1  A: 

Obviously, I'm not Juval, but I can take a stab at these

1.13 Avoid fully qualified type names. Use the "using" statement instead.

Performance can't be the issue here. I'm sure the issue is readability.

1.26 Use empty parenthesis on parameterless-anonymous methods. Omit the parenthesis only if the anonymous method could have been used on any delegate.

public delegate void Foo1();
public delegate void Foo2(int val);

public void Foo()
{
    Foo1 first = delegate { Console.WriteLine("Hello world"); };
    Foo2 second = delegate { Console.WriteLine("Hello world"); };
    Foo1 third = delegate() { Console.WriteLine("Hello world"); };
    Foo2 fourth = delegate() { Console.WriteLine("Hello world"); }; // does not compile
}

Without the parens, the anonymous delegate can be applied to any delegate. With the parens, you're being specific about the signature of the delegate. Prefer the second syntax unless you really need the flexibility.

2.19 Avoid defining custom exception classes

Again, readability is the issue here. The framework exception classes are rich and well-understood. Be wary when replacing them.

2.29 Avoid using the ternary conditional operator

It's a readability and expandability thing. I don't really agree, but it's a standard religious fight.

2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.

Partially this is readability, and partially it's for ease of debugging. I've starting to assign almost everything to temporary variables just so that they're easily found in the debugger later on.

2.47 Avoid interfaces with one member.

"Avoid" is kinda like "prefer", he's just saying think twice before you do it. If you only have one member, is the interface really modeling something useful and complete in your design? It's pretty rare to have a class with just one member, think seriously about why your interface is any different.

2.53 Prefer using explicit interface implementation

This is similar to the idea of using the least-public accessor you can. If your class doesn't need to make the interface public, then it probably shouldn't. This is going to differ significantly based on your design, obviously, but given the fact that most people just make the interface implicit without really thinking about it, it's advice worth considering.

tnyfst
+5  A: 

2.29 Avoid using the ternary conditional operator I have no problems with "simple" uses of the ternary operator but have recommended against using it in a nested fashion:

// This is fine
x := (conditionA) ? true_resultA : false_resultA;

// This would probably be clearer using if-then-elseif
x := (conditionA) ? 
       ((conditionA1) ? true_resultA1 : (condition2) ? true_result2 : false_result2) :
       ((conditionA2) ? true_resultA2 : false_resultA2);
Mark
This is the same conclusion I've always came to regarding this. Simple uses of the ternary operator are fine, but don't abuse it with excessive conditions or nesting.
Ryan Versaw
+1  A: 

Regarding 1.13 (Avoid fully qualified type names. Use the "using" statement instead):

It may be a bit more than readability. If you have too many usings at the beginning of the file, you have a class that is coupled with classes from too many namespaces.

The class is screaming out for refactoring. Using usings instead of fully-qualified class names lets you identify such tightly-coupled classes more easily.

azheglov