Sign in to follow this  
RyanZec

Kernighan and Ritchie (or K&R) and Other Coding Standards Discussion.

Recommended Posts

RyanZec    124
I don't know why but alot of the stuff in the K&R coding standards seem wierd to be and wanted to get your guys opinions. I will just go through each section that i disagree which. Naming: K&R : "A variable or function name should be sufficient to understand the meaning, while remaining concise. The shorter the lifespan or scope of a variable, the shorter its name should be; conversely, the more important a variable, and the more places it is used, the more descriptive that name should be." I really don't think naming a variables shorter if it is not used as much is really a good idea. I mean K&R sytle would have a variables named nelems which if i where jsut to look at that, I would be a little confused and would not know what it mean right away but I would name the name variable number_of_elements and to me that is much more clear becuase i knwo right away that it is the number of elements(i may not know what elements it is referring to but I would just need to look at the code around quickly, alot wuicker then i would if i needed to figure out what nelems means). Indentation and Spacing: This is the example on how to do it K&R style:
for (i=0; str[i] != '\0'; i++) {
	if (str[i] == ' ') {
		if (strcmp(&str[i+1], "static") == 0) {
			...
		}
		else {
			if (strcmp(&str[i+1], "final") == 0) {
				...
			}
		}
	}
}

And this is how I would do it:
for(i=0; str[i] != '\0'; i++)
{
	if(str[i] == ' ')
	{
		if(strcmp(&str[i+1], "static") == 0)
		{
			...
		}
		else
		{
			if(strcmp(&str[i+1], "final") == 0)
			{
				...
			}
		}
	}
}

For me, my way just seems alot clearer and cleaner. The major issue with K&R way is when I see major nested if statements. I have see some if statements that written in the K&R style, I just don't know where any if statement ends just by looking at the code but my way I can clearly see it. Another thing is the space between the statement and the parameters like if () seem like a waste of a space to me, it do not do anything good for the reading of the code. Comments: I for the most part agree with K&R. Other Things I See That I Am Not Sure If It Part Of K&R: One common thing i see is when declaring variables/function/classes they are declared like firstFunction, secondFucntion, firstVariable, secondVariable. For me the way I declare variables/function/classes are all different so i know which is which just by looking at the name. I declare variable in all lowercase and underspace for spaces, I declare function which all words first letter capped, and i delcare classes like function just with a 'C' in front of it. also when i declare a class variable i like to add "_object" to the end of it becuase that way i know it is a object just by looking at it. Also with any members(class variables), i use a underscore infront of it that way i know when i am dealing with member inside fo a class function if i happen to have a parameter that is the same name(usually with Set functions). Here is an example of all that.
//variable
int test_variable;

//function
void function DoSomethingFun()
{
}
//class
class CFile
{
	public:
		void SetTest(int test)
		{
			_test = test;
		}	

	private:
		int _test;
};

//sorry my c/cplusplus is a bit rusty becuase i have been doing php for the pass 1-2 years
CFile file_object = new CFile;

You guys disagree with me on any of these points, just like to know what you guys code standards are.

Share this post


Link to post
Share on other sites
Colin Jeanne    1114
My coding standards match whatever the coding standards are of the project I'm working on. Period.

If it's a personal project, then I'll pick whatever set of standards I prefer at the time and stick with it. I have different coding standards for different projects - it really doesnt matter what style you use.

Share this post


Link to post
Share on other sites
ToohrVyk    1596
Indentation, case, format, bracket placement, comment placement: I don't care. I can read all of them with equal ease, I can write all of them with equal fluency, and most of these can be transformed by automatic tools anyway. Just use the same throughout the code.

Variable naming: one-word names whenever possible. Two-word names if necessary. Three-word names should have a very strong justification. The vocabulary in a project should be as small as possible, with the common abbreviations where useful (numMatches). I use no correlation between the name of the variable and its scope.

Setters: I consider these to be prime indicators of bad design (not bad coding practices). Less than 1% of my classes need even a single setter.

Warts: I am guilty of the foo_t wart at the end of my types, especially when they are template arguments, because emacs likes them (for syntax highlighting). I also use the this-> prefix to indicate member variables and functions where ambiguous to the reader (which is in all ways superior to the underscore prefix). I don't use any other warts in my code, because they don't provide me with any other information I would want. In particular, I find no need for the _object suffix, since (with very few exceptions) all my variables represent objects anyway. Perhaps I should consider a _not_object suffix? [grin]

Share this post


Link to post
Share on other sites
LessBread    1415
Kernighan and Ritchie's book was first published in 1978 and then again in 1988 [1]. The 1988 edition was supposedly an update in light of the C89 specification. Since then the C99 specification has been issued but K&R haven't issued an updated book. So if your style isn't like their style, don't worry about it.

Share this post


Link to post
Share on other sites
Bregma    9214
Quote:
Original post by RyanZec
I don't know why but alot of the stuff in the K&R coding standards seem wierd to be and wanted to get your guys opinions. I will just go through each section that i disagree which.


vi not emacs

cpio not tar

Atari not Amiga

Beta not VHS

Sheesh, kids today. Gettin' so's it's too easy to start a religious war.

Share this post


Link to post
Share on other sites
NotAYakk    876

template<
typename foo,
int n
>
void bar( foo f ) {
if (f==n) {
// ...
} else if (f==2) {
// ...
}
switch (f()) {
case alpha: {
// ...
} break;
case beta: {
// ...
} break;
default: {
// ...
} break;
}
}

void baz(
error* err,
space* contained_space_,
dimension* dim_,
int count, int width, int height,
logger* log = 0, tracker* track=0
)
{
// ...
}
template< int n >
struct worker:
public virtual slave,
public virtual charlie,
public virtual reference_count
{
public:
// ...
private:
// ...
};

template<int n> worker<n>* clone(worker<n>* inp) {return inp->clone();}



But really, style is what looks good and is clear.

Share this post


Link to post
Share on other sites
Valere    248
From where I stand, what matters most is that the style for a given project be logical and consistently applied. Details are just that.

If your looking for what others like:

- I prefer CamelCase for word breaks in function and variable namin
- Newlines for blocks. I agree, it's easier to read. I don't agree on the nesting. If you do see several levels of nesting, you should probably be refactoring that code.
- Verbose variable and function names. It's a good way to gauge if something needs to be refactored if it's called DoThisThenThatAndThatOtherThing(10 parameters). I don't agree with K&R's rule of scope. I name things for what they do.
- I use m_ to denote class members, HOWEVER
- For prefixing of variable names, you might do well to do some reading up on Systems Hungarian vs Apps Hungarian and the various pitfalls both can imply. Joel has a pretty complete overview and a practical argument for Apps hungarian here . I like the use of prefixes to indicate scope, but for the most part I've decided against prefix notations. They make things look untidy, can prove a hassle for refactoring, and don't provide enough of a benefit in a strongly typed language to be worth it to me.



Share this post


Link to post
Share on other sites
ZQJ    496
I go for K&R style blocks because:

1) I can read them just as easily as your other style (which I used to use).
2) It involves marginally less typing (alright, VERY marginally)
3) The only real reason - I can get a good deal more code on screen, which I find really does make seeing what's going on easier.

Share this post


Link to post
Share on other sites
Inmate2993    222
The second line bracket style, which I prefer myself, is called the BSD/Allman style. Check the following wiki page for more info.

http://en.wikipedia.org/wiki/Indent_style#BSD.2FAllman_style

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by Bregma
Quote:
Original post by RyanZec
I don't know why but alot of the stuff in the K&R coding standards seem wierd to be and wanted to get your guys opinions. I will just go through each section that i disagree which.


vi not emacs

cpio not tar

Atari not Amiga

Beta not VHS

Sheesh, kids today. Gettin' so's it's too easy to start a religious war.


I've never even *heard* of cpio, so I guess you're showing your age ;)

Quote:
Teh OP
I really don't think naming a variables shorter if it is not used as much is really a good idea.


Try framing it the other way. Wouldn't you want to name a variable *longer* if it's used *more*? Or more precisely, has a wider scope? After all, bigger scopes = more symbols potentially hanging around to conflict, so you want longer names to reduce the chance of conflict. Also to *emphasize* them; things in a wider scope represent values that need to be *remembered* for some reason; and that typically means they're more *important*. So of course they should have a longer name - an honourary title.

"nelems" is horrible, though. "element_count" reads much more cleanly. Just "count" is a way to shorten that (especially if it's clear what's being counted). IMO, don't use "number_of" (or numberOf or however you want to spell it); "count" conveys the same information more easily.

Quote:

For me, my way just seems alot clearer and cleaner.


Many will disagree. What "seems" to be is what you should go with for your own stuff; de gustibus non disputandum est. If you're given a coding standard, do try to follow it.

Quote:

I have see some if statements that written in the K&R style, I just don't know where any if statement ends just by looking at the code but my way I can clearly see it.


How do you "see" it? By lining up the { with a } in the same column, right? Users of K&R style "see" it by lining up the 'if' keyword with a } in the same column. Same thing, really.

I personally pack things in even closer than K&R (i.e. I "cuddle" elses), because it "looks right" to *me*. Again, de gustibus non disputandum est.

Quote:

Another thing is the space between the statement and the parameters like if () seem like a waste of a space to me, it do not do anything good for the reading of the code.


This sounds inconsistent. A space after a keyword is "wasted space", but a whole separate line for a { character is "useful"?

(I *do* feel fairly strongly about this one. The reason for putting spaces after if/for/while/switch is to distinguish them visually from function calls. I don't particularly like having to rely on syntax colouring to tell that at a glance.)

Share this post


Link to post
Share on other sites
Melekor    379
Quote:
Original post by ToohrVyk
Setters: I consider these to be prime indicators of bad design (not bad coding practices). Less than 1% of my classes need even a single setter.


I'm intrigued. Can you explain why it's bad design and also what the alternative is? (maybe give an example?) I use a lot of them so if I could be designing my stuff better, I'd love to know how.

Share this post


Link to post
Share on other sites
ToohrVyk    1596
Quote:
Original post by Melekor
I'm intrigued. Can you explain why it's bad design and also what the alternative is? (maybe give an example?) I use a lot of them so if I could be designing my stuff better, I'd love to know how.


First, I would specify what a setter is. It's a member method in a class which is equivalent, in functionality and description (and possibly in implementation) to assigning the arguments to one or several member variables of that class, and which advertises to the users of the class the existence of those variables. So, in the following example, set_width and set_dimensions are setters:
class rect {
int w, h;
public:
void set_dimensions(int w, int h) {
this -> w = w;
this -> h = h;
}
void set_width(int w) {
this -> w = w;
}
};


On the other hand, functions such as std::vector<T>::resize are not setters, because they perform other operations in addition to altering a single value.

Now, why do I find setters to be an indicator of bad design? Because they only work if the class is a product type (that is, a list of properties which are more or less individually accessible). So, from there, I see two possibilities: first, the class provides nothing else, aside from that list of properties, at which point perhaps dropping the properties and making the class a structure with public members would achieve the same effect with less repetitiveness:


struct rect {
int w, h;
bool operator bool () const { return (w >= 0) && (h >= 0); }
};


Or the class does something aside from providing those properties, at which point it violates the single responsibility principle, and I would suggest separating the product type functionality into one class (such as "configuration" or "options") and leaving the rest of the functionality in the original class.

Note that I did not say setters are bad design. They do have their uses, for instance when providing alternate ways of accessing properties (see, for instance, a mathematical vector class where subscripting is provided as an alternative). They are, however, indicators of bad design because they most frequently appear in such designs, for a simple reason: when the class was designed from the inside out. In object oriented programming, it is in general best to design the interface of a class first, and only then to write its implementation (altering the interface only if major issues prevent you from sanely implementing it). Setters, however, are property advertiser: "What is inside the class?" as opposed to the more relevant "What does the class do?" question.

My proposed alternative is to design the class in terms of usage. You almost never want to set the health of a character by a given amount; you usually want to inflict or heal a certain amount of damage. In fact, in my current game, I can spawn, own, kill, think, render, loop, schedule, place, damage, heal, stop, reset, order, send and direct, but the only thing I can set is the X, Y and Z coordinates of my vector (an eminent case of bad design, since I use subscripting anyway).

Share this post


Link to post
Share on other sites
Deyja    920
1) Nobody cares about how you format your code or name your variables unless you're working with other people;
2) And then you have a style guide that everyone follows, whose' rules are still arbitrary;
3) And you aren't, and don't, but your rules are still arbitrary;

To summarize : Nobody cares if you think having the { on the next line or the same line is better, or whether you break encapsulation on a whim, or name things number_of_elements instead of just elements.

Share this post


Link to post
Share on other sites
Melekor    379
Thanks ToohrVyk, that was very interesting, especially the bit about inside out vs. interface first design. I'll definitely be thinking about it a bit more before writing my next class. Also, with your definition of setter, 1% doesn't sound as far fetched as it did before :)

Share this post


Link to post
Share on other sites
NotAYakk    876
Quote:
Note that I did not say setters are bad design. They do have their uses, for instance when providing alternate ways of accessing properties (see, for instance, a mathematical vector class where subscripting is provided as an alternative). They are, however, indicators of bad design because they most frequently appear in such designs, for a simple reason: when the class was designed from the inside out. In object oriented programming, it is in general best to design the interface of a class first, and only then to write its implementation (altering the interface only if major issues prevent you from sanely implementing it). Setters, however, are property advertiser: "What is inside the class?" as opposed to the more relevant "What does the class do?" question.

My proposed alternative is to design the class in terms of usage. You almost never want to set the health of a character by a given amount; you usually want to inflict or heal a certain amount of damage. In fact, in my current game, I can spawn, own, kill, think, render, loop, schedule, place, damage, heal, stop, reset, order, send and direct, but the only thing I can set is the X, Y and Z coordinates of my vector (an eminent case of bad design, since I use subscripting anyway).


Sometimes you want changing of data to have side effects: ie, people to be notified of the change, things that should automatically happen elsewhere, locks for multi-threaded purposes, etc. The wrapping of the data in settors and gettors gives you a guarantee that reads/writes to the data will be prefixed or followed with the other operations.

I'll admit most people don't do this -- but the advantage of having gettors/settors is that when you do start doing this (say, cacheing the height parameter, and only rebuilding it when it is both dirty and requested), the code that accessed the data doesn't have to change.

You can't do that with structs.

Share this post


Link to post
Share on other sites
ToohrVyk    1596
Quote:
Original post by NotAYakk
Sometimes you want changing of data to have side effects: ie, people to be notified of the change, things that should automatically happen elsewhere, locks for multi-threaded purposes, etc. The wrapping of the data in settors and gettors gives you a guarantee that reads/writes to the data will be prefixed or followed with the other operations.


If the operation isn't just "change member variable X" (no locking, no notifications, no automatic execution), chances are that you shouldn't be using a setter or a public variable anyway. You are, after all, describing a set of semantics that are performed in addition to altering the variable.

If there is a sane meaning behind these, create an abstraction that does that operation (that abstraction should not, generally, be a setter).

Quote:
I'll admit most people don't do this -- but the advantage of having gettors/settors is that when you do start doing this (say, cacheing the height parameter, and only rebuilding it when it is both dirty and requested), the code that accessed the data doesn't have to change.


Is that an advantage? First, altering code to adapt to a "transform a member variable into a function" change is a typical basic task for most post-2000 refactoring tools.

Second, if the objective of the class is not, precisely, to convey the height (and perhaps width) of an object in a "plain old data way", one has to wonder why the SRP was broken in the first place. And if it wasn't, then why not move the lazy evaluation to the function which creates the object?

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by ToohrVyk
If the operation isn't just "change member variable X" (no locking, no notifications, no automatic execution), chances are that you shouldn't be using a setter or a public variable anyway. You are, after all, describing a set of semantics that are performed in addition to altering the variable.

If there is a sane meaning behind these, create an abstraction that does that operation (that abstraction should not, generally, be a setter).


The technique can be used to present multiple "views" of the same data that is considered unencapsulated public data. For example, a complex number class might use either x,y or r, theta under the hood, and have get/set for *all four*, which work directly for two pairs, and for the other two pairs translate back and forth. This frees the calling code to use the instances as they'd like, and enables the programmer to profile to figure out which internal representation would work better and just change that. Voila, encapsulation-of-implementation of an "unencapsulated"-style interface. :)

(It can also be used, as also shown here, to expose sub-members of an aggregate without exposing details about how the aggregation is organized; but I suppose that benefit is pretty marginal.)


// I'm showing all the code in-line - except for the conversions ;) - just for
// illustrative purposes.
class Complex { // ignoring the existence of std::complex for now ;)
std::pair<double> xy; // or rtheta

std::pair<double> xy2rtheta(const std::pair<double>&);
std::pair<double> rtheta2xy(const std::pair<double>&);

// To avoid confusion, this class will only allow construction through its
// "named constructors".
Complex(std::pair<double> ab) : xy(ab) {}
public:
friend Complex Complex_xy(double x, double y) {
return Complex(std::make_pair(x, y));
}
friend Complex Complex_rtheta(double r, double theta) {
return Complex(rtheta2xy(std::make_pair(r, theta)));
}

void x(double x) { this->x = x; }
double x() { return x; }
void y(double y) { this->y = y; }
double y() { return y; }
void r(double r) {
std::pair<double> tmp(xy2rtheta(xy));
tmp.first = r;
return rtheta2xy(tmp);
}
double r() { return xy2rtheta(xy).first; }
void theta(double theta) {
std::pair<double> tmp(xy2rtheta(xy));
tmp.second = theta;
return rtheta2xy(tmp);
}
double theta() { return xy2rtheta(xy).second; }
};

// Changing this to use r-theta representation internally is tedious, but
// straightforward (and would be anyway; there are so many interesting details
// of the math operations, after all). And all the calling code is free to
// pretend the values are in either format. While we don't get type-checking
// to distinguish "created from xy" complexes from "created from rtheta" ones,
// that might not be desirable anyway.



IMO this kind of thing is the real reason to use properties, in languages that support them (C# and Python). Unfortunately, the real world is full of typing-practice (and/or ctrl-c/v practice, and/or editor hotkey practice) code that uses them to reinvent the public data member.

Quote:
Is that an advantage? First, altering code to adapt to a "transform a member variable into a function" change is a typical basic task for most post-2000 refactoring tools.


Even in C++? :)

Share this post


Link to post
Share on other sites
Rockoon1    104
Quote:
Original post by RyanZec
I really don't think naming a variables shorter if it is not used as much is really a good idea. I mean K&R sytle would have a variables named nelems which if i where jsut to look at that, I would be a little confused and would not know what it mean right away but I would name the name variable number_of_elements and to me that is much more clear becuase i knwo right away that it is the number of elements(i may not know what elements it is referring to but I would just need to look at the code around quickly, alot wuicker then i would if i needed to figure out what nelems means).


Wouldn't it simply be named 'n'? Right there you should know that its a count of something. And as you say, if you want to know what its a count of.. you can simply look at the code.

Single-letter variable names for short lived variables are vastly superior to anything else IMHO.

As a simple case-in-point: 'n' for the count, 'i' for the index into those, and 'x' for the temp or result being produced.

Simple. Clear. Efficient screen usage.

As far as 'nelems' .. thats some quasi hungarian style with none of the (few) advantages and all of the drawbacks.


Quote:
Original post by RyanZec
You guys disagree with me on any of these points, just like to know what you guys code standards are.


Well, as far as underscores within names and the like .. oh brother .. when do they actualy enhance readability? All they do is use extra space.

Member variables? Why are you messing with a class that you do not already know the member variables of? Seriously. And since such references are obviously out of scope of the function under consideration, shouldnt it automatically be assumed to be a member variable unless otherwise denoted? I mean really, are you going to assume that its a global variable or something?

Share this post


Link to post
Share on other sites
kRogue    100
I think member variabls should be denoted with something so you *know* fro sure when you are acesing them... the reason being that it alteast stops one irritating kind of scope bug, you jsut ahve to be bit by it once, to never want to be bit again....

though, the same line of though then should apply to member functions too. (some people like to write this->variable/this->function to avoid any ambiguity) but alas... I have to confess I do the following:

for member variable I give them the prefix m_ and for static memember variables I give them the prefix sm_, at times I get tempted to put into what I am working on now the prefix "f_" for member functions and "sf_" for static member functions... but doing that on over 1MB of source is not something I want to do with my time, and very few libraries for C++ put a prefix in front of member functions anyways (and typically all member variables are private anyways)... but still do get tempted... but ewwww... to go through everying just to do that... I don't know... if one takes it to exremes should local class and typedefs also have somekind of prefix like t_? (in the world of STL the answer is a big NO! as is prefixing functions with f_, because the convention for the function and local types does not have a prefix)

I never liked Hungrarian notation.

I never liked naming anything "foo" or "bar", that jsut irritates me to no end. The whole point of "foo" and "bar" is that they have no meaning, and if a paremeter (be it variable or template type) is used it *should* have a meaning.


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this