|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> wrote:
>>>> I don't have to guess. I read the code.
>>> Even a couple of years from now?
>
>> Even after someone has gone and changed it from a global to a member
>> variable without updating all the names, yes. :-)
>
> You magically know from the name of the variable that someone changed its
> scope?
No. I'm saying if you name the variable "gCounter" everywhere, and then
decide you really need to be able to have more than one instance, then you
better rename it to mCounter everywhere you use it, or you've made it even
*harder* to understand than if you hadn't flagged it at all.
Basically, your prefixes are comments, and wrong comments can be worse than
no comments.
Now, I already granted that such doesn't happen very often, but that's the
point I'm making here. Let it go long enough with sufficiently careless
programmers, and you'll have this problem. Using an IDE will prevent that
problem.
> As I said, you are just acknowleding that there *is* a problem in the
> naming which has to be solved by using an IDE.
No. I'm acknowledging that if your class is so complex that you can't easily
figure out where the variable is declared, chances are good that a naming
convention isn't going to help all that much.
Or, to put it another way, I've tried it. It didn't do anything for me. It
didn't help my understanding, even when reading code written by the guy who
did things that way. That doesn't mean it's right or wrong. It just means
that asserting it's always appropriate is probably incorrect. If I can't
figure out that a variable is a member variable from its name without the
flag, chances are I'm picking a crappy name for that member variable.
Something like "mCounter" for example.
For example, "CounterOfInstancesCreated" is obviously going to most likely
be a class-level static variable. "CounterOfMenuEntries" is probably an
instance variable in the class "Menu". It probably sizes the array
"MenuEntries" in the class Menu. "CounterOfEntriesUpdatedSoFar" is probably
a local variable. "CounterOfEntriesToRemove" is probably a function argument.
>>> A subclass cannot refer to a superclass' members because it has no access
>>> to them. They are private.
>
>> I fail to see how a superclass with all members private can be useful.
>> Unless you're using "member" to mean "instance variable" rather than
>> "instance function" or something.
>
> This whole thread has been about variables. Nobody has talked about
> functions.
Well, *I* was. I can't help you started putting arbitrary limitations on how
you use your language without telling me. :-)
Now, if you wanted to argue that you put "m" in front of private local
variables to distinguish them from properties, you might have a point there.
But then that defeats the purpose of using properties.
>>> A member variable in the protected section is as bad as in the public one,
>>> hence you don't put member variables in the protected section.
>
>> Why?
>
> Because from the point of view of the derived class the member variable
> is public, and thus with all the drawbacks.
You haven't told me what the drawbacks are. I suspect the drawbacks are
specific to languages where function calls don't look like variable
accesses. If your getters and setters look like variable assignments, why
would it be problematic to have actual variables in the public interface?
>> And what about member properties?
>
> Getter and setter functions are a separate issue. We are not talking
> about member functions here. (Or at least I am not.)
OK. Since pretty much all my non-private variables are accessed via
getter/setter functions (i.e., properties), then I don't see a problem here.
>> It doesn't. But the syntax is that of a variable.
>
> If you want to use confusing syntax, that's up to you. ("Not only do not
> I know if this is a local, global or member variable, I don't even know if
> this is actually a property of this class or any of its base classes." Way
> to add even more confusion.)
Well, (A) it's part of the language, so it's not really confusing syntax,
and (B) it's hiding whether it's a variable or a function for exactly the
same reason you're making private variables private.
>> I.e.,
>> x.a = 27;
>> does not tell you whether "a" is a variable or a function in C#.
>
> Since classes don't have public member variables, it is a function (even
> if the syntax is confusing). Haven't you learned already?
Um, sorry. "Warp's C++ programming style" doesn't define C# syntax, I fear.
> Getters and setters are member functions, not member variables, and hence
> other naming conventions apply to them.
OK.
>> If I have a string that's the title of the menu in a base class, and it's a
>> property that uses variable syntax, what should I name it and how would I
>> refer to it in the subclass?
>
> You use getter and setter functions, which are named with the proper naming
> convention for member functions.
Huh. And the proper naming convention for that in C# is to make it look like
a member variable. Funny that.
>
>>> Odd question. By calling a member function to set it up, of course.
>
>> I *am* calling a member function to set it up. The member function is
>> invoked by me saying
>> Title = "Game Options";
>
> Well, if you deliberately want to make it ambiguous and confusing, that's
> up to you. But remember that others may need to read and understand your
> code. That "Title" doesn't make it at all obvious what it might be and
> where it might be declared.
There's nothing in front of it (like this. or something) so it's a property
or variable declared in this class or a superclass thereof. It's really not
confusing or ambiguous.
> Abstraction. A member variable is part of the internal implementation of
> the class, while a public member function is part of its abstract public
> interface which should usually reveal as little as possible about the
> internal implementation details of the class.
Well, there ya go then. If I declare a property, then it's a function that
syntactically looks like a variable. It reveals very little about the
implementation, in that there need not be a backing variable at all.
Plus, if I make it a variable, technically I can replace *that* with a
function call in the future, with a simple recompile of the users of that
code, because the syntax is the same.
A property says "if you can set this and get this, then what gets returned
from the 'get' is almost certainly what you assigned with the 'set'."
It's only confusing if you don't know the language, and no more confusing
than having to find which implementation of a virtual function a given call
site invokes.
>> Is a getter/setter pair syntactically invoked like a variable and whose
>> underlying storage is inaccessible even to the class declaring the
>> setter/getter a member variable or a member function?
>
> I'd call it confusing.
That's because you're not used to it. It's basically a way of defining a
getter/setter pair that makes it clear it's a getter/setter to the caller.
> If you expose a member variable, you are exposing an internal
> implementation detail
No I'm not. Part of the API for a menu screen is the title of the menu and
the color it's drawn in. That's not an implementation detail.
> It's not a compiler-technical issue. It's an issue of program design.
> It has nothing to do with a specific programming language.
But you said right there it is, you see. If the syntax for assigning to or
from a variable is the same as the syntax for calling a getter or setter,
then you can trivially change from using a variable to using functions in
the future.
It would be like me arguing that C++ functors should have a different syntax
than functions for invocation, because otherwise it's confusing. No, that's
the *point* - if the user has to know whether it's a property or a variable,
*then* your design is bad.
>> Indeed, having functions unassociated with classes and having global
>> variables at all is a much worse OOP design than having variables exposed in
>> the class interface.
>
> Well, usually you shouldn't have global variables in a well-designed
> program. As for not having free functions, I don't quite get it. What's
> wrong with having some convenience functions?
I didn't say there's something wrong. I said it's not OOD.
>> But I don't. I can look up whether it's a global or not just fine without an
>> IDE. I don't feel the need to encode that into the names, is all.
>
> That's the problem: You have to "look it up". The name itself tells you
> nothing.
I have to look up whether it's an int or a float, too. I don't encode that
into the variable name either. Certainly if you're arguing that "mCounter"
is good style, then surely "m_pszTitle" is good style.
> You have to study the rest of the code in order to understand what
> the function is doing,
I would argue that *this* is the problem. :-)
It's also a problem that properties eliminate for getter/setter code: You
know from the fact it's a property what it's doing. Indeed, the whole reason
C# has properties is to eliminate the whole problem of "this used to be a
variable and now I have to do something to calculate it instead" or vice versa.
> and the name of the variable is giving you no hints
> on where you might start looking.
>
> However, if you see from the name that it's eg. a member variable, then
> there aren't many places you have to look for it.
There's already not a lot of places I have to look for it. If I stick with
only having variables be private, I have to look in the function arguments,
the local declarations, and the member variables of the class I'm in. The
function arguments and local declarations are right next to the code using
the variable.
> This becomes especially useful when there are dozens of different variables
> being referred to in a function.
I'd also argue that's a problem with your design, unless you're actually
doing something sufficiently complicated that you're going to have to look
up the types of the variables too. If I'm manipulating dozens of member
variables in a function, it's likely either a list of relatively independent
statements (like initializing dozens of parameters to their defaults) or a
function I should be refactoring.
>>> Code readability should not rely on IDEs. It's precisely that reliance
>>> that produces unreadable code which is hard to understand.
>
>> I agree. However, I'm not depending on the IDE to make the code readable.
>
> Seemingly you are, given how much you advocate using an IDE to look up
> variable definitions.
So when you see mCounter in your code, how do you know what type it is?
I don't rely on the IDE to look things up. But since it's there, I use it.
>
>>>> I'm generally against redundancy in programs.
>>> Are you against readability?
>
>> You're begging the question.
>
> I'm not. You are against redundancy. Are you also against redundancy when
> it makes the code more readable?
No, but you're assuming that your form of redundancy makes the code more
readable simply by asking the question. (I can't see any reason why you
would ask such a question except to imply that the redundancy you advocate
makes code more readable, which is exactly what we're discussing. However, I
may be misreading why you asked such a question. But I think not, given that
no reasonable programmer would be against readability, making it either a
rhetorical question or an insult.)
>> Having to resort to a naming convention to tell the reader what you already
>> told the reader is a tell-tale sign that the program could have been written
>> better too.
>
> Haha.
>
>> Especially if you're going to assert that "mCounter" is always a member
>> variable of *this* class.
>
> If it isn't, then your program is badly designed and hard to understand.
Well, we're talking about somewhat different things here, then.
>
>>> Take into account that maybe others will have to read your code, and they
>>> might not have that fancy IDE at hand at the moment, yet they may have to
>>> understand your code. Relying on IDEs for readability is a bad idea.
>
>> I'm not relying on the IDE for readability.
>
> You are making contradictory statements. In one place you say that you
> don't need any special naming conventions because you just use the IDE to
> tell you where variables are defined, and here you are telling that you are
> actually *not* using the IDE for readability.
I don't *need* the IDE to look up variables, and I don't *rely* on the IDE
for readability. Of course, ASCII code without an IDE is less readable than
with an IDE. That doesn't mean *your* solution to not using an IDE is the
best one, or even necessary.
> The type of the variable doesn't help you find its declaration. A naming
> convention telling you where to look does.
But if all member variables are private, I don't need a naming convention to
tell me where to look. If it's not a function argument or a local variable,
it's a member variable.
--
Darren New, San Diego CA, USA (PST)
Eiffel - The language that lets you specify exactly
that the code does what you think it does, even if
it doesn't do what you wanted.
Post a reply to this message
|
![](/i/fill.gif) |