-
Notifications
You must be signed in to change notification settings - Fork 1
1.1. Standards: Principles from Code Complete
This coding standard 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."
- 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";
int employee_count;
double total_revenue;
// GOOD
bool is_valid_input(int input);
// BAD
bool chk_inp(int in);
Stick to a consistent naming convention, e.g., snake_case for variables and PascalCase for classes.
double interest_rate;
class BankAccount { /* ... */ };
// Calculate average temperature to assess if heating is needed (why)
float avg_temperature = calculate_average(temperatures, num_readings);
/**
* @brief Calculates the area of a circle.
* @param radius The radius of the circle.
* @return The area of the circle.
*/
double calculate_circle_area(double radius)
{
return M_PI * radius * radius;
}
// GOOD (Single Responsibility)
double calculate_tax(double price, double tax_rate)
{
// ... implementation
}
// BAD (Multiple Responsibilities)
void process_order(Order* order)
{
calculate_price(order);
apply_discount(order);
send_email_confirmation(order);
}
int divide(int numerator, int denominator)
{
// Negative Check (Guard Clause)
if (denominator == 0)
{
throw std::runtime_error("Error: Division by zero");
}
// Positive Flow (Main Logic)
return numerator / denominator;
}
try
{
int result = divide(10, 0); // Potential for division by zero
}
catch (const std::runtime_error& e)
{
std::cerr << "Error: " << e.what() << std::endl; // Clear error message
}
Encapsulation bundles data (attributes) and the operations that manipulate that data (methods) into a single unit, the class. This hides implementation details, making the code easier to understand and maintain.
// Example (C++)
class BankAccount
{
private: // Private members (encapsulated)
double balance;
public:
void deposit(double amount)
{
balance += amount;
}
double getBalance() const
{
return balance;
}
};
In this example, the balance
attribute is private, so it can only be modified or accessed through the public deposit
and getBalance
methods. This protects the internal state of the object.
Inheritance allows you to create new classes (derived classes) that are based on existing classes (base classes). Derived classes inherit the properties and behaviours of the base class, promoting code reuse and establishing hierarchical relationships.
// Example (C++)
class Animal // Base class
{
public:
virtual void makeSound() const = 0; // Pure virtual function
};
class Dog : public Animal // Derived class (inherits from Animal)
{
public:
void makeSound() const override
{
std::cout << "Woof!\n";
}
};
class Cat : public Animal // Derived class (inherits from Animal)
{
public:
void makeSound() const override
{
std::cout << "Meow!\n";
}
};
Polymorphism enables you to use objects of different classes through a common interface. This flexibility is achieved through virtual functions (C++) or function pointers (C), allowing the same function call to behave differently based on the object's type.
// Using polymorphism (C++)
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
animal1->makeSound(); // Output: Woof!
animal2->makeSound(); // Output: Meow!
Unit tests are small, isolated tests that verify the correctness of individual units of code (e.g., functions, methods).
// Example (using Google Test framework in C++)
TEST(MathTest, Addition)
{
EXPECT_EQ(add(2, 3), 5);
EXPECT_EQ(add(-1, 1), 0);
}
Code reviews involve having other developers examine your code to catch errors, improve code quality, and share knowledge.
Tools like linters (e.g., Clang-Tidy) and formatters (e.g., ClangFormat) can help you automatically enforce coding standards and detect potential issues.
Added error handling for invalid file input in process_data() function.
See also Commit Message: The 50/72 Rule: A Simple Guide
Involves two developers working on the same code simultaneously, sharing knowledge, catching errors, and improving design.
- Use comments within the code to explain complex logic or important decisions.
- Create external documentation (README files, wikis, etc.) to provide an overview of the project, instructions for use, and API references.
- Language-Specific Conventions: Follow the conventions and best practices specific to the programming language you're using.
- Performance: Consider performance implications, but prioritize readability and maintainability over premature optimization.
- Security: Write secure code by following best practices to prevent vulnerabilities (e.g., input validation, sanitization).
- McConnell, S. (2004). Code Complete: A Practical Handbook of Software Construction (2nd ed.). Microsoft Press. Retrieved from https://github.com/media-lib/prog_lib/blob/master/general/Steve%20McConnell%20-%20Code%20Complete%20(2nd%20edition).pdf