Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Questions on Juval Lowy's IDesign C# Coding Standard [closed]

We are trying to use the IDesign C# Coding standard. Unfortunately, I found no comprehensive document to explain all the rules that it gives, and also his book does not always help.

Here are the open questions that remain for me (from chapter 2, Coding Practices):

  1. No. 26: Avoid providing explicit values for enums unless they are integer powers of 2
  2. No. 34: Always explicitly initialize an array of reference types using a for loop
  3. No. 50: Avoid events as interface members
  4. No. 52: Expose interfaces on class hierarchies
  5. No. 73: Do not define method-specific constraints in interfaces
  6. No. 74: Do not define constraints in delegates

Here's what I think about those:

  1. I thought that providing explicit values would be especially useful when adding new enum members at a later point in time. If these members are added between other already existing members, I would provide explicit values to make sure the integer representation of existing members does not change.
  2. No idea why I would want to do this. I'd say this totally depends on the logic of my program.
  3. I see that there is alternative option of providing "Sink interfaces" (simply providing already all "OnXxxHappened" methods), but what is the reason to prefer one over the other?
  4. Unsure what he means here: Could this mean "When implementing an interface explicitly in a non-sealed class, consider providing the implementation in a protected virtual method that can be overridden"? (see Programming .NET Components 2nd Edition, end of chapter “Interfaces and Class Hierarchies”).
  5. I suppose this is about providing a "where" clause when using generics, but why is this bad on an interface?
  6. I suppose this is about providing a "where" clause when using generics, but why is this bad on a delegate?
like image 572
Jan Avatar asked Oct 20 '11 09:10

Jan


1 Answers

Ok so I will basically chip in with the little rep I have on stackoverflow: You can all kill me for opening a religious debate.


The hint to working with Juval's code standard is really in it's preface:

"I believe that while fully understanding every insight that goes into a particular programming decision may require reading books and even years of experience, applying the standard should not."

Next hint is to read his work. Next would be doing what he advices. Maybe on the way understand why he is recognised as a "microsoft software legend". The next might be that it is delivered in a read-only pdf.


That didnt satisfy you?

The key here is realizing this is not a religious narrative, it is indeed a pragmatic one.

My personal experience with his standard is pretty much: If you follow the advices as best you can, you will get a productive outcome. Your needs of refactoring will be less, you productivity in the later cycles of the project will be higher.

This is an experience based evaluation.

Basically what you are looking for are the answers to "why" certain portions of the coding standard is in there, specifically these: 26, 34, 50, 52, 73, 74

You are asking these questions from a pragmatic perspective: You want to incorporate the standard and you "somehow" know this will give you a benefit in the longer run.

By examining these rules, through experience, you will perhaps come to understand why they are indeed there. Experience is here doing and not doing your code in accordance with the principles. But really that isnt the point. The point is that by working from the basis of a well considered, mature and reliable standard, your work now becomes work of quality.


On how to follow a standard

Really read the rules as advices, they are already very strictly worded: "Avoid, do not, do and so on" really means what they say. Avoid means "think really hard before breaking the principle". "Do not" really means "do not".

Juval is all about decoupling and most of his harder-to-grok advices really comes from not thinking "separation" into your code design.

Sometimes this is hard to do with a team that works in less abstract terms or in more feature oriented environments, and you can therefore sometimes find it necessary to break rules, "to get the team moving", but you really should refactor this to the standard when you can do so.

After a few years, a few projects more, you perhaps will come to understand the rationale for each and every rule in the simple guide. If you are a bright student. Me, I'm not so bright, so I base it on experience: Stuff that is in the non-standardized parts of the code often fails during integration testing. It is often harder to come back to. It often ties poorly to the environment and so on.

It really is a matter of trust. If you cant find it in yourself to trust this (not adopt it - trust it), standard, I will propose to you that you will find it hard to ever really write comprehensible c# code that is generally of a acceptable quality. This of course not considering the few really smart and really experienced out there that managed to build up their own set of internalizable rule sets on how to write code that is: Stable, readable, maintainable, extendable and generally mega-ble.

This not saying that this is the only standard, just that it do indeed work. Also over time.

You will be able to find other standards, most if not all, though sub-standard to this for working with code you "really want to work" in the long run, involving a team of developers and changing real time situations.

So consider your standard, it is really setting the bar for the quality you provide for the $ you earn.

Do not reconsider it, unless you have "real good reasons to".

But do learn from it.


You reached here and you are still not satisfied. You want answers!

Darn it. Ok let me give you my clouded and sub-par experience based view on the rules your team can't grok.

No. 26: Avoid providing explicit values for enums unless they are integer powers of 2

Its about simplicity and working within that simplicity. Enum's in c# are already numbered from "i=0" and injecting "++i" for every new field you define. The simplest way to [read code with/] think about enums are therefore either you flag them or you enumerate them. When you dont do this, you are probably doing something wrong. If you use the enum to "map" some other domain model, this rule can be broken, but the enum should be visibily separated from normal enums through placement/namespace/etc - to indicate you are "doing something not ordinary".

Now look at the enums you have created out-of-standard. Really look at them. Probably they are mapping something that really do not belong in a hard-coded enum at all. You wanted the efficiency of a switch, but you have in actuality now begun to hardcode out-of-domain properties. Sometimes this is ok and can be refactored later, sometimes it is not.

So avoid it.

The argument of "inserting into the middle" in the development process, is not really an issue that should break the standard. Why? Well if you are using or in any way storing the "int value" of the enumeration, then you are already diverging into a usage pattern where you need to stay very focused indeed. Not using 0, 1, 2 is not the answer to problems in that particular domain, i.e you are probably "doing it wrong".

The EF code-first argument is, probably not an issue to circumvent the rule here. If you feel you have such a need, please do describe your situation in a separate thread and I will try to guide you how to both follow the standard and work with your persistance framework.

My initial take would be: If they are code-first poco entities, then let them abide by the code standard, After all your team have decided to work with a code-first view on the data model. Allow them to do just that, following the same semantics as the rest of their code base.

If you run into specific problems related to the mapping to database tables, then solve these problems while maintaining the standard. For EF 4.3 I would say use the get/set with int pattern and replace in 5.0.

The real gritty stuff here is how to maintain this entity as the database evolves. Be sure to provide clear migration paths for your production database when your enum containing entities change design. Be very sure if the entities themselves change values. This go for add/remove/insert of new definitions. Not just add.

No. 34: Always explicitly initialize an array of reference types using a for loop

My guess is this is an "experience based" rule. In such a way that he looked through a lot of code and this point seemed to fail often for those that did not do it.

No. 50: Avoid events as interface members

Basically a question of separation - your interfaces are now coupled "both" ways into the interface and out of it. Read his book for clarification on why that is not "best practice" in the c# world.

In my limited view this is probably argumentation along the lines of: "Call-backs are very different in nature from function-calls. they make assumptions on the state of the receiver at an undefined "later time" of execution. If you want to provide callbacks, by all means do provide them, but make them into separate interfaces and also define an interface to negotiate these callbacks, in effect establishing all the hard things you wanted to abstract away, but really just circumvented. Or probably just use a recognized pattern. aka read the book."

No. 52: Expose interfaces on class hierarchies

Separation. I cant really explain it any further than: The alternative is hard to factor into a larger context/solution.

No. 73: Do not define method-specific constraints in interfaces

Separation. same as #52

No. 74: Do not define constraints in delegates

Separation.


Conclusion

......

Another view on #50 is that it is one of those rules where: If you dont get it, its probably not important for you. Importance here is an estimate on how critical the code is - and how critically you want that code to always work as intended.

This again leads into a broader context on how to verify your code actually is quality.

Some would say this can be done with tests only.

They however fail to understand the interconnectedness between defensively writing quality software and aggressively trying to prove it wrong.

In the real world, those two should be parts of a greater totality with the actual requirements of the software being the third.

Doing a quick mock-up? who cares. Doing a little visual thingy that you understand the runtime constraints of? who cares - well probably you should, but perhaps acceptable. and so on.

In the end compliance to a coding standard is not something you take on lightly. There are reasons for doing it that goes beyond just the code: Collaboration and communication primarily. Agreement on shared views. Assertions of assumptions.

etc.

like image 72
27 revs Avatar answered Sep 28 '22 11:09

27 revs