static class inheritance, generalized

  • Thread starter Ben Voigt [C++ MVP]
  • Start date
B

Ben Voigt [C++ MVP]

I find the class with static methods not pretty, but it has an
advantage over a bucket with routines forming a library: the class name
gives the reader hints where the method is implemented:
Calculator.Add() might be hurting for the eye when it comes to true OO,
however it's IMHO better than having 'Add()' alone, and the reader then
has to GUESS in which module Add is implemented.

Then you'd better outlaw "using namespace". After all, how can you know
what constructor "new Timer()" calls?

Oh, yes, you would look at the using namespace directives at the top of the
file or namespace. And with this suggested feature, you would also look at
the "using static" directives at the top of the file, namespace, or class,
to determine where 'Add()' came from.
 
B

Ben Voigt [C++ MVP]

Could it be used stupidly? Yes. Can it also vastly improve the
readability of certain cases, particularly maths? Absolutely.

And I've proposed another case that I think it would be extremely useful
for:

In order to share generic parameters between a family of classes, they need
to be nested within a generic class. But then you can't access them all
with using namespace, so you're left with a long, ugly qualifier including
the generic type arguments. "using static" could resolve this issue quite
neatly.

Imagine that the generic collections, instead of living in
System.Collections.Generic namespace, all lived in a generic class. Or at
least all the 1-D collections did. Then the data access layer for Customer
could declare "using static Collection<Customer>;" and then refer to
type-safe List, SortedList, IList, ICollection everywhere without
respecifying the generic argument everywhere as well. Maybe a map of string
to Customer should really be "Collection<Customer>.HashMap<string>".
 
J

Jon Skeet [C# MVP]

Ben Voigt said:
And I've proposed another case that I think it would be extremely useful
for:

In order to share generic parameters between a family of classes, they need
to be nested within a generic class. But then you can't access them all
with using namespace, so you're left with a long, ugly qualifier including
the generic type arguments. "using static" could resolve this issue quite
neatly.

Imagine that the generic collections, instead of living in
System.Collections.Generic namespace, all lived in a generic class. Or at
least all the 1-D collections did. Then the data access layer for Customer
could declare "using static Collection<Customer>;" and then refer to
type-safe List, SortedList, IList, ICollection everywhere without
respecifying the generic argument everywhere as well. Maybe a map of string
to Customer should really be "Collection<Customer>.HashMap<string>".

Hmmm... I can't say I can see the benefit of that at the moment. I
haven't been able to really follow your other examples in the C++ group
(partly due to the C++ references, partly due to not having enough time
to really go over them for long periods, I'm afraid). I can see the
benefit of *simple* static inclusions, but I'm not sure beyond that.
 
C

Christof Nordiek

Jon Skeet said:
and likewise I'd much rather read

double foo = Cos(theta) + Sin(alpha);

than

double foo = theta.Cos() + alpha.Sin();

Shouldn't that be:

double foo = theta.Cos().Add(alpha.Sin());

in 'pure' OO ;-)

Christof
 
F

Frans Bouma [C# MVP]

Jon said:
On Jun 7, 9:14 am, "Frans Bouma [C# MVP]"

10.Cos() might look weird, I agree, but
logically, it is something in line with "foo123".Substring(2);

I was going to reply to your response to me, but this is actually the
best example I've seen. As you said elsewhere, readability is vital.
It's more important (to me) than the logic of the thing. I would far
rather read:

double dist = Sqrt (x*x+y*y);

than either of

double dist = (x*x+y*y).Sqrt();
double dist = Math.Sqrt(x*x+y*y);

and likewise I'd much rather read

double foo = Cos(theta) + Sin(alpha);

than

double foo = theta.Cos() + alpha.Sin();
double foo = Math.Cos(theta) + Math.Sin(alpha);

I'm raised with assembler and C, when I was at the uni we didn't get
OO languages, just a lot of other paradigms. All nice but not OO.
Reading your examples, I have to admit:
double dist = Sqrt(x*x + y*y);
fits like a glove, I really like it because it's so familiar, as I've
written and read code like that for years and years.

What I want to make clear here is that it apparently seems that I am
actively PROMOTING 10.Sqrt();, but I'm not. I'm just arguing that
theoretically, it would be more OO. Not that that would be BETTER
necessarily.

Just because the code reads like old code from the good ol' times,
doesn't make it FIT in the surrounding code it is placed in,
necessarily. So if the surrounding code is pure OO code, it feels like
a friction to have code like
double dist = Sqrt(x*x + y*y);

The main reason is that the general paradigm is that 'Sqrt' here is a
method of the class this line is in. But that's not the case in the TS'
proposal.

This thus clashes, IMHO. By proceeding with what TS's proposes, you
create ambiguity in the language for the reader of the code. I then
argue: you shouldn't proceed with this, as it is a degration of
readability (== reader understands what's written).

My argument was a bit ripped apart, perhaps because I didn't structure
it well enough, but what I argued was that the REASON the static
methods are there is because of the friction between OO and procedural
and you could solve it in two ways: move the method to the class which
instance holds the data the method works on (the dreaded 10.Sqrt()) or
use it as static methods, which is IMHO still some sort of hack.

I personally agree with your examples, but not because I find them
formulate better constructs, but because they feel more closer to what
I have been reading/writing for a long time, more familiar.

However merging that with an OO language gives IMHO more problems than
it solves, so I can't agree with the proposal of TS, on the contrary.
Do you genuinely believe that either the instance method version or
the static method version including the class name conveys the
intention of the code more simply than my preferred version?

Yes, because the preferred version clashes with
SomeType t = ClassMethod(val);

when we see this kind of code in a C# class, we KNOW that
'ClassMethod' is either in this class or in its supertype. It's not a
class defined elsewhere.
Yes, you may occasionally want to use Intellisense to confirm which
class a method actually belongs to - although I'd say that when used
sparingly, it should always be obvious anyway. That productivity
decrease is easily matched by the improvement of readability in cases
like the above.

IMHO any reliance on intellisense for readability of code is bad,
because code should be clear from its construction, not because you
have fancy tools at hand. The next step will be that 'code is perfectly
clear if you have resharper x.y, coderush vZ etc. installed and setup
like user ABC.'.
Could it be used stupidly? Yes. Can it also vastly improve the
readability of certain cases, particularly maths? Absolutely.

As I see 'readability' as the term for: the reader understands what's
been written perfectly, I don't really see how
double d = Math.Sqrt(val);

is less readable than
double d = Sqrt(val);

simply because Math.Sqrt() tells the reader which Sqrt is called: the
one in the Math class. Simply calling Sqrt() is less clear, because it
could be in the class or supertype OR it could (if TS' suggestion is
added) somewhere in the classes of the scope data imported by the using
statements. IMHO not a thing you'd want to have. (Sqrt is pretty
obvious what it does, a simple thing, but a method which is pretty
complex and will call a lot of other methods, it's not that clear).

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

Ben said:
Then you'd better outlaw "using namespace". After all, how can you
know what constructor "new Timer()" calls?

Oh, yes, you would look at the using namespace directives at the top
of the file or namespace. And with this suggested feature, you would
also look at the "using static" directives at the top of the file,
namespace, or class, to determine where 'Add()' came from.

So, because that set of using statements makes it already less clear,
you're perfectly OK with making it VERY unclear for the reader with
further scope increases?

double d = Sqrt(foo);

where does 'Sqrt(foo)' live? I have NO idea. Sure, with fancy tooling
I might find the place where this is. But reliance on tooling to READ
and UNDERSTAND code is IMHO a slippery slope I at least don't want to
be on. Code should be understandable and clear for the reader who reads
it. ANY degration to that is IMHO bad. Sure your suggestion might save
a few keystrokes, but it also introduces degration of the clarity of
code written. I simply fail to understand how you can ignore that fact.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

On Jun 8, 9:37 am, "Frans Bouma [C# MVP]"

So, because that set of using statements makes it already less clear,
you're perfectly OK with making it VERY unclear for the reader with
further scope increases?

double d = Sqrt(foo);

where does 'Sqrt(foo)' live? I have NO idea.

Do you *really* have no idea, in real life rather than in theory?
Would you not *guess* that it was in System.Math, given no other
information, and considering the context?
Sure, with fancy tooling
I might find the place where this is. But reliance on tooling to READ
and UNDERSTAND code is IMHO a slippery slope I at least don't want to
be on. Code should be understandable and clear for the reader who reads
it. ANY degration to that is IMHO bad. Sure your suggestion might save
a few keystrokes, but it also introduces degration of the clarity of
code written. I simply fail to understand how you can ignore that fact.

We apparently view clarity differently. If I'm working on something
which I know from the context uses trigonometry, then formulae which
just have things like:

double x = Pow(Sin(alpha)+Cos(theta), 2);

have more clarity for me than formulae such as:

double x = Math.Pow(Math.Sin(alpha)+Math.Cos(theta), 2);

Have you read much C# code that requires extensive use of System.Math?
It's horrible currently, and would *greatly* benefit from this. The
ambiguity due to the *possibility* of Cos/Sin/Pow etc is greatly
dwarfed by the *guaranteed* extra cruft of having to prefix everything
with "Math".

Jon
 
F

Frans Bouma [C# MVP]

Ben said:
[snip]
Though why not specify the class in which the method is defined in
front of the method? Math.Cos() instead of Cos() ?

Don't you mean global::System.Math.Cos()? Or do also you see a need
for not always using the fully-qualified name?

I write a lot of C# code and I've never ever have to use global::. I
also hardly have to use full qualified namespaces in front of types.
Perhaps I write code no-one else writes, but that's my experience.
You've missed my entire point that class members don't all fall into
the categories of (instance method/field/property/event) and (static
method/field/property/event). There are also nested classes, and
these are quite possibly a more important use of the feature than all
others combined. So even in a pure OO environment, where everything
is a class, there is still value in adding class members to the
search scope.

So, you suggest this kind of code is good?
public class Foo
{
private Bar _bar;
private string _val;

private class Bar
{
private Foo _container;

internal Bar(Foo container)
{
_container = container;
}

public string GetVal()
{
return "Bar" + _container._val;
}
}

public Foo()
{
_bar = new Bar(this);
_val = "Foo";
}

public string Do()
{
return _bar.GetVal();
}
}

where bar accesses private members of Foo?

why go that route? Isn't that asking for trouble? Sure, it's possible
but why not create properties and access Foo's code through that? It's
not as if Bar is placed elsewhere, the code is inside Foo anyway.

Sure, in these kind of cross-referencing code, just having to refrence
to '_val' instead of _container._val, can be less typing, but I find it
obscure. Just because a nested type is inside the surrounding type
doesn't make the code (IMHO) semantically part of the surrounding type.
At least, I find it leaky. Sure it's possible, but that doesn't make it
more readable.
There is a huge need for being able to omit or shorten the name of
the containing class, whether you are referring to a member field,
event, property, method, or class. Specifically, when the parent
class name is quite long, which is quite common in the presence of
generics. And, the existing "using" (alias) directive cannot be used
inside a class, so it doesn't fully support generics.

using the keyword 'using' just to save some keystrokes is IMHO not the
way to go. Similar to what some people think is logical to use typedefs
all over the place just because it makes the code mode 'readable' to
them.. :X

A program's control flow can be controlled with a lot of delegates. It
will work, and probably be 'very' flexible. THe downside is that
readability (== the reader understands what's written and going on)
goes out the window, simply because the only way to understand what the
code does is stepping through it in a debugger. well.. Hurray... :-/
Here is a really quick example of the shortcomings of the existing
"using" directive:

Non-generic:

class LinkedListNode { ... }

using Node = LinkedListNode; // of dubious value, not saving much
typing

class LinkedList { /* use Node here */ }

Generic:

class LinkedListNode<TValue> { ... }

using Node = LinkedListNode<TValue>; // error, not in scope of TValue

class LinkedList<TValue>
{
using Node = LinkedListNode<TValue>; // error: here TValue is
available, but the using directive isn't allowed /* use Node here
*/ }

using 'using' in this kind of code is IMHO only useful if you can
reword a type to another name, like when the same piece of code has to
use be compiled against two different oracle providers (ODP.NET and MS
Oracle client) and the only difference is the enum type name with the
type definitions to create parameters for example. then using the same
code with both providers can save a lot of time in maintenance.

Because, often people forget what the biggest pile of work is with a
piece of software: maintenance. Software maintenance will become
horrible the more readability and clarity of the code goes out the
window. Redefinining type names with using is IMHO doing that, unless
you can't otherwise. To do it just by 'saving some typing' is IMHO not
an excuse to introduce it, simply because where does it end? ANd will
maintainability be BETTER after it? I seriously doubt it will.

We soon reach the point where there will be more software applications
on this planet than engineers to maintain them. Introducing more
problems for maintainability is IMHO only increasing that problem we're
soon facing.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

On Jun 8, 9:33 am, "Frans Bouma [C# MVP]"

I'm raised with assembler and C, when I was at the uni we didn't get
OO languages, just a lot of other paradigms. All nice but not OO.
Reading your examples, I have to admit:
double dist = Sqrt(x*x + y*y);
fits like a glove, I really like it because it's so familiar, as I've
written and read code like that for years and years.

It's not just in code though - it's in anywhere you might see formulae
written down. Yes, there's be a square root sign instead of Sqrt, but
that translation is relatively unintrusive.
What I want to make clear here is that it apparently seems that I am
actively PROMOTING 10.Sqrt();, but I'm not. I'm just arguing that
theoretically, it would be more OO. Not that that would be BETTER
necessarily.

I don't think anyone's arguing that "static using" would make C# more
OO, just that it would make life better in some situations -
specifically when writing math-intensive code.
Just because the code reads like old code from the good ol' times,
doesn't make it FIT in the surrounding code it is placed in,
necessarily.

It's not that it reads like old code, it's that it reads like a
formula you might see in a book.

I've recently been using the Haversine formula to calculate distances.
It's described at
http://en.wikipedia.org/wiki/Haversine_formula

The C# code to calculate it is hard to verify as accurately
representing the formulae described on the page, because there's so
much extra cruft involved.

Maths code frequently represents implementations of formulae written
down elsewhere. The ease of *that* translation is often more important
to me than the OO purity of the resulting code.

Unless you propose that the maths world starts becoming OO as well,
there will always be a tension - but in my experience the code is
easier to read by sacrificing the OO-ness in order to make the code
look closer to the written form.
Yes, because the preferred version clashes with
SomeType t = ClassMethod(val);

when we see this kind of code in a C# class, we KNOW that
'ClassMethod' is either in this class or in its supertype. It's not a
class defined elsewhere.

Only because "static using" isn't an option at the moment! Yes, if
this were overused it would be horrible - but in the specific case of
using it for maths, I don't believe there's a problem at all. How many
Sin and Cos methods have you written?
IMHO any reliance on intellisense for readability of code is bad,
because code should be clear from its construction, not because you
have fancy tools at hand. The next step will be that 'code is perfectly
clear if you have resharper x.y, coderush vZ etc. installed and setup
like user ABC.'.

So as Ben suggested, you don't use any using statements at all? Do you
find *they* reduce readability? If not, why not? They introduce
exactly the same sort of potential ambiguity, so why would you reject
"using static" but accept a normal "using"?
As I see 'readability' as the term for: the reader understands what's
been written perfectly, I don't really see how
double d = Math.Sqrt(val);

is less readable than
double d = Sqrt(val);

Everywhere I've ever used Sqrt, it's obvious from the context that I'm
interested in maths functionality. The more extraneous information
that's present, the harder it is to read the code.
simply because Math.Sqrt() tells the reader which Sqrt is called: the
one in the Math class. Simply calling Sqrt() is less clear, because it
could be in the class or supertype OR it could (if TS' suggestion is
added) somewhere in the classes of the scope data imported by the using
statements. IMHO not a thing you'd want to have. (Sqrt is pretty
obvious what it does, a simple thing, but a method which is pretty
complex and will call a lot of other methods, it's not that clear).

Which is why you'd have to use it sparingly, of course. I'd rarely use
it outside System.Math, although in Java I found some other uses which
give DSL-like capabilities rather nicely.

Jon
 
B

Ben Voigt [C++ MVP]

Jon Skeet said:
On Jun 8, 9:37 am, "Frans Bouma [C# MVP]"

So, because that set of using statements makes it already less
clear,
you're perfectly OK with making it VERY unclear for the reader with
further scope increases?

double d = Sqrt(foo);

where does 'Sqrt(foo)' live? I have NO idea.

Do you *really* have no idea, in real life rather than in theory?
Would you not *guess* that it was in System.Math, given no other
information, and considering the context?
Sure, with fancy tooling
I might find the place where this is. But reliance on tooling to READ
and UNDERSTAND code is IMHO a slippery slope I at least don't want to
be on. Code should be understandable and clear for the reader who reads
it. ANY degration to that is IMHO bad. Sure your suggestion might save
a few keystrokes, but it also introduces degration of the clarity of
code written. I simply fail to understand how you can ignore that fact.

We apparently view clarity differently. If I'm working on something
which I know from the context uses trigonometry, then formulae which
just have things like:

double x = Pow(Sin(alpha)+Cos(theta), 2);

have more clarity for me than formulae such as:

double x = Math.Pow(Math.Sin(alpha)+Math.Cos(theta), 2);

Have you read much C# code that requires extensive use of System.Math?
It's horrible currently, and would *greatly* benefit from this. The
ambiguity due to the *possibility* of Cos/Sin/Pow etc is greatly
dwarfed by the *guaranteed* extra cruft of having to prefix everything
with "Math".

Plus the fact that if you ever found a bug in System.Math, or needed a
version that cached results, or anything like that, all you would need to do
is change:

using static System.Math;

to

using static MyLib.CachingMath;

and recompile.

While "using static" isn't anti-OOP, the idea that every call-site should
specify exactly what function is called, is. One of the three pillars of
object-oriented programming, polymorphism, is anti-thetical.
 
B

Ben Voigt [C++ MVP]

Jon Skeet said:
On Jun 8, 9:33 am, "Frans Bouma [C# MVP]"

I'm raised with assembler and C, when I was at the uni we didn't
get
OO languages, just a lot of other paradigms. All nice but not OO.
Reading your examples, I have to admit:
double dist = Sqrt(x*x + y*y);
fits like a glove, I really like it because it's so familiar, as I've
written and read code like that for years and years.

It's not just in code though - it's in anywhere you might see formulae
written down. Yes, there's be a square root sign instead of Sqrt, but
that translation is relatively unintrusive.
What I want to make clear here is that it apparently seems that I
am
actively PROMOTING 10.Sqrt();, but I'm not. I'm just arguing that
theoretically, it would be more OO. Not that that would be BETTER
necessarily.

I don't think anyone's arguing that "static using" would make C# more
OO, just that it would make life better in some situations -
specifically when writing math-intensive code.

Well, I am.

Because nested classes aren't instance members, I'm claiming they should be
visible through static using as well. That allows passing a set of type
parameters to a whole group of classes at once, which I'm also claiming is a
useful application of generics. Everyone thinks of generics in terms of
either avoiding unboxing, or polymorphism, whereas I am trying to make the
point that they can break dependencies even when the generic parameter will
take only one type at runtime. Furthermore, I think generics ought to have
an attribute, that causes the JIT to optimize each version separately for
reference types, just as it already does for value types. There's no reason
that Dictionary shouldn't be able to inline GetHashCode() in a lot of cases.
 
B

Ben Voigt [C++ MVP]

So, you suggest this kind of code is good?
public class Foo
{
private Bar _bar;
private string _val;

private class Bar
{
private Foo _container;

internal Bar(Foo container)
{
_container = container;
}

public string GetVal()
{
return "Bar" + _container._val;
}
}

public Foo()
{
_bar = new Bar(this);
_val = "Foo";
}

public string Do()
{
return _bar.GetVal();
}
}

where bar accesses private members of Foo?

why go that route? Isn't that asking for trouble? Sure, it's possible
but why not create properties and access Foo's code through that? It's
not as if Bar is placed elsewhere, the code is inside Foo anyway.

Sure, in these kind of cross-referencing code, just having to refrence
to '_val' instead of _container._val, can be less typing, but I find it
obscure. Just because a nested type is inside the surrounding type
doesn't make the code (IMHO) semantically part of the surrounding type.
At least, I find it leaky. Sure it's possible, but that doesn't make it
more readable.

There are cases where that kind of code is definitely called for. The BCL
has all kinds of nested classes, many of which are appropriate. Among other
things, anonymous closures are really nested classes.

The key is to use containment where appropriate.

One use case for "static using" involves nesting a number of classes inside
a generic class which has no private members (possible private classes).
This is similar to a namespace, except (1) you now have a finer level of
local class than "internal", and generics are supported.

Take a look at System.dll. There are a ton of internal classes that would
be much better bound to a tight group of classes that use them and each
other. But that's not possible until we get the same ability to reference
nested classes via using that we currently have for namespace members. (I'm
not suggesting that System.dll would be reorganized, but new code could be
modularized much better).
 
B

Ben Voigt [C++ MVP]

Ben Voigt said:
So, you suggest this kind of code is good?
public class Foo
{
private Bar _bar;
private string _val;

private class Bar
{
private Foo _container;

internal Bar(Foo container)
{
_container = container;
}

public string GetVal()
{
return "Bar" + _container._val;
}
}

public Foo()
{
_bar = new Bar(this);
_val = "Foo";
}

public string Do()
{
return _bar.GetVal();
}
}
[snip]

There are cases where that kind of code is definitely called for. The BCL
has all kinds of nested classes, many of which are appropriate. Among
other things, anonymous closures are really nested classes.

I meant with the exception of identifiers starting with underscore, which
breaks any reasonable code standard (because any cross-language standard
must reserve those identifiers to the compiler vendor if even one language
does).
 
F

Frans Bouma [C# MVP]

Jon said:
On Jun 8, 9:37 am, "Frans Bouma [C# MVP]"

So, because that set of using statements makes it already
less clear, you're perfectly OK with making it VERY unclear for the
reader with further scope increases?

double d = Sqrt(foo);

where does 'Sqrt(foo)' live? I have NO idea.

Do you really have no idea, in real life rather than in theory?
Would you not guess that it was in System.Math, given no other
information, and considering the context?

I don't want to 'guess', Jon. That's the whole point. Of course, any
math method likely will be in Math, though the world is bigger than the
set of methods in Math. Of course, with 'Sqrt' it's pretty obvious
where that method might be located, however Validate(myCustomer) is a
bit less clear.

So, IMHO the example you're pushing is actually an incredibly narrow
scope, but the feature required to use that example as discussed won't
be used solely for very narrow scoped methods, but for a lot more
methods. I then say: it will give more problems than it solves.
We apparently view clarity differently. If I'm working on something
which I know from the context uses trigonometry, then formulae which
just have things like:

double x = Pow(Sin(alpha)+Cos(theta), 2);

have more clarity for me than formulae such as:

double x = Math.Pow(Math.Sin(alpha)+Math.Cos(theta), 2);

Sure, though is that in general the case with any random method, or is
it just more clear because the methods in the example are clearly math
related routines so there could be just one place where they'd be
located?
Have you read much C# code that requires extensive use of System.Math?

No, last time I did geometry related code was in C++ some years ago.
It's horrible currently, and would greatly benefit from this. The
ambiguity due to the possibility of Cos/Sin/Pow etc is greatly
dwarfed by the guaranteed extra cruft of having to prefix everything
with "Math".

In THIS particular example, I see your point, but IMHO it's also the
only example or perhaps one of the very few examples which would make
this feature worth having. IMHO, what the cause of this problem is is
that a piece of logic has to be formulated in language L1 which uses
paradigm P1, but the piece of logic is far better expressed in language
L2 which uses paradigm P2. Because L1 is the language of choice, the
logic has to be written in a way which is less expressive.

I.o.w. a way to have any DSL D inside C# and where context awareness
is possible inside D and C# would be very welcome. But that's not going
to happen, see the way how they added Linq instead of adding a DSL
awareness and WITH that Linq. That same DSL awareness then would have
given you the ability for formulate the formulas in a language much
more expressive for that than C# and at the same time wouldn't butcher
C# with features which are actually a big burden for a lot of other
situations than the situation it would be handy for.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

Frans Bouma said:
I don't want to 'guess', Jon. That's the whole point. Of course, any
math method likely will be in Math, though the world is bigger than the
set of methods in Math. Of course, with 'Sqrt' it's pretty obvious
where that method might be located, however Validate(myCustomer) is a
bit less clear.

Which is why it would be a bad idea to use it for Validate.

Here's another example, without changing anything. If I write a method
called "DoSomething" then wherever I use it, I've either got to guess
what it does or consult the documentation (which would usually be via
Intellisense).

What's my answer to this? Naming methods sensibly.
So, IMHO the example you're pushing is actually an incredibly narrow
scope, but the feature required to use that example as discussed won't
be used solely for very narrow scoped methods, but for a lot more
methods. I then say: it will give more problems than it solves.

To which I say: only if used incredibly stupidly.
Sure, though is that in general the case with any random method, or is
it just more clear because the methods in the example are clearly math
related routines so there could be just one place where they'd be
located?

It's because it's clear, certainly - and I wouldn't recommend using it
in any cases *other* than where it's clear.
No, last time I did geometry related code was in C++ some years ago.

I suspect you'd be more in favour of the feature if you had had to
experience the nastiness which requiring "Math." presents.
In THIS particular example, I see your point, but IMHO it's also the
only example or perhaps one of the very few examples which would make
this feature worth having. IMHO, what the cause of this problem is is
that a piece of logic has to be formulated in language L1 which uses
paradigm P1, but the piece of logic is far better expressed in language
L2 which uses paradigm P2. Because L1 is the language of choice, the
logic has to be written in a way which is less expressive.

Absolutely. But this feature would help things enormously.
I.o.w. a way to have any DSL D inside C# and where context awareness
is possible inside D and C# would be very welcome. But that's not going
to happen, see the way how they added Linq instead of adding a DSL
awareness and WITH that Linq. That same DSL awareness then would have
given you the ability for formulate the formulas in a language much
more expressive for that than C# and at the same time wouldn't butcher
C# with features which are actually a big burden for a lot of other
situations than the situation it would be handy for.

Well, the situation I was thinking of is actually Hibernate and its
Criteria API, but I can't find the page that gives a nice example at
the moment.
 
B

Barry Kelly

Frans said:
Jon said:
On Jun 8, 9:37 am, "Frans Bouma [C# MVP]"

So, because that set of using statements makes it already
less clear, you're perfectly OK with making it VERY unclear for the
reader with further scope increases?

double d = Sqrt(foo);

where does 'Sqrt(foo)' live? I have NO idea.

Do you really have no idea, in real life rather than in theory?
Would you not guess that it was in System.Math, given no other
information, and considering the context?

I don't want to 'guess', Jon.

You still have to guess that it's System.Math, and not some other Math
:)

FWIW, I think OO is overrated, has been for a long time now. It's on the
wane, as things become more normal.

-- Barry
 
F

Frans Bouma [C# MVP]

Jon said:
Which is why it would be a bad idea to use it for Validate.

Here's another example, without changing anything. If I write a
method called "DoSomething" then wherever I use it, I've either got
to guess what it does or consult the documentation (which would
usually be via Intellisense).

What's my answer to this? Naming methods sensibly.

Sure, though if the language has the construct of static methods, the
class name becomes part of the method name (IMHO), in such a way that
the scope in which the method operates is described by the class name
so it's not necessary to add that description in the method name itself.

FOr example, String.Copy(). It's a static method. Using the proposed
mechanism, I end up with code like:
myVar = Copy(myOtherVar);

In a procedural language, one wouldn't use 'Copy'. One would use
CopyString() for example as it copies a string. But because the method
is statically defined on String, CopyString is redundant, Copy is
enough information, as 'String' is already specified.
I suspect you'd be more in favour of the feature if you had had to
experience the nastiness which requiring "Math." presents.

I guess :)
Well, the situation I was thinking of is actually Hibernate and its
Criteria API, but I can't find the page that gives a nice example at
the moment.

We use a similar API, to get compile time checked queries (without
having Linq around ;)). Like:
IPredicate p = (CustomerFields.CompanyName == "BigCorp Inc");

The perfect DSL for querying is SQL, it's however set oriented, not
procedural nor OO. That friction has to be overcome somehow, if you
want to specify what you want in C# if you can't use SQL. IMHO the same
with mathematical procedures in an OO environment. Cutting up the
target language to become a language for another paradigm is IMHO
making the language very weak and open for abuse. Better is to enable
interoperability in a transparent form so you can write a complex
formula in the DSL which does that best, evaluate it with that DSL and
refer to the result in normal C#. And back, refer to values in the C#
program in the formula.

It would get you what you want, and in the best possible form. However
I'm not sure if we'll see it in a short timeframe in C#, unless things
like JRuby will get that much traction that MS has to act upon it. (For
the JRuby impaired readers: JRuby is an enviroment which allows you to
write ruby code and java code and let them interoperate on eachother:
call java code from within ruby, call ruby code from within java and
refer to elements living in the other language space).

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

Frans Bouma said:
Sure, though if the language has the construct of static methods, the
class name becomes part of the method name (IMHO), in such a way that
the scope in which the method operates is described by the class name
so it's not necessary to add that description in the method name itself.

FOr example, String.Copy(). It's a static method. Using the proposed
mechanism, I end up with code like:
myVar = Copy(myOtherVar);

Only if you abuse the feature though. There's nothing to force you do

static using System.String;

and indeed I wouldn't recommend it.
In a procedural language, one wouldn't use 'Copy'. One would use
CopyString() for example as it copies a string. But because the method
is statically defined on String, CopyString is redundant, Copy is
enough information, as 'String' is already specified.

Right - so where it's not clear, you don't use the feature.

We use a similar API, to get compile time checked queries (without
having Linq around ;)). Like:
IPredicate p = (CustomerFields.CompanyName == "BigCorp Inc");

The perfect DSL for querying is SQL, it's however set oriented, not
procedural nor OO. That friction has to be overcome somehow, if you
want to specify what you want in C# if you can't use SQL. IMHO the same
with mathematical procedures in an OO environment. Cutting up the
target language to become a language for another paradigm is IMHO
making the language very weak and open for abuse. Better is to enable
interoperability in a transparent form so you can write a complex
formula in the DSL which does that best, evaluate it with that DSL and
refer to the result in normal C#. And back, refer to values in the C#
program in the formula.

In this case it doesn't make the language "very weak" but enables a
fluent interface which reads quite naturally. (It doesn't particularly
read like SQL, but that's okay.)
It would get you what you want, and in the best possible form. However
I'm not sure if we'll see it in a short timeframe in C#, unless things
like JRuby will get that much traction that MS has to act upon it. (For
the JRuby impaired readers: JRuby is an enviroment which allows you to
write ruby code and java code and let them interoperate on eachother:
call java code from within ruby, call ruby code from within java and
refer to elements living in the other language space).

Have you not heard about DLR and IronRuby?

http://blogs.msdn.com/hugunin/archive/2007/04/30/a-dynamic-language-
runtime-dlr.aspx

http://www.iunknown.com/2007/04/introducing_iro.html
 
F

Frans Bouma [C# MVP]

Jon said:
Only if you abuse the feature though. There's nothing to force you do

static using System.String;

and indeed I wouldn't recommend it.

Ok, though IMHO (but we differ in opinion on that ;)) this feature's
usage is usually (in my eyes) an abuse.

Yes I have, though afaik, the DLR doesn't support C#, nor is it giving
me (but I might have understood it wrong) true language integration
between two languages.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

Frans Bouma said:
Ok, though IMHO (but we differ in opinion on that ;)) this feature's
usage is usually (in my eyes) an abuse.

How can we talk about "usually" when we don't know what's "usual"?
Until we've seen how often such a feature would be used in reality, we
can't know what proportion of such uses is abusive, even if we agree on
what constitutes abuse.

What I *will* say is that the feature exists in Java (v5+) and most of
the times I've seen it used have been beneficial.
Yes I have, though afaik, the DLR doesn't support C#, nor is it giving
me (but I might have understood it wrong) true language integration
between two languages.

The DLR extends the CLR as far as I'm aware, so it can call code
written in C#. I haven't looked in enough detail to see whether C# can
call code written in, say, IronRuby - but I'd certainly hope so.

Personally I'd love to see an equivalent of Groovy but for C# - I think
Boo is as close as it comes at the moment, but who knows what may be
possible on the DLR...
 
Top