FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Style and standards
Goto page 1, 2  Next
 
Post new topic   Reply to topic     Forum Index -> Ares
View previous topic :: View next topic  
Author Message
sean



Joined: 24 Jun 2004
Posts: 609
Location: Bay Area, CA

PostPosted: Thu Sep 09, 2004 11:49 am    Post subject: Style and standards Reply with quote

Per qbert's request, how about we hammer out some style and interface guidelines. Standard D syntax style is defined here:

http://www.digitalmars.com/d/dstyle.html

Basic rule is to always use mixed case, verbs (functions) have a leading lowercase letter while nouns (types) have a leading uppercase letter. Constants are in all caps. The guide leaves variable names open, and at the risk of inviting argument I suggest there be some qualifier for class member variables (and possibly a different one for static member variables). Some common prefixes are "m_" and "sm_" or "d_" and "s_" for standard and static members, respectively.

I would also suggest that all class variables be made non-public and that properties be used if direct variable manipulation is required. A suggested class definition layout would be to have all public members at the top, with members grouped by type: constructors, manipulators, etc.

All imports should be private, and anything declarations or functions not having to do with a module's external interface should be private as well.

I can't think of anything having to do with syntax offhand. Suggestions? And what about interface guidelines?
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Thu Sep 09, 2004 1:03 pm    Post subject: Member variables Reply with quote

I'm not a fan of underscores (_) in variables. If we want prefixes to member variables, I'd prefer something like myVariable. I think it looks nicer, and it's easier to type (at least for me).
Back to top
View user's profile Send private message Send e-mail AIM Address
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Thu Sep 09, 2004 1:45 pm    Post subject: Reply with quote

I think we're mostly in agreement on using the d coding standard, and I'm for that.

As for the limited hungarian notation you suggested, that makes sense too. Personally, I'm not for excessive use of hungarian notation. Using prefixies for member and static are helpful, but I'm not sure if there's any value to be realized in having those in the spec. I'm welcome to be wrong of course. Wink

The only other thing I can think of is requiring, at a minimum, documentation either in the code or submitted with documentation that can be added to a user's guide and/or library reference. Having this in the code is ideal, and may be the way to go, but we may have to settle on a documentation engine to back if that's to become useful.

What about tabification? 2 spaces, 4 spaces, /t as a standard? Or no standard here at all (hey, we can convert it later if we want to, right)?

Also D, exposes several different ways to declare public/private/protected: using brackets, a colon or no decoration at all (ala java). Should this be in the spec as well?

Anyway, here's where we are:
Code:
// example module for coding standards
private import std.stdio;

// simple class documentation here
class ExampleClass{
    // simple method documentation here
    public this();
    public int getValue();
    public void setValue(int); // should accessors/mutators use this syntax?
   
    private int m_value;
    private static int ms_value;
    private void doSomething();
 
    protected abstract void handleSomething();
}

_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
sean



Joined: 24 Jun 2004
Posts: 609
Location: Bay Area, CA

PostPosted: Thu Sep 09, 2004 4:29 pm    Post subject: Reply with quote

pragma wrote:

As for the limited hungarian notation you suggested, that makes sense too. Personally, I'm not for excessive use of hungarian notation. Using prefixies for member and static are helpful, but I'm not sure if there's any value to be realized in having those in the spec. I'm welcome to be wrong of course. Wink

I'd debated about that as well, but finally decided to include it because it's suggested in "Large Scale C++ Software Design" as an aid to maintainability. But I'm pretty indifferent on this score as it's implementation-level stuff.

Quote:

What about tabification? 2 spaces, 4 spaces, /t as a standard? Or no standard here at all (hey, we can convert it later if we want to, right)?

Good question. I prefer spaces over tabs as there's less of a chance of formatting problems, but beyond that I don't really care. I personally use 4 spaces though.

Quote:

Also D, exposes several different ways to declare public/private/protected: using brackets, a colon or no decoration at all (ala java). Should this be in the spec as well?

I don't think it's necessary, though I would say a good rule of thumb is to use the method that requires the least typing Smile

As for accessors/mutators, I do it this way:

Code:

class C
{
public:
    int val() { return m_val; }
    void val( int v ) { m_val = v; }

private:
    int m_val;
}

ie. I don't use the get/set notation. To me, this seems to fit fairly well with the concept of properties anyway, as I prefer "c.val" to "c.getVal."


Sean
Back to top
View user's profile Send private message
regan



Joined: 21 Jun 2004
Posts: 23

PostPosted: Thu Sep 09, 2004 7:24 pm    Post subject: Re: Style and standards Reply with quote

sean wrote:

I would also suggest that all class variables be made non-public and that properties be used if direct variable manipulation is required.


Why?

sean wrote:

A suggested class definition layout would be to have all public members at the top, with members grouped by type: constructors, manipulators, etc.


I like it, something like:

class A {
//public: this is the default, so, do we need this line?
//constructors
this();
~this();

//manipulators?
opApply();

//normal members
fooBar();

private:
int m_val;

}
Back to top
View user's profile Send private message
sean



Joined: 24 Jun 2004
Posts: 609
Location: Bay Area, CA

PostPosted: Thu Sep 09, 2004 9:40 pm    Post subject: Re: Style and standards Reply with quote

regan wrote:
sean wrote:

I would also suggest that all class variables be made non-public and that properties be used if direct variable manipulation is required.

Why?

Robustness, mostly. While a property behaves syntactically the same as a public variable (so in D you're really not stuck once you've made the choice), you need to go through a member to check class invariant rules (AFAIK), use DBC, etc. And as much as I'm indifferent to traditional OO programming methods, using properties just "feels right" in this case.
Back to top
View user's profile Send private message
larsivi
Site Admin


Joined: 27 Mar 2004
Posts: 453
Location: Trondheim, Norway

PostPosted: Fri Sep 10, 2004 1:07 am    Post subject: Reply with quote

pragma wrote:
What about tabification? 2 spaces, 4 spaces, /t as a standard? Or no standard here at all (hey, we can convert it later if we want to, right)?


I want 2 spaces (at least no tabs!).

I agree with most of the other topics.
Back to top
View user's profile Send private message
andy



Joined: 15 Mar 2004
Posts: 71

PostPosted: Fri Sep 10, 2004 7:23 am    Post subject: Reply with quote

larsivi wrote:
I want 2 spaces (at least no tabs!).
This means war. Wink

Personally, I don't think things like spacing and private attributes are all that important. They don't have any affect at all on code which is using the library, so it's not really all that important if they're inconsistent between modules.

(which reminds me: at one point, I was rolling around the idea of writing a refactoring tool for D using that ANTLR parser I started...)

sean wrote:
Robustness, mostly. While a property behaves syntactically the same as a public variable (so in D you're really not stuck once you've made the choice), you need to go through a member to check class invariant rules (AFAIK), use DBC, etc. And as much as I'm indifferent to traditional OO programming methods, using properties just "feels right" in this case.
Using properties instead of public fields is probably the way to go in the end because it offers the possibility of binary compatibility between library versions if Ares should be linked as a DLL.
_________________
"Complacency is a far more dangerous attitude than outrage." - Naomi Littlebear
Back to top
View user's profile Send private message
larsivi
Site Admin


Joined: 27 Mar 2004
Posts: 453
Location: Trondheim, Norway

PostPosted: Fri Sep 10, 2004 11:24 am    Post subject: Reply with quote

andy wrote:
larsivi wrote:
I want 2 spaces (at least no tabs!).
This means war. Wink

Personally, I don't think things like spacing and private attributes are all that important. They don't have any affect at all on code which is using the library, so it's not really all that important if they're inconsistent between modules.


It's not really important of course, I can always change the 'offending' files to my liking. I just know that the source of todays Phobos is really chaotic in my VIM-setup, making it nearly unreadable.

Oh, and I'm all for properties instead of fields.
Back to top
View user's profile Send private message
regan



Joined: 21 Jun 2004
Posts: 23

PostPosted: Sun Sep 12, 2004 4:12 pm    Post subject: Reply with quote

andy wrote:
larsivi wrote:
I want 2 spaces (at least no tabs!).
This means war. Wink

Personally, I don't think things like spacing and private attributes are all that important. They don't have any affect at all on code which is using the library, so it's not really all that important if they're inconsistent between modules.

(which reminds me: at one point, I was rolling around the idea of writing a refactoring tool for D using that ANTLR parser I started...)


I've always thought using tabs is best. 'most' editors will display tabs as any width of spaces you want, further, writing an app to reformat it to something else is simplest if they're all tabs, especially if you do what I do below..

I use spaces in certain places eg:
(a . is a space, a \ a tab)

enum.BOB.{
\ONE...=.1,
\TWO...=.2,
\THREE.=.3,
\FOUR..=.4,
}

in other words I use tabs where I simply mean to indent, and spaces to align things (which only works if you have fixed width fonts)

sean wrote:
Robustness, mostly. While a property behaves syntactically the same as a public variable (so in D you're really not stuck once you've made the choice), you need to go through a member to check class invariant rules (AFAIK), use DBC, etc.


What about in this case (a constant read-only variable - not using a get property)

class A {
const int b;
this()
{
b = 2;
}
}

void main()
{
A a = new A();
printf("?d",a.b);
}

granted, the above not only fails to compile but it crashes dmd (I'm posting a bug report now) and you can also do it like this..

class A {
enum {
b = 2
}
}

Don't get me wrong I'm, I think I agree with you, I just have to play 'devils advocate' in order to explore all the possibilities.

sean wrote:

And as much as I'm indifferent to traditional OO programming methods, using properties just "feels right" in this case.


I agree.

andy wrote:

Using properties instead of public fields is probably the way to go in the end because it offers the possibility of binary compatibility between library versions if Ares should be linked as a DLL.


I don't understand, if you have time to educate me, please explain.. Smile
Back to top
View user's profile Send private message
larsivi
Site Admin


Joined: 27 Mar 2004
Posts: 453
Location: Trondheim, Norway

PostPosted: Tue Sep 14, 2004 3:03 am    Post subject: Code style draft suggestion Reply with quote

I've made a codestyle draft (It's more or less copied from Coin (www.coin3d.org), but grafted onto D.

I try to use this in my own projects and find it clean and nice.

The draft don't discuss templates, mixins or documentation. There are possibly other things that should be mentioned also.

Code:

Coding guidelines for Ares
First draft by Lars Ivar Igesund
Blatant copy from Coin (www.coin3d.org) where applicable to D
This revision: larsivi 20040914

 0) If the code you write is not 100? complete;

    - Leave a "FIXME" message if you believe the code is fairly
      correct, but you are unsure and have not checked the correctness
      yet, or if there are known deficiencies. This includes cases
      like ambiguities in documentation that will require some
      investigation to resolve, error-cases or places where one should
      be more robust that haven't been fixed yet due to time
      constraints, etc.

    - Insert "AresStub();" statements if the code lacks certain
      important functionality, so situations where unimplemented
      features are used will be detected at run-time.

    - Leave FIXMEs if you see obvious cases for performance
      improvements which should be explored.

    A FIXME-message must include a description of the problem, who
    wrote the message, and when.  Please include whatever you have
    already found out about the problem in the FIXME text, so your
    next of kin don't have to painstakingly re-do all the thought-work
    you already have laid down.  Example:

      // FIXME: should be possible to create a good standard library.
      // 20040914 larsivi.

    or

      // FIXME: this action seems completely bogus, as if something fails,
      // all bets are off and we should simply terminate the import
      // operation. (flushInput() continues to read and scans for a
      // closing brace). Run with this code disabled for a while and axe
      // it if nothing bad seems to come frome it. 20020531 mortene.
      //
      // if (!ret && flush) SoBase::flushInput(in);

    This goes also for other keywords in comments (see below).  It
    makes it much easier when others try to fix code that doesn't
    work.  You will know who to ask if you don't understand the
    problem, and the date could indicate among other things the
    urgency of the problem.
 
 1) If blocks of code are commented out (obsoleted) to make place for
    new code, or because it has become superfluous, one should mark it
    like the example below if it is a large block of code, if the new
    code is very experimental, or if the new code is obfuscated
    (e.g. because of optimizations).

    version (None) { // OBSOLETE: <textual description>. <yyyymmdd userid>.
    ...old code...
    }
    else {// short description of new code
    ...new code...
    }

    See also the next rule.

 2) Under *no* circumstances should developers leave any code which
    has been commented out with the language constructs "// ..." or
    "/* ... */" in anything you check into SVN, at least not without
    commenting _why_ the code is still present.

    It's often very time-consuming and just a bloody pain in the ass
    and a waste of resources trying to figure out why commented-out
    code is still present in a source file (is it new code which
    *might* fix a bug, but which haven't been tested yet?  is it old
    code found to be buggy which have been removed? is it commented
    out because it is a new feature which is yet to be completed? etc
    etc etc).

    Programmers who continues to sin against this rule after having
    this pointed out to them should be taken out behind the barn to be
    shot.

 3) During debugging, write debug code like this:

    debug {
      // FIXME: Should we use some sort of standardized formatting for
      // these cases? 20040914 larsivi
      writefln(...);
    }

    If there is a chance that the debug information might be useful
    later, keep it as is. If not, remove it before making a patch or
    checking in.

    If there are many debug statements in the same category, use a
    debug identifier for that category (debug (identifier) )

    UPDATE 2001-11-21 larsa: Actually, we now prefer that you use this
    define as an if-condition instead, because of the cleaner look the
    source code gets when it is not littered with preprocessing
    directives.  For permanent debugging code, write therefore source
    code like this instead:

 4) Do not under any circumstances use printf() / fprintf() / puts()
    or related functions for output. writefln do the job perfectly.

 5) Don't use any variablename, classname, define, functionname or any
    other identifier that starts with double underscores. That namespace is
    per the D specs fully reserved for the compiler
    implementation.

 6) Prefix with the "this" keyword for dynamic functions and member
    variables, prefix with the classname for static functions and
    variables.

    The rationale for doing this extra typing is that it makes the
    code immensely more easily readable when skimming it. If the
    prefixes are missing, one has often to scroll back and forth to
    find out if variables are input arguments to methods or stack
    variables -- with "this." or "ClassName." prefixes there is
    immediately no doubt where the variable comes from.
 
 7) Expose all class fields using properties, hiding the fields themselves
    in "private" blocks. This is considered good OOP practice in addition
    to the fact that it might hinder binary compatibility problems in the
    future.

 8) Code formatting rules. The default is to use Kernighan and Ritchie style.

   a) Braces: keep opening braces on the end of the line, and closing
      braces at the start. Like this:

      if (...) {
        ...
      }

      And not like this:

      if (...)
      {
        ...
      }

      The exception from this rule is functions, which should have the
      opening brace on the next line.

   b) Indentation: use 2 spaces extra for each level of nesting.

      *Never* use tabulator characters (ie ASCII code 0x09), as
      editors expands them differently. The code indentation will
      therefore more often than not look like crap with the default
      settings of any other editor than the one you happen to be using
      yourself.

   c) Spacing: use 1 space after commas and around operators (like +,
      -, *, /, ==, &&, etc), but not after or before parentheses.

      Like this:

      if (val) { i = sqrt(a) * func(b, c); }

      Not like this:

      if ( val ) { i=sqrt(a)*func(b,c); }

   d) Naming: class names should be uppercased for each word, function
      names for each word except the first one, variable names should
      be all lowercase, and defines, enums and constants should be all
      uppercase. Example:

      class MathClass {
     
      float
      calculateValue(float in)
      {
        const float FACTOR = 2.78;
        ...
        ...
      }

      FIXME: The note below make perfectly sense in C/C++, but possibly
      not in all cases for D. I still vote for the below choice, though.
      20040914 larsivi

      NOTE: do *not* use Hungarian-style naming, ie prefixing names
      with indicators about type. So don't for instance name classes
      with a leading "c", or member variables with an "m", or integers
      with an "i" and so on and so on. You're better off in the
      readability-department by using the "this" prefix, as explained
      above, and then the Hungarian naming style just obfuscates the
      code.

   e) Pointer types and references: use a space on each side of the
      '*' and '&' operators, like this

        SoNode * mynode = NULL;

      not like this

        SoNode *mynode = NULL;

      because it makes it look like the '*' "belongs" to the variable
      name (which of course is wrong -- it's part of the type), and
      not like this either

        SoNode* mynode = NULL;

      because it's ugly and unusual. So for consistency, _please_
      stick with the space-on-both-sides convention in Ares code.

   f) Use
                   return x;
      and not
                   return (x);

      (Since "return" is not a function with arguments, the latter
      just looks plain wrong.)

   g) For the access modifiers "private", "protected" and "public" within
      a class, always use ':'. There are more than enough braces to go
      around in there anyway.

      For the same modifiers outside a class, use blocks if they affect more
      than one member. This should apply to all other modifiers that can
      group using braces. The rationale is that members can be grouped
      together with other similarly modified members, making hungarian
      notation less necessary, e.g.:

      static {
        void foo();
        int bar(int joe);
      }

   h) Fields should not be lined up neither on identifier nor '=' as the
      addition of new fields might ruin the setup and make more work than
      necessary. One space should be used everywhere, e.g.:

      int var = 3;
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Tue Sep 14, 2004 8:45 am    Post subject: Reply with quote

Thanks Larsivi! That's a very solid start, and probably good enough to start coding now. Provided, of course, it meets with everyone's approval. Smile

One tiny nitpick: it mentions puttnig the opening brace on the first line for everything except functions and methods. Is this correct? Why not just make everything consistent by having functions open on the first line as well?

I'd assume that try/catch would use this form:
Code:

try{
   /*...*/
}
catch(Exception e){
  /*...*/
}
finally{
  /*...*/
}


And templates would use something like this:
Code:

template foobar(T1, T2, T3){
  void foobar(T1 one, T2 two, T3 three){
    /*...*/
  }
}

class Foobar(T1, T2, T3){
  /*...*/
}


Outside of that, I'd say this is the way to go. It covers all the bases that have been discussed so far.
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
larsivi
Site Admin


Joined: 27 Mar 2004
Posts: 453
Location: Trondheim, Norway

PostPosted: Tue Sep 14, 2004 12:41 pm    Post subject: Reply with quote

pragma wrote:
One tiny nitpick: it mentions puttnig the opening brace on the first line for everything except functions and methods. Is this correct? Why not just make everything consistent by having functions open on the first line as well?


Well, it is consistent (sortof). Functions are units of code (just like classes, structs and templates, see below) that can be used elsewhere, whereas the other stuff is control structures and just part of other code.

pragma wrote:

I'd assume that try/catch would use this form:
Code:

try{
   /*...*/
}
catch(Exception e){
  /*...*/
}
finally{
  /*...*/
}



Added to my file.

Templates and classes like below.

Code:

template foobar(T1, T2, T3)
{
  void foobar(T1 one, T2 two, T3 three)
  {
    /*...*/
  }
}

class Foobar(T1, T2, T3)
{
  /*...*/
}

class Foobar
{

}

struct Foobar
{

}

// Inherited classes
class Foo
: Bar, Iface
{

}


I've uploaded my file to
http://www.igesund.net/larsivar/ares/codestyle

In the future, it should be present in the SVN repository.
Back to top
View user's profile Send private message
regan



Joined: 21 Jun 2004
Posts: 23

PostPosted: Tue Sep 14, 2004 4:01 pm    Post subject: Re: Code style draft suggestion Reply with quote

larsivi wrote:
I've made a codestyle draft (It's more or less copied from Coin (www.coin3d.org), but grafted onto D.

I try to use this in my own projects and find it clean and nice.

The draft don't discuss templates, mixins or documentation. There are possibly other things that should be mentioned also.


Great work!

Code:

    UPDATE 2001-11-21 larsa: Actually, we now prefer that you use this
    define as an if-condition instead, because of the cleaner look the
    source code gets when it is not littered with preprocessing
    directives.  For permanent debugging code, write therefore source
    code like this instead:


Is this part correct? we don't have pre-processor directives? debugging should be done with

debug (ident) {
}

right?

Code:

   e) Pointer types and references: use a space on each side of the
      '*' and '&' operators, like this

        SoNode * mynode = NULL;

      not like this

        SoNode *mynode = NULL;

      because it makes it look like the '*' "belongs" to the variable
      name (which of course is wrong -- it's part of the type), and
      not like this either

        SoNode* mynode = NULL;

      because it's ugly and unusual. So for consistency, _please_
      stick with the space-on-both-sides convention in Ares code.


I thought D style was:

SoNode* mynode = NULL;

Regan
Back to top
View user's profile Send private message
jcc7



Joined: 22 Feb 2004
Posts: 657
Location: Muskogee, OK, USA

PostPosted: Tue Sep 14, 2004 5:32 pm    Post subject: Re: Code style draft suggestion Reply with quote

regan wrote:
I thought D style was:

SoNode* mynode = NULL;

Regan
I agree. Better yet:
Code:
  SoNode* mynode = null;
Smile
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Ares All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group