About best coding Style of C#

  • Thread starter Thread starter kiplring
  • Start date Start date
While I'm reading readings on YAGNI, I have a feeling that YAGNI isn't good
for all cases, especially when you foresee there will be a change breaking
"fundamental assumptions" when you design the application. In that case you
will really curse yourself for not writing "not currently needed code" in
the very beginning.

I have a project in hand that because the origional writer does not foresee
there will be other completely different types of products (yes, the
origional code does handle a range of products, but they all have common
characteristics, so the "alien types" added later cased huge trouble), he
ends up need to rewrite nearly half of the application just for that. If he
had the idea that "there might be other type of products that have
completely different characteritics", he'd write more flexible code and
suffer less when the new type is added.
 
While I'm reading readings on YAGNI, I have a feeling that YAGNI isn't
good for all cases, especially when you foresee there will be a change
breaking "fundamental assumptions" when you design the application.

If you can accurately foresee such changes, then Y-Are-GNI. If not, you
should just make sure you follow normal OOP principles, and then you'll be
prepared to change the design when and as needed.
In that case you will really curse yourself for not writing "not currently
needed code" in the very beginning.

The problem is in knowing what code will be needed. If you do spend
significant time handling nonexistent requirements, you may never get a
chance to see if those requirements are ever introduced, because your
project doesn't ship in time and your company runs out of money!
I have a project in hand that because the origional writer does not
foresee there will be other completely different types of products (yes,
the origional code does handle a range of products, but they all have
common characteristics, so the "alien types" added later cased huge
trouble), he ends up need to rewrite nearly half of the application just
for that.

Well, there's bad code of all flavors. And a design that required rewriting
half the application when it changed was never a good design.

But should you really design for "completely different types of products"
when there is absolutely no indication that you'll ever need that
capability? If you're selling insurance policies, should you design it so
you can also sell bicycle tires? It's going to take longer if you do design
it for bicycle tires, and cost more. And you may go out of business while
you're doing it.
If he had the idea that "there might be other type of products that have
completely different characteritics", he'd write more flexible code and
suffer less when the new type is added.

Predicting the future is hard, and we always look bad when we guess wrong.
That's why YAGNI says not to worry about the future. Changing software to
meet changing requirements when necessary should not be hard, because those
requirements certainly will change. The trick is to write good, separated,
encapsulated, seamful (polymorphic) code that can be changed with a minimum
of bother, not code that can handle unrequired requirements.

(Jon will no doubt address this much better than me, and I'm looking forward
to his reply.)

///ark
 
(Jon will no doubt address this much better than me, and I'm looking forward
to his reply.)

Sorry to disappoint, but I think you said it all better than I could
have done anyway :)
 
Lau Lei Cheong said:
I won't rely on behaviours that I'm not sure at the time I write something.

That's reasonable - but it's also reasonable *to* rely on behaviour
when it's specified. (The way you phrased it originally suggested that
even when it's documented you shouldn't rely on it.)
I search the MSDN library, but can't find anywhere explicitly say this. The
Array Overview said nothing about it too.

Indeed - it's in the C# language spec in this case.
And everywhere here and there
inside it declares variable like this:

Copied from "Properties overview" :
ms-help://MS.MSDNQTR.2006JAN.1033/cpguide/html/cpconPropertiesOverview.htm

[C#]
private int number = 0;
[Visual Basic]
Private number As Integer = 0

So I think there should be a reason for initializing the variables
explicitly.

There's plenty of bad code in MSDN - and initialising a single variable
to its default value isn't actually so bad anyway. Going through and
initialising a whole array suggests that something useful is happening
when it isn't.
 
One OT(since it's a C# newsgroup) question - Given it's a C# specification
behaviour, would I be safe to assume that it'd be the same in VB.NET?
 
Lau said:
One OT(since it's a C# newsgroup) question - Given it's a C# specification
behaviour, would I be safe to assume that it'd be the same in VB.NET?

Not necessarily. In fact, I *believe* it's also specified in the CLI,
although a quick flick through doesn't make it obvious, unless this is
covered in 8.9.6.6 or partition 1, which says that user-visible memory
for a new value of an object type is zeroed.

It would be best to check in the VB.NET specification - although I'd be
very surprised if it weren't the same.

Jon
 
Jon Skeet [C# MVP] wrote:
....
There's plenty of bad code in MSDN - and initialising a single variable
to its default value isn't actually so bad anyway.

Except there are more instructions generated in IL, while the default
initialization is performed some other way.
Another thing looks strange. We know now that explicit initialization
to default value is redundant and just plain wrong because efficiency
suffers. This is documented and supposed to be followed, at least at MS.
Then, why compiler does not allow me do things like this:
int i;
int ii = i;
throwing "using unassigned variable" error?
 
Another thing looks strange. We know now that explicit initialization
to default value is redundant and just plain wrong because efficiency
suffers.

To me, initialization of fields to default values just screams "the writer
doesn't know C#!"

I'm glad to have another reason besides snobbery to deprecate it.
This is documented and supposed to be followed, at least at MS.
Then, why compiler does not allow me do things like this:
int i;
int ii = i;
throwing "using unassigned variable" error?

(I assume you're talking about fields, not local variables - in the latter
case, i is not initialized.)

True, but you can't do

int i = 0;
int ii = i + 1;

either. For whatever reason, field initializers aren't allowed to access
nonstatic fields.

///ark
 
Mark said:
To me, initialization of fields to default values just screams "the writer
doesn't know C#!"

I'm glad to have another reason besides snobbery to deprecate it.


(I assume you're talking about fields, not local variables - in the latter
case, i is not initialized.)

Sorry, I just jumped a step ahead without warning... We discussed
specification for field initialization, but I am talking about local
variables now. Looks like it is initialized. If I write:

int i;
i = 1;

and stop in the debugger right after its declaration, I can see it having value 0.
And the message is quite clear on that: it says "unassigned". It is probably
due to the language spec vs CLI spec, and designed so just to be safer.
 
Mark said:
To me, initialization of fields to default values just screams "the writer
doesn't know C#!"

It doesn't mean any such thing. It means that the coder has a variable that
he/she wants initialized to 0.
 
Ian Semmel said:
It doesn't mean any such thing. It means that the coder has a variable
that he/she wants initialized to 0.

If she knows the basics of the C# language, then she'll know that if she
wants a field initialized to 0, she doesn't need to (and indeed should not)
use a field initializer.

///ark
 
Sericinus said:
Sorry, I just jumped a step ahead without warning... We discussed
specification for field initialization, but I am talking about local
variables now. Looks like it is initialized. If I write:

int i;
i = 1;

and stop in the debugger right after its declaration, I can see it
having value 0.
And the message is quite clear on that: it says "unassigned". It is
probably
due to the language spec vs CLI spec, and designed so just to be safer.

No, it's not initialized.

It has a value (as a variables always has one), and it happens to be
zero in this case, but the value is undefined and could be anything that
happened to be in that memory location on the stack when it was allocated.
 
Göran Andersson said:
Sericinus hunter wrote: ....

No, it's not initialized.

It has a value (as a variables always has one), and it happens to be
zero in this case, but the value is undefined and could be anything that
happened to be in that memory location on the stack when it was allocated.

This makes sense. Thank you.
 
Mark said:
If she knows the basics of the C# language, then she'll know that if she
wants a field initialized to 0, she doesn't need to (and indeed should not)
use a field initializer.

///ark

No, in any language, the (equivalent) statement of

int x;

means that this variable exists, but it has a 'don't care' value, the
implication being that it will be set later on.

int x = 0;

means that it starts off with a definite value.

Similarly, parentheses should always be used in expressions without depending on
a language-specific hierarchy of operator precedence. It is an old 'C' hacker
convention to help the compiler by reducing the number of characters in source code.

It is a good idea to use a commonality of coding styles across all languages in
my opinion.
 
Ian said:
Mark Wilden wrote: ....

No, in any language, the (equivalent) statement of

int x;

means that this variable exists, but it has a 'don't care' value, the
implication being that it will be set later on.

int x = 0;

means that it starts off with a definite value.

Similarly, parentheses should always be used in expressions without
depending on a language-specific hierarchy of operator precedence. It is
an old 'C' hacker convention to help the compiler by reducing the number
of characters in source code.

It is a good idea to use a commonality of coding styles across all
languages in my opinion.

Just to make sure, we are talking about the same thing. What Mark says
(and what I agree with him upon) relates to type fields, not to local
variables. Fields have initializers, this is a feature of the language.
Fields are initialized automatically using processor instructions to
fill memory blocks with zeros, thus very efficiently. It would be just
silly to reassign a field to the same value again and besides using
less efficient higher level commands.
 
And some feel it is even more silly to not initialize such data. From a
managers perspective you don't know who is going to maintain that code
several years down the road when a whole new set of languages is being used
and those people may not know a thing about C#. Many perspectives can be
valid. What Albert wrote many years ago is still true, "It is all relative".
 
It is a good idea to use a commonality of coding styles across all languages in
my opinion.

I couldn't disagree more.

Many languages have different coding conventions in many ways - naming
being the most obvious example. Some idioms from some languages *just
don't work* in others, or effectively fight against the language.

IMO it's worth going with the idioms, specification and conventions of
each language you use - try to avoid writing in one language with an
"accent" of another.
 
And some feel it is even more silly to not initialize such data. From a
managers perspective you don't know who is going to maintain that code
several years down the road when a whole new set of languages is being used
and those people may not know a thing about C#. Many perspectives can be
valid. What Albert wrote many years ago is still true, "It is all relative".

While it's a valid viewpoint in some ways, I'd argue that anyone who
doesn't know C# to at least a reasonable extent shouldn't be
maintaining it. It's likely to be unproductive in the long run. Suppose
someone is used to C++ and starts maintaining C# - they might assume
that the RAII idiom works in C#, and so never calls Dispose on any
streams etc. Not a good idea.

I think it's good to try to avoid relying on people knowing really
obscure bits of the spec, but some basic knowledge is reasonable.

If we agree on that, the question is really whether or not default
values count as basic knowledge. Personally I'd say they are, but I
wouldn't be surprised to find people disagreeing.
 
Ian Semmel said:
No, in any language, the (equivalent) statement of

int x;

means that this variable exists, but it has a 'don't care' value, the
implication being that it will be set later on.

In C#, when x is a field, means that the variable's value is set to 0.
Similarly, parentheses should always be used in expressions without
depending on a language-specific hierarchy of operator precedence. It is
an old 'C' hacker convention to help the compiler by reducing the number
of characters in source code.

It is a good idea to use a commonality of coding styles across all
languages in my opinion.

I can't see any possible basis for that opinion. By that logic, we wouldn't
use OOP, since C doesn't support it.
 
And some feel it is even more silly to not initialize such data. From a
managers perspective you don't know who is going to maintain that code
several years down the road when a whole new set of languages is being
used
and those people may not know a thing about C#.

So you're saying we ought to write C# so that it can be understood by people
who do not know a thing about C#?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top