Freigeben über


Why static import is bad...

John Rusk asked me to elaborate on why I think static import is bad.

It's all about readability. Most people agree that the average line of source code is read far more times than it is written, which means that being able to understand the line is more important than being able to write it quickly.

Static import is bad because it adds an exception to the rules that everybody has to know and remember. If you see

int x = Process(s);

it's a line of code that's easy to understand, because you know what Process is, and more importantly, you know where to go look for it.

But if you add the capability of doing static imports, Process() can now come from other places, so you have to keep that in the back of your mind, and may have to traipse back to find the import statement. A good IDE could help out at this, but I don't think that should be a language design point.

One can argue that for its intended use - things like Math.Sin(), it will make things clearer, which I agree with. The problem is that I can see this feature being used by people who are familiar with their code to save time, and for them it's obvious that they've done that, but that's not true for the poor guy who inherits the code.

Any feature that comes with the kinds of warnings that were given at the introductions yesterday is questionable in my book, and I don't like adding something that has a good potential to be abused to address a case where people are doing the wrong thing already.

Of course, you can argue that C# has lots of areas of potential abuse, and I'd have to agree with you there, though I think the utility of those features is higher than merely saving a few keystrokes.

Comments

  • Anonymous
    June 30, 2004
    I agree 100% with you, PLEASE DON'T add static import support to C#, I always hate those languages where you can do that, they're SO HARD to read!!!
  • Anonymous
    June 30, 2004
    I'm so happy to read this! Static imports is easily the worst Java language feature ever.
  • Anonymous
    June 30, 2004

    I tend to agree.
    I think the issue is more 90% runtime and 10% compiler.(if that).

    As I said in your initial post (http://blogs.msdn.com/ericgu/archive/2004/06/29/169394.aspx?Pending=true)
    ,I think its about intervention, not code weaving.

    I think that many (I am not referring to you or readers) confuse the benefit of hooking in, with what AOP really is all about.
    AOP causes chaos in terms of readability and the changed quantities. But instilling an "intervention philosophy" is *no more * complicated than understanding threads /polymorphism / observer and factory patterns.

  • Anonymous
    June 30, 2004
    How about a with statement like in VB? I build a lot of datasets by hand and I'm tired of writing...

    ds.Tables.Add

    I would love to be able to do like in VB.NET

    With ds.Tables
    .Add
    End With

    Considering it is a block of code, I don't feel that readability is lost.
  • Anonymous
    June 30, 2004
    Nested "with" blocks can be very obscure. If you have a couple of complicated objects and a complicated expression involving several properties from both it is very hard to see what's going on.

    To avoid this, members should be resolved against the innermost "with" block only.
  • Anonymous
    June 30, 2004
    Maybe I'm ignorant, but can you explain to me why static import in Java is bad, but the using statement in C# is ok?

    C# allows you to do things that turn this:

    Math.Sin()

    into this:

    using Math;
    .
    .
    .
    Sin()
    .
    .
    .

    While it is easy to see in the VS IDE where Sin comes from by mousing over it, isn't that the same principle as static imports?
  • Anonymous
    June 30, 2004
    Lee,

    It's not possible to do what you say in C#. I think, but am not sure, that you can do it in VB
  • Anonymous
    June 30, 2004
    >One can argue that for its intended use - things like Math.Sin(), it will make things clearer, which I agree with. The problem is that I can see this feature being used by people who are familiar with their code to save time, and for them it's obvious that they've done that, but that's not true for the poor guy who inherits the code.

    I've wished we had it for the likes of Math.Sin(). But, I must admit that your reasoning makes sense. Thanks for sharing it with us.

    John
  • Anonymous
    June 30, 2004
    The comment has been removed
  • Anonymous
    June 30, 2004
    oooo - and I just thought of one other thing...

    Absolutely ANY argument saying this is bad:

    > using Math;
    > ...
    > x = Sin(23);

    applies EQUALLY well to this scenario:

    > using System.Drawing;
    > ...
    > Color baseColor = Color.Red;

    If you accept that "using" a static class is bad, you MUST also accept that "using" a namespace is bad - because in every way you are doing the same thing... so really you should be writing

    > System.Drawing.Color baseColor = System.Drawing.Color.Red;

    Now some people probably wouldn't be horrified by that - but I am!

    I believe this whole argument comes down to the slow religions conversion of people into OO.. remember - OO is useful in some situations - but it IS NOT the only tool, and in a lot of cases it IS NOT the BEST tool. Functional programming and structured programming very much still have their place in today's languages - and both provide no particular requirement for a function to "belong" to something. Making decisions based on religious zealotry is a bad thing! :)



  • Anonymous
    June 30, 2004
    The comment has been removed
  • Anonymous
    July 01, 2004
    "If you accept that "using" a static class is bad, you MUST also accept that "using" a namespace is bad - because in every way you are doing the same thing... so really you should be writing "

    That was more my point with the example I gave. Why are static imports bad, but shortcutting namespaces ok?

  • Anonymous
    July 01, 2004
    I don't like this concept as it stands, I think it creates confusion. However I can suggest a different solution using the new namespace resolution operator. It wouldn't be so bad to be able to write something like

    using static Math;
    using static BigIntegerMath;
    ...
    int x;
    BigInt y;
    static::Sin(x)
    static::Min(y)

    what have you or to allow syntax that aggregates static functions into a single, named namespace. (Note I don't use = here because that suggests single assignment).

    using static System.Math -> Math;
    using static BigInteger.Math -> Math;
    ...
    int x;
    BigInt y;
    Math::Sin(x);
    Math::Cos(y);

    Something that explicitly shows what you are doing while avoiding the problems of type replacement, make it clearer that you are importing a classes members, not a namespace, and perhaps a few other minor issues that I havn't thought of yet. Most importantly it would make it easy to simulate static class aggregation. There would be rules to deal with, conflicting overloads etc may be a touch troublesome, but I don't think it would be anything worse the conflict problems you face with direct static import or namespace importing.

    Comments?
  • Anonymous
    July 03, 2004
    One possible solution to the problem of not being able to distinguish external methods, would be for the IDE to support different coloring for internal vs. external members.
  • Anonymous
    July 06, 2004
    Darren, on c) you should use refactoring. On e), you should use generics.
    Daniel, using can be used to define shortcuts, like this:
    using BigInteger.Math = BigMath;
  • Anonymous
    July 07, 2004
    The comment has been removed
  • Anonymous
    July 07, 2004
    The comment has been removed
  • Anonymous
    July 07, 2004
    The comment has been removed
  • Anonymous
    July 08, 2004
    Some thoughts on static imports and other stuff...