Skip to content

1.1. Standards: Principles from Code Complete

kanjoe24 edited this page Nov 5, 2025 · 4 revisions

Standards: Principles from Code Complete (C/C++)

This coding standard is inspired by the principles in Steve McConnell's Code Complete, aiming for clarity, maintainability, and robustness:

  • "Effective software construction practices are crucial for maintaining code quality."

Organization level guidelines

1. Layout and Formatting

  • Indentation: Use consistent indentation (spaces, not tabs) to clearly show code structure.
  • Line Length: Keep lines to a reasonable length (around 80 characters).
  • Whitespace: Use blank lines to separate logical sections.
  • Braces: Always use braces for blocks, even for single-statement blocks. Place each brace on a new line.
// GOOD
if (x > 0)
{
    std::cout << "x is positive\n";
}
else
{
    std::cout << "x is not positive\n";
}

// BAD (no braces for single-statement block)
if (x > 0)
    std::cout << "x is positive\n";

2. Naming Conventions

Function Naming Rules

  1. Use Descriptive Names: Names should clearly convey function intent.
// GOOD
double calculateInvoiceTotal();
void sendEmailNotification();

// BAD
double process();
void doTask();
  1. Prefer Verbs: Functions perform actions, so use verbs.
// GOOD
bool validateUser(int id);
std::string fetchCustomerData(int customerId);

// BAD
bool checkUser(int id);
std::string getData(int customerId);
  1. Be Consistent: Stick to uniform naming conventions across the project.
// GOOD
std::string fetchUserInfo();
void updateUserProfile();

// BAD (Inconsistent naming)
std::string retrieveUserInfo();
void modifyUserProfile();
  1. Avoid Ambiguity: Names should be precise.
// GOOD
void validateUserInput(std::string input);

// BAD
void handleInput(std::string input);
  1. Concise but Clear: Function names should be long enough for clarity but not overly verbose.
// GOOD
void loadUserPreferences();

// BAD
void loadUserPreferencesFromDatabaseIfPresentOtherwiseUseDefaults();
  1. No Generic Words: Avoid vague terms like data or info.
// GOOD
void saveUserSettings();

// BAD
void saveData();
  1. Match Behavior to Name: Boolean functions should reflect expected values.
// GOOD
bool isValid();

// BAD
bool checkValidity();
  1. Avoid Negatives: Prefer positive naming conventions.
// GOOD
bool isAvailable();

// BAD
bool isNotAvailable();
  1. Easy to Pronounce: Clear naming improves communication.
// GOOD
double computeAverage();

// BAD
double cmpAvg();
  1. Reflect Expected Output: Ensure function names indicate return values.
// GOOD
std::string getUserName();
int countActiveSessions();

// BAD
std::string fetch();
int sessions();

3. Comments and Documentation

Clear Comments

Use comments to explain why a piece of code exists, rather than just describing what it does.

// Calculate average temperature to assess if heating is needed
float avg_temperature = calculateAverage(temperatures, num_readings);

Doxygen Comments (C++)

/**
 * Calculates the area of a circle.
 * @param radius The radius of the circle.
 * @return The computed area.
 */
double calculateCircleArea(double radius) 
{
    return M_PI * radius * radius;
}

4. Functions and Modules

Single Responsibility Principle (SRP)

Each function should have a single well-defined responsibility.

// GOOD
double calculateTax(double price, double tax_rate);

// BAD (Multiple Responsibilities)
void processOrder(Order* order);

Guard Clauses for Error Handling

int divide(int numerator, int denominator) 
{
    if (denominator == 0) 
    {
        throw std::runtime_error("Error: Division by zero");
    }
    return numerator / denominator;
}

5. Error Handling (C++)

try 
{
    int result = divide(10, 0);
} 
catch (const std::runtime_error& e) 
{
    std::cerr << "Error: " << e.what() << std::endl;
}

6. Object-Oriented Programming

Encapsulation

class BankAccount 
{
private:
    double balance;
public:
    void deposit(double amount) 
    {
        balance += amount;
    }
    double getBalance() const 
    {
        return balance;
    }
};

Inheritance and Polymorphism

class Animal 
{
public:
    virtual void makeSound() const = 0; // Pure virtual function 
};

class Dog : public Animal 
{
public:
    void makeSound() const override 
    {
        std::cout << "Woof!\n";
    }
};

class Cat : public Animal 
{
public:
    void makeSound() const override 
    {
        std::cout << "Meow!\n";
    }
};

7. Testing and Quality Assurance

Unit Tests

// Example (using Google Test framework)
TEST(MathTest, Addition) 
{
    EXPECT_EQ(add(2, 3), 5);
    EXPECT_EQ(add(-1, 1), 0);
}

Code Reviews and Automated Testing

  • Use linters like Clang-Tidy for code style.
  • Use static analysis tools for bug detection.

8. Collaboration and Communication

Clear Commit Messages (Example)

Added error handling for invalid file input in processData() function. 

See also Commit Message: The 50/72 Rule

Documentation:

  • Use comments within the code for complex logic.
  • Maintain external documentation (README files, wikis, etc.).

References

  • McConnell, S. (2004). Code Complete: A Practical Handbook of Software Construction (2nd ed.). Microsoft Press. Retrieved from GitHub Repository

Clone this wiki locally