Partager via


Are some features more harmful than helpful?

We've been talking a lot about the suggestions everyone has been asking us to make.  As you may or may not have guessed, many of the suggestions are things that have come up internally and have already been given a lot of thought.  The reasons we don't have them for this version are many-fold.  But the main reasons are:

  1. We don't have time to implement that feature even though we'd like to
  2. We actually don't think the feature is a good thing and we think it will be detrimental to add it

The first is something that I think everyone can understand.  We have a limited number of resources (time, developers, QA, etc.) and there is only so much we can do.  Large features that affect many teams use a large amount of resources, and we'll only commit to them if we see immense user benefit.  In general we'll schedule to provide the greatest user benefit.  There's no set way of doing this, but (for example) we might pick 5 really great features rather than 1 amazing one because we can do the 5 in the same amount of time and altogether they are better than that 1 other feature.  Of course, figuring out how many resources something will take to do is extremely difficult and things get updated as work progresses.  Sometimes a feature take 1/10 the time you thought, sometimes three times longer.

The second is something that I think people understand but don't necessarily think about.  While they see a benefit to the suggestion, they don't consider that there might be a downside.  I do a lot of my coding in C++ (unfortunately) and I see that as a language whose design philosophy was “that looks cool!  is it fast or powerful?  Yes!!  Then lets add it.”  This is generally why people talk about C++ as a shotgun that not only comes preloaded but also is pre-aimed at your feet.  The features it has can be used amazingly effectively in some situations, but tend to get abused to no end leading to nigh-impossible to understand code with bugs that can be horrendous to find.  I'm also someone who followed the development of java (and other languages) quite closely.  You could see that in their design process the looked carefully at the features that other languages had and they asked “is that feature something that is normally used well, or normally abused”.  If it fell into the latter category then they said “we're not going to include that.  Even if it is a burden for the programmer who would use it well, it's better for the platform overall”.  This is a philosophy that I agree with.  Why?  Because if you make a mistake and later realize that you need something, then you can always add it later.  If, instead, you had added these features then you'd be stuck because it's very very difficult to remove something from a language as you may break existing code.

Many features we've looked at could help programmers in special situations, but we feel that they would lead to developers creating bad code and APIs.  An example of this is the “optional/named parameters” argument.  When you have a language with optional parameters you can end up with apis with methods that take 50 parameters.  (See the Office Object Models for example of this).  The reason this is generally bad is that these 50 parameters have a relationship that you can't express.  Like “if you give the font argument, then you also must specify size, but not specify window layout or brush stroke”.  These kind of constraints are things that should be encapsulated elsewhere.  The arguments people generally make for wanting this feature are so they can inter-operate with these APIs.  However, if we added feature then more of these APIs would breed and you could get a proliferation of bad APIs. 

That's an example of a language feature that we worry about.  There are also issues with our tools that we worry about.  For example, one thing we're ambivalent about is allowing users to collapse regions in the Visual C#.  What we've seen is that people end up with a “#region fields, #region methods, etc.” which they then collapse to get a class that is only like 10 lines long.  If you expand it you end up with a 200k file (no joke).  In this case because we've made it so easy to hide the complexity you end up thinking that your class isn't complex and you end up with an impossibly complex object.    If we didn't have this then frankly you'd be forced to break up your object to make it less unwieldy. 

Another tools feature that we worry about would be Edit & Continue.  Richard Grimes has a very interesting article on it where he argues that it actually leads to poor development and design skills.  I somewhat agree with this view.  As I posted about earlier, when I'm in Ocaml/Java/C# i never use a debugger.  Why?  Because I tend to keep follow development processes that make it unnecessary.  When things to go wrong I tend to just sit down and think about it for about 5 minutes after which I'm pretty sure I know what the issue is.  A quick test will usually confirm it.  I'll then fix up the issue and add tests to make sure that it won't happen again.  When i use the debugger I tend to find the area where the problem actually manifests itself and I'm then tempting to fix it right there.  By doing this I might be overlooking the fact that something else way before actually screwed something up and I'm fixing it in the wrong place.

The best fixes that I've ever made to code have come about because I didn't just path a couple of lines and move on.  Instead I went and talked to my peers about it.  I say what i think is wrong, and how I think it should get fixed.  They're response is usually “waitaminute... that doesn't make any sense.”  or  “wait.. how did this work before.”  or “if you do that Foo will break.  You should be fixing it here instead so that the problem is actually gone”.  or, even better “wait... this is just fundamentally broken.  Of course this would fail.  We really need to rethink this and do it correctly”.   That last statement has happened a lot in the whidbey time-frame and our code-base has become much much better because of it.  Long standing deep seated bugs were rooted out because we didn't just fix a symptom, we tracked it down to the actual source of the bug (usually a way overcomplicated class), ripped it out and replaced it with something far simpler and understandable that we were then much more confident in. 

Note: This is my opinion :-)     many people disagree with me on this.  There are tons of people who live in the debugger (and who create very good code).  They would probably be able to leverage this quite effectively.  However, again, this is one of those areas where we have to ask “are we doing more harm than good”.  If, in the end, we feel the answer is yes (i.e. the feedback from you is “i understand the risks, but this is something that makes me a better developer”) then we'll do it because we want C# developers as a whole to be more productive.

This post came out a lot longer than I expected.  But I thought it might be helpful to understand that we do think very carefully about new features and it doesn't boil down to “lets just do it because we can”.  If you have any questions or issues with anything I've said, let me know!

Comments

  • Anonymous
    June 22, 2004
    Edit & Continue simply speeds up debugging, sometimes by quite a bit.

    It is often that I have a problem that surfaces reproducibly, but the repro scenario takes a minute of clicking and typing in the right places to get the data to look right. Without Edit & Continue, I would have to run the code, see the problem, stop, write some code to fix it, restart the app, spend a minute climbing the mountain till I reach my bug, run it again -- and hopefuly I fixed the problem the first time, otherwise I'll have to re-run again.

    With Eidt & Continue, I can fix simple problems interactively the first time I run the app. After it's done, I can do a verification run-through, but at my leisure. In some cases, with Edit & Continue, I can fix multiple problems at once. IIRC, Edit & Continue in C++ has previously made me about 5x more productive in debugging.
  • Anonymous
    June 22, 2004
    I totaly agree with you, that it's better to think first about your changes. But with your argumentation about edit and continue you have to disable the debugger too. (or at least make it more difficult to start him). I think edit and continue ist just an good time saver in some situations.

    Besides i don't see a large difference in VB and c# developers. Both are human beeings with similar errors.

    bye
  • Anonymous
    June 22, 2004
    Andreas: There's a world of difference. One has a V and B, one has C and a #. Duh. :-)
  • Anonymous
    June 22, 2004
    The comment has been removed
  • Anonymous
    June 22, 2004
    two features to get rid of
    1. Dynamic Help
    of make it usefull, mostly it is just not usefull at the same time as being slow and in the way.
    2. Debug and Design window layout.
    e.g. show server explorer/solution explorer. I swithc between them based on that I am think about and working on not based on debug or code edit.

    Edit and continue seems like such a large developer resource leak (to implement) that I'd much rather all the other productiviy IDE enhancements were added first.I'd probably use it if you added it but the whole intelisense, spell checker concept is far and by above more a useful feature.
  • Anonymous
    June 22, 2004
    What about this compromise. Just add support to properly! consume optional parameters and named indexers and don't add support to create such interfaces yourself in C#. I think this satisfies everything: we can easily use other (even if poorly designed) libraries and we are forced to create great libraries.

    I'd also like to hear what you think about named indexers/properties with arguments (I think you've confused this with named arguments).
  • Anonymous
    June 22, 2004
    I think that a lot of the need for Edit&Continue can be removed if you use nUnit or annother test framework.

    You write a test that causes the bug, rebuild and then run the test.

    One more difference beetween C and Visual Basic, B.A.S.I.C. is an acronym.
  • Anonymous
    June 22, 2004
    nUnit isn't the be-all, end-all to development.

    I think most C++ turned C# developers are against E&C because they only understand E&C within the framework of C++; if they had ever used VB6's E&C, they wouldn't be so brash about declaring it a bad feature. The implementation can cloud your opinion of a thing very easily.


    The people that are going to write bad code because they are using E&C have already written bad code to begin with! You aren't saving anyone from anything; those who use E&C responsibly probably also use nUnit and do plenty of testing too.


    If we shouldn't have E&C then we shouldn't have debuggers or the command window either; if we do need debuggers then we need E&C. Stop trying to save people from themselves and let the users have the tools they want.


    (I also find it quite amusing that test-driven development is the C# answer to VB's E&C, but the VS team won't include nUnit in Whidbey. Microsoft's official perscribed solution is use this 3rd party thing over here? Thanks guys, way to present a coherent plan.)
  • Anonymous
    June 23, 2004
    At work E&C would save me a lot of time in having to track down to a problem. There are many times where instead of even bothering with debugging I just though a Response.Write statement in where I think the problem is, rebuild and run the page. This is because its quicker then having to get everything into the proper state over and over and over again.

    Really there isnt much difference between E&C and having to restart the debugger each time that would solve your issue of fixing things in the wrong place, it just takes longer without E&C. If they would do that with E&C they probobly already do it with the current debugger.

    While I am really liking NUnit for my personal development project. It is not really a feasible option to implement at employer, mostly because my boss doesn't see the value of it. And partly just because of the way that the object model was designed does not really support unit testing (lots of httpcontext and no datalayer).
  • Anonymous
    June 23, 2004
    More harmful than helpful: inheritance.
    Oops, too late. (sigh)
  • Anonymous
    June 23, 2004
    I once had a boss who was completely againt refactoring portions of really long methods into separate methods. His reason? We can just put a #region around it.
  • Anonymous
    June 23, 2004
    If the need for E&C is a result of poor testing, does that mean that the need for refactoring is the result of poor design? :-)
  • Anonymous
    June 23, 2004
    I'm not sure about anyone else, but I personally found VB E&C more of a hassle than a useful tool. Perhaps its simply the nature of most of the bugs I write/wrote, but it seemed much more often than not, the changes I needed to make were beyond the E&C limit. I got to the point where I loathed the "You will have to start and try again" message the editor would pop up. (Keep in mind, however, the last time I much used VB was around VB3.) The "autopsy report" from the debugger, especially the stack trace at death, is usually enough for me to go on, at least with most of my projects.
  • Anonymous
    June 23, 2004
    Seems to me everyone is commenting on E&C for fixing bug in existing apps, or apps that are in QA. Personally the majority of the time I used it was for doing Unit testing. It allowed me to exercise my code within the contect of the entire app. Besides, I hate having to rerun my entire unit test just because I forgot to NEW an object or something dumb like that. :)
  • Anonymous
    June 23, 2004
    The comment has been removed
  • Anonymous
    June 23, 2004
    Ilya: I understand completely what you're saying. But what if we could create software that made it so you never even needed to debug? What good would it be to improve the debugging process then?

    Which would you prefer? If we could help prevent bugs rather than helping you fix bugs? :-)

    It's an interesting thing to consider.
  • Anonymous
    June 23, 2004
    Andreas: Hey... if i had my way, we wouldn't have the debugger ;-)

    But that's not going to happen.

    The question that's important is:

    Given our resources are there better ways we can help out C# developers? If not, then maybe we should do E&C. But we should look into it.
  • Anonymous
    June 23, 2004
    Wesner: I don't understand. Even with optional parameters you need to test every variant of the method.

    Can you show me an example where default/optional parameters are good?
  • Anonymous
    June 23, 2004
    Adam: You can turn of DH if you don't want it. I know the UE team has worked very hard to improve the DH experience. I hope you'll find it useful.

    Anson has worked hard to improve the window layout of the product. I think you'll find it a lot beter.

    Thanks for the feedback on intellisense inhancements.
  • Anonymous
    June 23, 2004
    Kavan: We could do this. However, I think we'd prefer to not encourage these sort of APIs and have better Primary Interop Assemblies generated that would make the C# developer's experience far nicer with dealing with office.

    Say, we added this support. By the time it came out office released a new API that worked well from C#. Then no one would use this new feature.

    I'm fine with named indexer and properties with arguments. I have nothing against it, but I also don't see a large benefit to them. Can you give examples of where you'd really want them.
  • Anonymous
    June 23, 2004
    Russ: See my earlier comment on this.

    We have a limited number of resources here. We're tryign to figure out the best way to help out our users. What if we could help you out by producing tools that made it harder to make these mistakes in the first place. Would that offset the need for E&C.

    The philosophy of "Stop trying to save people from themselves and let the users have the tools they want. " is incredibly important. If we didn't have this then we'd end up with C++ all over again.

    Also, I don't know what you mean about nUnit. Many nUnit developers works for MS and MS is committed to unit testing in whidbey. Have you seen the VS2005 team system?
  • Anonymous
    June 23, 2004
    The comment has been removed
  • Anonymous
    June 23, 2004
    Luke: :-P

    Haacked: Yup. Features can be (ab)used. It's a big concern. Sometimes you only realize the consequences afterwards.
  • Anonymous
    June 23, 2004
    Sean: No. Agile methodologies would dictate that you solve the problem at hand. Then, in the future, when you need to support other feature/scenarios you refactor the current code as necessary to support the old behavior and the new.
  • Anonymous
    June 23, 2004
    Steve: Thanks! I never considered that.

    Other people at work told me that they use E&C to help try out a system and play with it.

    I don't have an issue with E&C being used a discovery model. I worry about it being used as a quick way to patch bugs without actually understanding what's wrong and fixing the real problem.
  • Anonymous
    June 23, 2004
    Cyrus: It's not only office api. I'm a VB.NET developer mainly (unless I need unsafe or native code and in the future anonymous methods), so what I want is that also the C# world could easyly consume my libraries. And I plan to encourage this kind of apis in the future. Not in the abusive way however. So to answer you where I see benefit in using these things.

    Optional arguments are a big saver in terms of override clutter. I'm not talking office 30 arguments and such. I'm talking about methods taking up to 6 arguments (including optional). I'd rather have 3 such overrides than 18 of them.

    The answer against properties with arguments is usually that you should encapsualte that into a collection of some sort and expose it through indexer in that collection. I have found several situations where it's impossible to rise the required fields to collection because of too tight relation with the parent class. So the only workaround would seem to be to create a nested collection class that has access to private state of the parent. This is valid option to me but the implementation isn't as clean as it could be with properties with arguments/named indexers. It also goes against the guideline about not having public nested classes.
  • Anonymous
    June 23, 2004
    Another point that I find amusing. Why do you have optional/named arguments support for attributes?
  • Anonymous
    June 24, 2004
    Kavan: Excellent points you're making. We do make things tough for some cross langauge developers.

    This is an extremely difficult thing to gauge (And trust me, we ahven't made up our minds on it). But it always comes down to a question of "how much does this benefit ourcustomers" and "woudl something else be more beneficial". In your case this would have HUGE advantages.

    However, I'm still worried about this. The APIs you are describing are ones that I don't know enough about. In the Office/Word/Excel case I'm very aware that the patterns they use are not ones we would recommend nowadays. I feel that while this feature could be helpful, (so far) it has always been more detrimental than it's worth

    As to attributes. Those aren't optional/named parameters. Those are ways to set fields/properties of an attribute in one fell swoop.

    There are no optional parameters in an attribute's actual constructor. You must specify each and every specified parameter. The named parameters exist so taht you can set writable fields/properties after construction time. :-)

  • Anonymous
    June 24, 2004
    Well if I can help you in the decision with some examples I'm glad to help. If it turns out that I could do things better in another way then ok. My main perspective to decide on what is better is ease of use for my customers, and I put VB.NET customers first :)
  • Anonymous
    June 24, 2004
    Kavan: Yup :-)

    And we are totally committed to our C# customers.

    Now, if we find that a large majority of them are people who have to interface with VB libraries, and this is a significant deterrent for them, then I'll probably think differently.

    To those reading this. Do you want optional/parameters? If so, vote for them :-)
  • Anonymous
    June 24, 2004
    I'm glad we don't have optional parameters in C# as I prefer to achieve the same with overloads.

    As mentioned above Attributes have named parameters, which are actually just properties of the Attribute object which seems a good strategy for implementing lots of optional parameters.

    I don't like the way they are currently implemented in VB.NET either which is by baking the optional value into the calling assembly.
  • Anonymous
    June 24, 2004
    I'll give just one example, then I'll probably give up :)

    Imagine that you have a class that represents an input device, for example a keyboard. And you have to provide a way to determine if a given key is pressed at the moment. You have the state stored internally in an array and you have to decide how to expose this to the user. Which of the following ways would you choose:

    1) Expose the state through a readonly collection that is indexed by key enumeration
    2) Create a function that given a key enum returns a boolean
    3) Create readonly property taking the key enum as parameter
    4) Other

    Please explain what's your motivation for the choice.

    I'd go for 3 as it indicates to the user that he's only accessing an internal state of the class compared to function, which would indicate that something more performance intensive is taking place. Option 1 seems to be quite good but to me having a public key collection indicates that it can live on its own without the keyboard which is not the case.
  • Anonymous
    June 24, 2004
    The comment has been removed
  • Anonymous
    June 25, 2004
    You cannot have the property return an enum as you can have multiple keys pressed at the same time. This is the whole idea why you have properties with arguments.
  • Anonymous
    June 25, 2004
    The comment has been removed
  • Anonymous
    June 25, 2004
    If you don't see the difference then what is the difference between Class.GetX()/SetX(value) and Class.X?
  • Anonymous
    June 25, 2004
    The comment has been removed
  • Anonymous
    June 25, 2004
    Here's a quote from design guidelines that is the main factor for me:

    In general, methods represent actions and properties represent data.

    The only reason why design guidelines says to use only one indexed property is because:

    Do not use nondefault indexed properties. C# does not allow this.

    I'm giving up.
  • Anonymous
    June 25, 2004
    I have to say this one more thing. You seem to be thinking like this: this feature could be misused, so let's not put it in the language. I tell you, you already have features that can be misused. And that's perfectly ok, because you have FxCop. Let the language have features that could be useful and let FxCop decide if they are used properly or misused.
  • Anonymous
    June 26, 2004
    Kavan: We were talking about propeties with arguments vs methods. I'm still not seeing any difference between the two. Could you please tell me what the difference is. I'm really ignorant here and I would appreciate your help in understanding this.

    As to your point about FxCop. That is only partly true. There is not enough time for us to add all the features that people want into the language. So we have to pick what we think will have the best impact for our customers.

    Given a feature that tends to be good in all circumstances, vs. a feature that is only good occasionally and tends to be misused, which do you think we should add?
  • Anonymous
    June 26, 2004
    I understand your point completely. Just want to make sure you don't discard these features at the time you've done all the things that can't be misused :)

    The difference between property and function without arguments is the same as the difference between property and function with arguments. One is used to represent data while the other is used to represent actions. And all the benefits you've said that properties have are also valid for properties with arguments. I just want to say that properties are used for the same purpose when they have arguments or when they don't. The only difference is that one represent single element data while the other represents array data. I hope this makes it clear.
  • Anonymous
    June 26, 2004
    The comment has been removed
  • Anonymous
    June 26, 2004
    The comment has been removed
  • Anonymous
    June 26, 2004
    Interesting. For me, I find it cleaner that you have encapsulation with those classes. But then again, I tend to go OO to the extreme :-)
  • Anonymous
    June 18, 2009
    PingBack from http://fancyporchswing.info/story.php?id=688