General Rules

From ScorecWiki

Jump to: navigation, search

Contents

No "spaghetti code"

See http://en.wikipedia.org/wiki/Spaghetti_code

  • Definition:* Program code written without a coherent structure. The logic moves from routine to routine without returning to a base point, making it hard to follow. It implies excessive use of the _GOTO_ instruction, which directs the computer to branch to another part of the program without a guarantee of returning. In structured programming, functions are used, which are subroutines that guarantee a return to the instruction following the one that called it.
  • Example:* Below is an example of what would be considered a trivial example of spaghetti code in BASIC. The program prints the numbers 1 to 10 to the screen along with their square. Notice that indentation is not needed and that the program's GOTO statements create a reliance on line numbers. Also observe the unpredictable way the flow of execution jumps from one area to another. Real-world occurrences of spaghetti code are more complex and can add greatly to a program's maintenance costs.
10 i = 0
20 i = i + 1
30 PRINT i; " squared = "; i * i
40 IF i >= 10 THEN GOTO 60
50 GOTO 20
60 PRINT "Program Completed."
70 END

Here is the same code written in a structured programming style:

FOR i = 1 TO 10
    PRINT i; " squared = "; i * i
NEXT i
PRINT "Program Completed."
END

The program jumps from one area to another but this jumping is predictable and formal. This is because using for loops and functions are standard ways of providing flow control whereas the goto statement encourages arbitrary flow control. Though this example is small, real world programs are composed of many lines of code and are difficult to maintain when written in a spaghetti code fashion.

Miscellaneous

Do

  • Allocate memory to class data member only when needed
 #define SAFE_DELETE(p) {delete (p); (p)=NULL; }
 typedef std::map<int, mEntity*> remoteCopyMap;
 class mEntity
 {
   pmEntity* thePClassification;      // partition classification
   remoteCopyMap* theRemoteCopies;    // remote copy container
 } 

[Bad]
 mEntity::mEntity()
 {
    // Only part boundary entity needs the two members set
    // However, this example use memory no matter what the members are needed or not
    thePClassification = new pmEntity;    
    theRemoteCopies = new remoteCopyMap;  
 }


[Good]
 mEntity::mEntity()
 {
    // The constructor does not use any memory initially
    thePClassification = NULL;  
    theRemoteCopies = NULL;
 }

 // When needed, assign the memory;
 thePClassification = new pmEntity;
 theRemoteCopies = new remoteCopyMap;

 // When not needed, deallocate the memory
 thePClassification = NULL;      // nullify partition classification for non-part boundary entity
 SAFE_DELETE (theRemoteCopies);  // remove remote copy container for non-part boundary entity

[Note 1] Declare class members as pointer
[Note 2] Do NULL check before any operation on pointer members
[Note 3] Define copy constructor and assignment operator for the class with pointer members
  • Delete pointer members in destructors
[Bad]
 mEntity::~mEntity()
 {
 }

[Good]
 mEntity::~mEntity()
 {
   thePClassification = NULL;
   SAFE_DELETE (theRemoteCopies);
 }
  • Prefer short int to int
[Good]
 int dim;          // range of entity dimension is 0 to 3

[Better]
 short int dim; 
  • Prefer pre-increment to post-increment

Good:

for (unsigned int i = 0; i < 5; ++i) {
    std::cout << "Hello " << i << '\n';
}

Not as good:

for (unsigned int i = 0; i < 5; i++) {
    std::cout << "Hello " << i << '\n';
}
  • Put a newline character at the end of files. You may be able to set your editor to do this automatically.


STL

  • Use "reserve" to avoid unnecessary reallocations
[Bad]
vector<int> v;
for (int i=1; i<=1000; ++i) push_back(i); 

[Good]
vector<int> v;
v.reserve(1000);
for (int i=1; i<=1000; ++i) push_back(i);
  • Explicitly deallocate memory after using map

Don't

  1. vector<bool>
  2. Declare variable in for loop


SCOREC Code Interfaces

  • General
    • name is <project_name>.h ex) FMDB.h, meshAdapt.h, SGMI.h
    • pure C interfaces - use 'extern C' if using c++ compiler
    • clear separation between 'internal' functions and 'external' functions
      • internal functions should not appear in <project_name.h>;
      • external functions should appear, and call internal functions inside.
  • Function naming
    • FMDB_ - FMDB (FMDB_M_load(Mesh) - load the mesh in FMDB)
    • MA_ - MeshAdapt
    • GMI_ - SGMI
    • AMSI_ - AMSI
    • IPCM_ - IPComMan

Files

File length

  • Length of a file shall not exceed 2000 lines.

Including files

  • include the minimal number of header files in interface files
  • avoid including header files that are unused


Class declaration format

  • In C++ language, shall declare a class as illustrated in the example
// class declaration template

class XX
{
public:
    XX();
    XX( const XX&);   //copy constructor
    ~XX();
    // OPERATORS
    XX& operator=( XX&); // assignment operator
    // OPERATIONS
    // ACCESS
    // INQUIRY
protected:
private:
};

// INLINE METHODS
// EXTERNAL REFERENCES
#endif  // _XX_H_
  • In C++ language, define class in public, protected and private order
class Date
{
public:
    Date();
    Date( int year);
protected:
    void print();
private:
    void draw();
};

Enumerations

Here there will be a list of enumerations for different aspects of dealing with the mesh / topology / errors. The link to the ITAPS iBase interface enumerations. http://www.itaps-scidac.org/software/specifications/iBase-v0.8.h

Personal tools