Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1412053 Posts in 69447 Topics- by 58483 Members - Latest Member: Exye

June 22, 2024, 06:48:49 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Coding styles
Pages: 1 2 [3] 4 5 ... 7
Print
Author Topic: Coding styles  (Read 18976 times)
increpare
Guest
« Reply #40 on: February 27, 2010, 03:49:07 PM »

You guys realize
int f(const int i)
and
int f(int i)
have the same signature? Outermost consts are completely ignored by the compiler, except creating compile errors if you try to modify i in the const version.
What do you mean by 'signature' here? 
Logged
Riley Adams
Level 5
*****


I don't actually use Ubuntu much...


View Profile
« Reply #41 on: February 27, 2010, 04:40:05 PM »

You guys realize
int f(const int i)
and
int f(int i)
have the same signature? Outermost consts are completely ignored by the compiler, except creating compile errors if you try to modify i in the const version.
What do you mean by 'signature' here? 

The signature is the combination of the name, return type and argument types that the compiler uses to tell functions apart. It means the compiler sees them as the same thing, you couldn't make an overload of int f(int i) that was simply int f(const int i), you'd get an error about defining the same function twice.
Logged

increpare
Guest
« Reply #42 on: February 27, 2010, 04:45:30 PM »

Ok - right, thanks.  I was being stupid...  (However, though this isn't related, I hadn't come across the c/whatever notion of 'function signature'/'method signature' (as distinct from 'type signature') before).
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #43 on: February 27, 2010, 06:13:57 PM »

The signature is the combination of the name, return type and argument types that the compiler uses to tell functions apart. It means the compiler sees them as the same thing, you couldn't make an overload of int f(int i) that was simply int f(const int i), you'd get an error about defining the same function twice.

Actually, the return type is not used to differentiate functions, at least not in C++.  You can't overload on return types.  This is illegal:

Code:
int f();
float f();

This is perfectly legal (and extremely useful) in Ada though, and I miss it every time I go back to C++.

Code:
function F return Integer;
function F return Float; -- OK!
Logged



What would John Carmack do?
Riley Adams
Level 5
*****


I don't actually use Ubuntu much...


View Profile
« Reply #44 on: February 27, 2010, 06:42:46 PM »

Quote
Actually, the return type is not used to differentiate functions, at least not in C++.  You can't overload on return types.  This is illegal:

I know you aren't allowed to overload with a different return type, but isn't it technically still a part of the signature? (for instance, you have to include the return type when you typecast a function pointer).
Logged

Sos
Level 8
***


I make bad games


View Profile WWW
« Reply #45 on: February 27, 2010, 06:43:31 PM »

Actually, the return type is not used to differentiate functions, at least not in C++.  You can't overload on return types.  This is illegal:

Code:
int f();
float f();

This means, you shouldn't need that. I was amazed how can you code without jumps, when swapping from ASM to C.
When starting on ASM I was amazed how can you ever write a game without multiplication / division (C64).
After a short period of time i forgot about that, and it seemed thiere is little use for unimplemented stuff.
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #46 on: February 27, 2010, 06:57:42 PM »

Quote
Actually, the return type is not used to differentiate functions, at least not in C++.  You can't overload on return types.  This is illegal:

I know you aren't allowed to overload with a different return type, but isn't it technically still a part of the signature? (for instance, you have to include the return type when you typecast a function pointer).

For function pointers yes, but for overload purposes no.  I thought you were just referring to overloads.
Logged



What would John Carmack do?
Core Xii
Level 10
*****


the resident dissident


View Profile WWW
« Reply #47 on: February 28, 2010, 12:04:50 AM »

He pretty much does it for everything, control structures and functions.

Eww, functions too? WTF



I always include brackets even if a control structure has only one statement. This makes it easier to expand it in the future... I got tired of adding and removing brackets every time I moved code around.
Logged
terloon
Level 0
**


View Profile WWW
« Reply #48 on: February 28, 2010, 12:14:19 AM »

Everything. I do the same for brackets for the exact same reason. Plus I've seen too many of these in old code to make me cry:

Code:
if(someImportantFlag)
    doThisFunction();
    doThisFunctionToo(); // whooops...
Logged
skyy
Level 2
**


[ SkyWhy ]


View Profile
« Reply #49 on: February 28, 2010, 08:04:23 AM »

What about refactoring?

Software engineer principles pretty much say that after completion of a certain part of the code you are working on and you know it works, you should refactor it so it will make more sense and look tidier etc. etc.

What do you think? Bullshit or win?

I generally agree with the refactoring and test driven development (unit tests.. ugh) but at times when I'm just blitzing code to get the it done, I could not care less. Should but ... BUT...  Shrug

And please, refrain from "omg lol you should keep the code clean from the start" comments. It's obvious but that's not what this is about. Writing poo code and having to rewrite it != refactoring working code.
Logged

st33d
Guest
« Reply #50 on: February 28, 2010, 08:54:05 AM »

I think the "what the fuck is going on in here" argument is always a strong case for clean code.

Even sloppy yet well commented code is good enough.

I once had to maintain a co-worker's code whilst he was on holiday. Instead of having some kind of sensible state machine in the main game loop with you know, dare I say it, subroutines, he had 500 lines of random crap going on. The comments either didn't make sense or were just old code, and to top it off, it was broken and I had to fix it.

Even going back to old code I've written myself can be painful if my IQ has dropped in the past month. And the way I party, that happens a lot.
Logged
skyy
Level 2
**


[ SkyWhy ]


View Profile
« Reply #51 on: February 28, 2010, 08:57:14 AM »

Hehe. One of the main reasons why I go back and refactor is to keep it CLEAN and when I come back to it in a month or so I can figure it out pretty much instantly based on the flow of the program, comments and random stuff I like to drop around.

But yeah, comments, comments and comments. Not too much... Just the right amount of comments that make sense. And obviously variables, methods etc. named in a sense making way too.

Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #52 on: February 28, 2010, 09:51:12 AM »

I keep my code as tidy as possible, mostly so that I can insert debug code in weird ways that will always catch my eye.  It will, for example, be indented wrong or something.  This why I rarely forget to remove debug code, because it looks so out of place that I can't miss it.
Logged



What would John Carmack do?
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #53 on: February 28, 2010, 11:01:54 AM »

So here's my current coding standard document. It is basically based on the Allman style, with some additions for clarity of presentation. I like to use liberal amounts of vertical whitespace to emphasise code structure and logic flow. I also have some pretty unique preferences about styles of comments.


Quote
I would avoid doing this in C/C++ because the following code doesn't do what it looks like it should do:
Code:

int* p1, p2;

yeah I always put the * after the int because I feel it's part of the type however I know lots of people who do this...

int *p1, *p2;

which will work and do what you think it would do.

The asterisk is not part of the type, it is a specifier, like &, const or volatile. It should belong with the variable it specifies. Write specifiers together with the variable, always.

[quote link=topic=11327.msg346852#msg346852 date=1267196264]
Rectangle.h

Code:
#ifndef __AWESOME_RECTANGLE_H_
    #define __AWESOME_RECTANGLE_H_

All names containing two consecutive underscores, or beginning with an underscore followed by a capital letter are in the compiler's reserved namespace.  Doing that is an extremely bad idea.
[/quote]

Well, the #define symbols only exist for the compiler, so it should probably be ok. If you redefine a compiler symbol it should throw a warning at you. [edit] I read your later reply where you mentioned your colleague's problems, so apparently the compiler maybe will not complain about name conflicts inside its own space.

Oh goodness, I have a great disdain for spaces after if, for, while, etc. A coworker does this to me on purpose to annoy me to no end Cheesy. When did that syntax take root?

It is a very good style, in fact. For, while, throw, catch, if etc (and conceptually even assert), are logic and flow control, not functions. Employing what is syntactic redundancy for the parser provides readability to humans. Flow control should be indented one space from its criteria, while functions should belong together with its signature.

Code:
if (something) 
{
    Function( myPreciousss );
}
« Last Edit: December 18, 2015, 05:11:55 PM by Silbereisen » Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #54 on: February 28, 2010, 02:53:04 PM »

Quote
Code:
if (something) 
{
    Function( myPreciousss );
}
Ew.
"Ew" is not an argument, it is an invitation for holy wars, which is territory better left untrodden. I enjoy reasons people give for their styles because I can learn from it. I am however utterly disinterested in aesthetic preferences.
« Last Edit: December 18, 2015, 05:12:20 PM by Silbereisen » Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
skyy
Level 2
**


[ SkyWhy ]


View Profile
« Reply #55 on: February 28, 2010, 02:57:23 PM »

Oh well, what ever the style, once you start working in a team in a medium size company (or bigger), you can throw your great ideals into hell. They generally mean rats ass at that point Durr...?

It's the company / lead who decides all the stuff and you just follow. Obviously, if you are in a position where you can decide these in a company, then .. hells yeah, let the brainwashing begin and convert more people into your own "religion". Since, that's what it basically is. Should there be a space, capital, underline and so on.

I'm kind of used to swapping styles / conventions (different projects) as I go along. I do have my personal preferences but really not that fuzzed about it.  Gentleman

EDIT # 1:
EDIT # 2: first edit turned it into a total troll... All I'm saying is: I agree with Mikademus.  Beer!
« Last Edit: February 28, 2010, 03:02:52 PM by skyy » Logged

LemonScented
Level 7
**



View Profile
« Reply #56 on: February 28, 2010, 06:55:57 PM »

I could take ages describing my coding style in lots of different scenarios, but here are the basic conventions, in a header file and a bit of a cpp. Obviously my comments tend to be a lot thinner on the ground than in this example. Also, the code tags have messed up my tabbing, but meh - it works on my machine  Wink

Code:
// CodingStyle.h
// Comments always in this style rather than /* */
// It makes it easier to comment out chunks of code when testing stuff

#ifndef CODING_STYLE_H
#define CODING_STYLE_H

// Standard library stuff first, pointy brackets
#include <standardlibrarything.h>

// Only include stuff I absolutely need to in headers. Prefer forward declarations.
// Filenames tend to be capitalised like this.
#include "BaseClassThing.h"

// Defines in capitals with underscores, always with brackets to ensure sensible behaviour...
#define SOME_NUMBER (42)
#define ANOTHER_NUMBER (69)
// ... In cases like this:
#define MAX_WHATNOTS (SOME_NUMBER + ANOTHER_NUMBER)

// ^^^ really these should be const variables, but they show up better in the syntax
// colouring in my IDE this way, and to me the improved readability is an acceptable
// trade-off for the lack of type safety

// Forward declarations
class cSomeOtherClass;
struct sSomeOtherStruct;

// Structs prefixed with "s". Very rarely have private members or methods of any kind
// inside structs - if I need those things, I usually change the struct to a class.
struct sSomeStruct
{
// Always provide a constructor to ensure sane default values, unless performance
// reasons dictate otherwise;
sSomeStruct() :
someMember(0),
someOtherMember(0.0f),
bIsMadeOfCheese(false),
pOtherStruct(NULL) {}

// Variables in structs treated the same as local variables: camelCase, and
// generally with no particular prefix...
int someMember;
float someOtherMember;

// ... Although I use "b" for booleanso (and generally include something like "is" in the name ...
bool bIsMadeOfCheese;
// ... And p for pointers. The asterisk goes with the data type, not the variable name
sSomeOtherStruct* pOtherStruct;
};

// Globals prefixed with "g", but I use globals very rarely anyway.
int gGlobalThing;

// Classes prefixed with "c". When derived from other classes, I sometimes (but
// not always name the derived class in such a way that it has something in common
// with the base class, in this case "ClassThing")
class cAwesomeClassThing : public cBaseClassThing
{
// Public stuff first, starting with the constructor
public:

// Always have a constructor. For classes, which tend to be bigger and more complex than structs,
// I define the constructor in the .cpp file. Helps to reduce dependencies, and keeps the header
// files clean
cAwesomeClassThing();

// ALWAYS have an explicitly-declared virtual destructor for any class that derives from something.
// Even if nothing in the hierarchy contains virtual functions now, it might in future.
virtual ~cAwesomeClassThing();

// enums next. I almost always name enums, prefixed with an "e", and depending on my
enum eSmell
{
SMELL_FUNKY,
SMELL_FRESH,
SMELL_LEMONY,

MAX_SMELLS,
};

// Virtual functions next.
virtual void Update();

// Get/Set functions for appropriate things here.
// These are always const-correct, and in simple cases like this always put in the header
// as a hint to the compiler to inline them - I'm usually too lazy to explicitly type "inline",
// but then if the compiler ignores me putting the function in the header, it would probably
// ignore the inline keyword anyway
int GetSocks() const { return mSocks; }
// By convention I tend to use "val" as the variable name in a simple set function like this.
// Also, to respond to some of the stuff in the thread, the const here is as much to tell the compiler
// that val won't change inside the function than it is to tell any programmers. Being explicit about
// const-correctness is good for compiler optimisations as well as readability and safety.
void SetSocks(const int val) { mSocks = val; }

// Only deal in pointers when the result could be NULL (use references otherwise).
// Const reference for passing anything in that shouldn't change, non-const for anything that
// might form part of the output of the function (not that I use this much). Probably outputInfo
// should actually be a pointer rather than a reference to make it clearer in calling code, but to
// me a reference means that there's guaranteed to be an output structure passed in, rather than
// risking a NULL pointer. Spacing in and around brackets and commas as shown.
cSomeOtherClass* DoSomething(const sSomeOtherStruct& inputInfo, sSomeOtherStruct& outputInfo);

// Protected after public. Private after that. Only ever have at most one of each keyword in a class
// declaration. And never have any data members be public.
protected:

// Member variables prefixed with "m".
// I don't generally subscribe to the int thing1, thing2, thing3; way of doing stuff. Declare
// each variable seperately.

// Tab variable names into a line. As you see below I don't do this for whole files, but
// localised "chunks" of code should look uniform, even if each "chunk" is tabbed differently
// to the others. Speaking of tabs, I use actual tabs for indending, NOT spaces, because
// spaces are a disaster when you're trying to edit stuff.
int mSocks;
int mShoes;
bool mbAreSocksStinky;

private:

// Generally name an array of something as a plural. Where it can be known at compile time,
// prefer fixed-size arrays allocated upfront like this, rather than using new and delete.
cSomeOtherClass* mpThingamajigs[MAX_WHATNOTS];
// Prefer instances of the actual enum type for type-safety, rather than
// just an int or something.
eSmell mCurrentSmell;

};

#endif // CODING_STYLE_H

Code:
// CodingStyle.cpp

// Line breaks in function signatures and long if statements. Although my line width isn't
// constrained to anything other than the width of my edit window (maybe 100 characters, give or take?)
cSomeOtherClass* cAwesomeClassThing::DoSomething(const sSomeOtherStruct& inputInfo,
sSomeOtherStruct& outputInfo)
{
// No spaces before or around brackets for control flow statements, but
// spaces around numerical operators and boolean evaluators. Curly braces in this style always,
// even for single-line if statements
if(inputInfo.dontDoSomethingAfterAll && inputInfo.isTellingTheTruth)
{
return NULL;
}

// Try to initialise variables as soon as they're created. Always have a space
// either side of the equals during assignment.
int wibblyGiblets = inputInfo.jellification * gGlobalThing;

// i, j and k are fine for loop variable names in trivial cases, but often I'll go back
// later to give them more specific names. Prefer signed ints to unsigned, except for bitfields
// and "raw bytes". Prefer ++i to i++ in loops. Spacing like this.
for(int i = 0; i < MAX_WHATNOTS; ++i)
{
if(inputInfo.sockAroma * inputInfo.sockProximity > mpThingamajigs[i]->nasalInterference)
{
outputInfo.foundSocks = i * wibblyGiblets;
return mpThingamajigs[i];
}
}

return NULL;
}
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #57 on: February 28, 2010, 07:39:09 PM »

Other stuff that comes to mind:

C++:
If it isn't main, or declared extern "C", it goes in a namespace:

Namespaces are good, use them.

Define EVERYTHING in the exact same order it was declared:

If function A is declared after function B, I expect to see them that way in the implementation, too.

Ada:
If a subprogram has more than one library that only it uses, make it separate:
Prefer private packages to nested packages, and if you have to use a nested package, make it separate:

These won't make sense to anyone that doesn't know Ada, but I'll explain if pressed.

For packages that contain tagged types, name the package after the plural of the type:
The controlling parameter of an operation should be named 'This':
Use elaboration pragmas everywhere you can:
Use the 'overriding' keyword to detect typos on overrides, I'm not so keen on 'not overriding,' but if it floats your boat...:

Code:
with Ada.Finalization;

use Ada.Finalization;

package Widgets is
    pragma Preelaborate;

    type Widget is abstract new Controlled with private;
    pragma Preelaborable_Initialization(Widget);
   
    overriding
    procedure Finalize(This: in out Widget);

    procedure Draw(This: in Widget) is abstract;

private
    type Widget is abstract tagged
    record
        Something: Integer := 0;
    end record;
end Widgets;
« Last Edit: February 28, 2010, 07:43:33 PM by Average Software » Logged



What would John Carmack do?
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #58 on: February 28, 2010, 08:55:53 PM »

Code:
	// enums next. I almost always name enums, prefixed with an "e", and depending on my
enum eSmell
{
SMELL_FUNKY,
SMELL_FRESH,
SMELL_LEMONY,

MAX_SMELLS,
};

All caps enum (and const) values are another thing that can be very dangerous, since it's just begging for macro clashes.  I think this comes from the fact that enums and const were relatively late additions to C, and I think people used to convert #define macros without the changing the names.  It's the only explanation I can come up with for why people do this.

It's worth noting than modern C++ authorities like Stroustrup all recommend against doing this.
Logged



What would John Carmack do?
Sos
Level 8
***


I make bad games


View Profile WWW
« Reply #59 on: February 28, 2010, 09:02:45 PM »

I don't see any benefits of using enums instead of good old defines.
Logged

Pages: 1 2 [3] 4 5 ... 7
Print
Jump to:  

Theme orange-lt created by panic