|
Graham.
|
 |
« Reply #15 on: June 24, 2012, 04:43:04 AM » |
|
Yeah, I like that.
I've been thinking about ways to limit access in code. So I'd have some class that on construction gets a pointer to its creator, then restricts access based on who is who. Then I'd extend this class.
Is that what a smart pointer is?
The proper way to do it is to construct and manually pass in the "owner/creator." Having the constructed class go through the call stack to get its creator is kind-of fucked up.... I wouldn't actually do that.
The issue is that you lose static analysis. The compiler can't check it someone is accessing something it shouldn't; only runtime would pick that up. The naming convention would then communicate something to the programmer that the code would only communicate with a possibly overly-thorough read through.
The answer to that issue is to test-suite out the ass. Then if someone has their hands in the wrong place you get test errors, and the programmer doesn't need to care.
Or you could declare who is allowed to create something from within the "creat-ed," statically. You could have a class called, "only can be constructed if you are of type Lover," then extend it. You'd need a pre-compiler that watches out for these kinds of things. It would rock to have intellisense for this.
Aannd we're back to macros.
-----
EDIT: I get the feeling I'm missing something here. I thought about this before and feel like I concluded that you could have static permissions. Ohhhh.... no, here's the solution.
IF you have some class, Penis, and you want Penis to be the only guy who's allowed to... say create class Anus, so that Penis owns Anus, and is thus responsible for destroying it and so forth.... You'd have to create a class called AnusMaster, then make the Anus constructor private to AnusMaster. Then AnusMaster would have a list of who's allowed instances of Anus. Penis is on his list so Penis can get an Anus, no questions asked. When Penis gets an Anus, AnusMaster gives over the destroy responsibilities. Only AnusMaster can transfer these abilities. Then only Penis can destroy the Anus - as normal logic would dictate.
I like that solution better.
Actually, if you still want to see the equivalent of mAnus inside Penis (without using the prefix) you'd have to do some more work. Whatever, programming.
|
|
|
|
« Last Edit: June 24, 2012, 04:57:02 AM by toast_trip »
|
Logged
|
|
|
|
|
Eniko
|
 |
« Reply #16 on: June 24, 2012, 05:07:11 AM » |
|
Microsoft best practices actually also say not to use variable prefixes. IIRC they advocate camel casing for local scope and member variables, and upper case for public/global. Ironically they break their own rule, because they're stuck with their own legacy conventions. Does Mono have prefixes in their code, too?
I've had a lot of discussions with a friend of mine about the camel casing thing, and he maintains that it's too confusing between local scope and members. Personally, I've never had a problem with it, though I guess I can see the potential for inadvertently hiding a member variable with a local one.
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #17 on: June 24, 2012, 05:21:51 AM » |
|
I'll camel-case with first-letter-caps class names. I do_this_way with function names and variables. You can read those a lot faster. I don't mind the slow-down for class names because declaring types and instantiation deserve the emphasis.
Globals are so rare that they don't need a special type. I'll global a constant, and that'll be all caps.
public vs. private seems weird. If you want a difference between member vars and local vars you can prefix. It's not the end of the world.
I don't know what you mean with the camel-casing applying to member vs local. Your friend wants a type differentiation between the two? I think prefixes are better. A type change is too loud.
Honestly, the way it should work is like this. You have a static analysis tool - Visual Studio can do this. You then color-code member variables differently. If you override something it'll be obvious. I should have thought of that before....
I love emacs, and I love static analysis. I'll probably be using Visual Studio's intellisense in the background and bring it through into emacs on my next thing. So I forgot intellisense was the way to go.
EDIT: thisWay vs this_way for read speed is debatable. It might be personal, or maybe I'm just wrong.
|
|
|
|
|
Logged
|
|
|
|
|
EdgeOfProphecy
|
 |
« Reply #18 on: June 24, 2012, 06:25:21 AM » |
|
I've switched back to coding a lot of Objective-C lately, and I've lately taken to postfixing my variable names with _
The reason is a bit Objective-C specific, but generally applicable to other languages.
All variables in a class are internal, and then I write functions to access them externally. There is no such thing in the code as a public variable. If you want to do anything to it externally, you're going to have to use an accessor. While it is totally possible to have public variables in Objective-C, it is very strongly discouraged, and should only be used when there's some tangible benefit to be derived from not going through an accessor.
I prefer the postfixing because I don't actually like clumping up my stuff in the autocomplete lists, and I think it better preserves the naming of things. It's like how some natural languages use particles attached to the end of words to denote what grammatical role that word is playing in the sentence (English doesn't really do this so much). The word itself isn't changed, but it has a little identifying symbol tacked on at the end.
Ultimately, though, I don't think naming conventions are that big a deal, especially if you're working solo. Whatever makes you work efficiently is what you should use. If you're planning on releasing your code as a library, then it could be a good idea to adopt a standard syntax, and it goes without saying that people should try to sync up stylistically if you're collaborating with others. You don't have to go super overboard, but having 3 or 4 distinct naming conventions within the same function definition is pretty bad.
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #19 on: June 24, 2012, 06:45:05 AM » |
|
One day I'll just make a tagging system for code elements. They'd be like attributes. Types would have their own restrictions on which attributes could be applied. Everything would be enforced statically.
You could add whatever kind of property you'd like to something, say a variable. You could say, "this is a private thing," or, "this guy gets used by <x> subsystem," or, "this is world data," or whatever. You could put tags into class definitions if you'd like and all it's instances would inherit them.
Then, I'd hook the tags into intellisense. And then I'd have everybody on the team mess around with custom representations for displaying code elements with each kind of tag. Depending on the type of work you're doing you could flip a switch and "see" the code from a different perspective.
I'd put some productivity measuring stuff in there (long story), have everyone mess around with it, and determine the best ways to represent stuff. People could throw tags around willy-nilly just to see what sticks. Maybe it's useful to see where the thread boundaries are during run-time (with code coloring), or the access of 3 particular classes within a particular area of code when in condition <something or the other> (with more code coloring, fonting, awesome).
Maybe there are different best reps depending on the time of day, or if you're debugging, or you're in a particular section of the code.
Then there are no conventions. People tag stuff, then they can see it however they want. The best representations would circulate. You could enforce things if you wanted to.
|
|
|
|
|
Logged
|
|
|
|
|
Eniko
|
 |
« Reply #20 on: June 24, 2012, 07:09:17 AM » |
|
I don't know what you mean with the camel-casing applying to member vs local. Your friend wants a type differentiation between the two? I think prefixes are better. A type change is too loud. What I meant was this: class SomeClass { private int someMemberVar;
private void SomeFunction() { int someLocalVar; int someMemberVar; // hides SomeClass.someMemberVar } } He prefers prefixing. I disagree. We have long long discussions about it and ultimately neither of us change our minds on the topic. 
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #21 on: June 24, 2012, 07:42:30 AM » |
|
I see. In that case I'd choose a different name for one of the vars. They're technically doing different things. Before defining the local var, the member var already has a meaning inside the function. Overriding it messes with that meaning. The meaning of someMemberVar should be consistent through all your functions. Re-defining inside a function is like saying, "except here." If it's okay to break the rule there, how good is the name to begin with? Either the member var or the local var are better suited for the name. One takes precedence. Having a clash indicates that you're unsure about what the real meaning of your var is.
This is the kind of situation that pre-fixes are sometimes lauded for. If you need a prefix it generally means you have a naming clash, meaning something has been named haphazardly. If you wish to have the duplication anyway, I think using a prefix or not is debatable as you say.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #22 on: June 24, 2012, 07:48:07 AM » |
|
I'll camel-case with first-letter-caps class names. That isn't camel-case, that's Pascal case. camelCase PascalCase
|
|
|
|
|
Logged
|
|
|
|
|
EdgeOfProphecy
|
 |
« Reply #23 on: June 24, 2012, 07:52:41 AM » |
|
I see. In that case I'd choose a different name for one of the vars. They're technically doing different things. Before defining the local var, the member var already has a meaning inside the function. Overriding it messes with that meaning. The meaning of someMemberVar should be consistent through all your functions. Re-defining inside a function is like saying, "except here." If it's okay to break the rule there, how good is the name to begin with? Either the member var or the local var are better suited for the name. One takes precedence. Having a clash indicates that you're unsure about what the real meaning of your var is.
This is the kind of situation that pre-fixes are sometimes lauded for. If you need a prefix it generally means you have a naming clash, meaning something has been named haphazardly. If you wish to have the duplication anyway, I think using a prefix or not is debatable as you say.
It's not really overriding anything. Whenever you're using a variable name in code, you're requesting that variable in the most immediate scope. The compiler (or runtime environment) will drill through the scope layers until it finds the closest variable, and that will be what you're manipulating. Having variables with the same name in different scopes is totes legit, we do that all the time with having the same variable names in different classes. All that this.foo does is specify the scope that you want to reference. (Disclaimer, languages do handle scope resolution differently, so this may not be true for every language. However, far as I know languages do handle scope resolution consistently, which is the important bit). Whether you name your variables uniquely or not, you're not changing this behavior. It's just that a lot of people aren't used to thinking about variable access in this way (or don't know that's how variable access works), so they get confused about what's going on. You haven't changed any rules at all, so I certainly see no problem with it.
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #24 on: June 24, 2012, 09:07:28 AM » |
|
Yeah, Pascal casing. I just couldn't remember what it was called.
If you as by-convention access member variables using "this." or whatever, then I agree with you. There isn't technically a hard rule here. However, the implication is that access is being made to a member variable without "this". Maybe "override" isn't the right term; maybe precedence is better.
... If I have a loop, and that loop has a variable bar inside it, and outside that loop, before it, we have a different bar. Here I don't see an issue necessarily. If the loop is long I'd have a problem, because it could easily become unclear which bar you are referring to. But if length is the determining factor... it suggests you shouldn't use bar in the loop at all, and that doesn't make sense.
If you could never re-use a name in a nested scope then the idea of scope would be partially pointless. The real value of scope is deconstruction, not for taking precedence over previously declared variables. At least that's how I see it. Taking precendence is a necessary corollary (obviously...).
For short-loops the issue is debatable. I've re-used names inside loops and gone back and changed it when I realized that each name actually referred to something different in their respective contexts. But that isn't the case every time. At least I'd say it's something I think about.
With functions the story is different. If you have a handful of classes accessing a member variable without explicitly stating "this," it would be weird to mix the meaning of that variable's name. I guess I just don't like the idea of doing it haphazardly. Naming clashes is always a big warning sign. If you have intellisense then there isn't as big of a deal, maybe.
A function's scope is its own little world... ok. The class is its own scope.
The issue isn't about robustness, it's clarity. (I don't even know what I'm talking about anymore). You pick a name because its the best name. When you get into a position where you're looking at a line of code and you can't tell the defining scope of a variable just be looking at it, that's a lack of clarity. Without intellisense you're scanning around to find out whether a variable refers to a local or a member.
.... I can't make up my mind here. I'll put it this way. Most of the time I see this issue, with a name clash in a nested scope, it's because one, or more commonly both, name(s) are too general. A prefix doesn't seem perfect. I wouldn't hurt someone for using them, though I wouldn't use them myself.
A member variable is pretty important to a function. If a member variable isn't important to a function then that function probably shouldn't be there. If a function needs to declare a variable with a name that clashes with a member variable, then it begs the question: how is the new variable exactly the same from that function's perspective?
If the two variables serve the same the purpose why are there two? If they serve slightly different purposes, then why do they have the same name? Each name should best reflect its relationship with whoever has access to it, namely the function in question. Most of the time when the names are the same it's because they're both generalizations of their namees' purposes. This isn't terrible, but it often indicates a broken understanding of the purpose of one variable or the other.
Name clashes indicate a contradictory understanding of the relationship an item (function/var/class/module) has with the things that can access it. Sorting naming out often leads to better abstractions, better abstractions lead to clearer code, clear code is the basis of flexible and reliable code... blah, blah. When I start playing big games that don't bug out or slow down, or are actual steady improvements of long-lasting engines; or I can access my network in Windows without having to wait forever, then I'll believe we abstract well enough. Until then I'm going to fret over naming. ... Also, load times. Holy Fucking Shit. 2012.
|
|
|
|
« Last Edit: June 24, 2012, 09:58:37 AM by toast_trip »
|
Logged
|
|
|
|
|
Evan Balster
|
 |
« Reply #25 on: June 24, 2012, 11:51:18 AM » |
|
http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifierIt's fine to declare _booger as a member variable, local variable, or function parameter. I was bitten once by using "_S" as a template parameter, though; it was some kind of macro. I prefix constructor arguments with the same names as the members they initialize with underscores frequently, like so: Point(float _x, float _y) : x(_x), y(_y) {} I prefix member variables with underscores when their identifiers are displaced by similarly-named accessors and mutators, like so: class Pitch { public: float rate() {return _rate;} void rate(float rate) {_rate = rate;} float tone() {return ToSemitones(_rate);} void tone(float tone) {_rate = Semitones(tone);}
private: float _rate; } These simple practices have served me well over the years.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #26 on: June 24, 2012, 04:22:08 PM » |
|
As I mentioned in my first post, no it isn't. Identifiers beginning with an underscore are reserved in the global namespace for any purpose, including macros, Declaring _booger as a member variable, local variable, or function parameter is not safe. C99 section 7.1.3 states that these names are reserved for identifiers, 6.4.2.1 states that identifiers represent any of the entities identified in section 6.2.1, and 6.2.1 specifically calls out macros. C++ inherits all of these rules. Leading underscores are never safe in C or C++.
|
|
|
|
|
Logged
|
|
|
|
|
Klaim
|
 |
« Reply #27 on: June 24, 2012, 08:08:00 PM » |
|
Also, then can make code harder to read. Today I'm trying the experiment I was talking about. Wish me luck. 
|
|
|
|
|
Logged
|
|
|
|
|
Klaim
|
 |
« Reply #28 on: June 24, 2012, 08:23:19 PM » |
|
Ok I stop here. (few minutes later...)
I have several types that expose name() functions and have a name member. I can't think of any good naming that would not be a PITA each time I read it.
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #29 on: June 24, 2012, 09:45:28 PM » |
|
Yeah, in that case, without macros - which in C I don't recommend - I would do the same thing.
|
|
|
|
|
Logged
|
|
|
|
|