I talked with my friend philipmat, today, about some of the bad practices that I identified for C♭. After our conversation, he recommended that I take some time to clarify my perspective.
After that, my friend
eb^2 and I talked about the post and he raised some
So, here, I will do that without irony, but with sincerity, instead.
The following sections contain some clarifications for the “features” of C♭ that I identified in Part 1.
Methods only take one parameter and it’s a lambda/Func/Action.
philipmat and I agree that passing a callable to a method has a real place in
design, most notably when we pass filter functions to LINQ methods or when we
pass a factory function to Autofac’s registration methods. We should also pass
lambdas as arguments when the target method expects an
runtime inspection of abstract syntax trees.
However, when we pass anonymous methods as part of the behavior of a class, then we’ve strayed from comprehensible code. We’ve left the world of good object-oriented programming. That may sound like too purist of a view; however, we must write maintainable code, code that others can understand. When I have to jump back and forth and
philipmat suggested that I make the requirement read something like
Methods only take on parameters and it must be a lambda expression at least four lines long.
I like that idea. However, to be honest with you, that makes the C♭ transcompiler more difficult to write. So, out of self interest, I will leave the requirement alone.
The compiler fails to compile a file with any XML documentation.
I believe that I live in rare company as a programmer that expects to have and make quality documentation for end users, fellow developers, and management. These documents, often, bear no similarity to one another. For developers, in their IDE of choice (VS2010?), XML documentation can provide contextual help without having to navigate outside of the IDE.
A lot of projects that I’ve seen, though, have no embedded documentation. Or, when it does, the developer has left the documentation empty or used a generator like GhostDoc to make the documentation.
As with code, documentation should have some though behind it. If it merely parrots the method’s name or the get/set accessibility of a property, that documentation has no meaning.
In OO, behavior is king! (I sure do write that a lot.) Instead of writing for
a property “Gets and sets the value of Poop,” instead, write about the side
affects of setting
Poop. That is what we want to know. How many C#
properties have you seen that have no public getter? Very few, I bet.
The compiler will automatically generate an interface for each class.
This requirement caused the most conversation, the most controversy. To paraphrase philipmat (any misrepresentation is my own):
I want programmers to program against interfaces! They should not rely on implementations. They should not have the ability to use the
newoperator without approval. Instead, they should ask for an implementation from a DI container that will fulfill their expectations.
This requirement comes from the blind way in which many C# programmers make their decisions about the interfaces that they create. Interfaces are about the behavior that they declare, not about the implementation that follows. We should use interfaces to comply with the Principle of Least Knowledge which often coincides with the Principle of Least Astonishment.
In a facetious and silly mood, philipmat named an interface
ICanHazCheezeburger. I laughed and then went on about my business. Later
that evening I realized that how he named that interface had an implicit
and immutable truth to it: it described behavior. The really smart
contributors to the C2 wiki have a great thread named
Interfaces Should Be Adjectives.
I agree with this.
Because the age-old naming convention for interfaces in .NET dictates “an interface’s name should begin with ‘I’,” it makes sense to use that “I” as the personal pronoun for the interface.
For example, I recently started a project in which I wrote an interface that described the common behavior for classes that act like a catalog for rules in the system. In the old days, I would have named it “IRuleCatalog”. However, that does not describe behavior. To make that comply with my philosophical perspective, I made the name “ICatalogRules.” It reads like an English sentence, tells me what the collection of behavior achieves, and truly distinguishes the name semantically from the implementors of the interface like “SimpleRuleCatalog”.
So, I rail against the knee-jerk, poorly-considered “my
Nachos class has an
INachos.” That makes little sense when viewed from my perspective
of object-oriented programming and the correct use of interfaces.
I see a lot of developers do it, though. I think it bad. Hence, I put it in the language.
If you have any other objections or some additions to C♭, please post them in the comments because I will forget them. For example, philipmat brought up a glaring deficiency in my requirements which I have now forgotten. Sorry, man. Perhaps you can remind me, again, later.
Hmmm…. I’m trying to remember it….
Nope. Can’t. Darn it! Damn my feeble short-term memory!
Oh, wait! REGIONS! Yes, regions. Ok, one more feature of C♭.
All methods must be enclsed in a region. Any method over 10 lines long must have regions inside it.
I hate regions. I delete them when I see them in a project on which I work. If you need to collapse your code at artificial levels because you have so much of it, consider that you’ve engaged in bad design and your class has not complied to the SRP.
I once worked on a project where (ZOMG! WTF!?) someone had written methods so long that they included regions in the method body itself. I get the willies thinking about it, even now.
So, regions are stupid. Therefore, C♭ must enforce their usage.