Best Practices
Write clean, maintainable, and bug-free C++ code.
๐งน Clean Code Rules
One function, one job
Each function should do exactly one thing. If you can't describe it without 'and', split it.
Keep functions short
Aim for 20-30 lines max. If a function is longer, break it into helper functions.
Use const wherever possible
Mark variables, parameters, and methods as const when they shouldn't change.
Initialize all variables
Never rely on default values. Always give variables an explicit initial value.
Avoid magic numbers
Replace hardcoded numbers with named constants: const int MAX_STUDENTS = 100;
RAII โ Resource Acquisition Is Initialization
Acquire resources in constructors, release in destructors. Use smart pointers.
// โ BAD โ Magic numbers, unclear names, too much in one function
void f(int a[], int n) {
for(int i=0; i<n; i++)
if(a[i] > 100) a[i] = 100;
int s = 0;
for(int i=0; i<n; i++) s += a[i];
cout << s/n;
}
// โ
GOOD โ Named constants, clear names, single responsibility
const int MAX_SCORE = 100;
void capScores(int scores[], int count) {
for (int i = 0; i < count; i++) {
if (scores[i] > MAX_SCORE) {
scores[i] = MAX_SCORE;
}
}
}
double calculateAverage(const int scores[], int count) {
int total = 0;
for (int i = 0; i < count; i++) {
total += scores[i];
}
return static_cast<double>(total) / count;
}
void displayClassAverage(int scores[], int count) {
capScores(scores, count);
double avg = calculateAverage(scores, count);
cout << "Class average: " << avg << endl;
}๐ Naming Conventions
// Variables โ camelCase
int studentCount = 0;
double averageScore = 85.5;
string firstName = "Alice";
// Constants โ UPPER_SNAKE_CASE
const int MAX_RETRIES = 3;
const double TAX_RATE = 0.08;
// Functions โ camelCase (verb-first)
void calculateTotal();
bool isValidEmail(string email);
int findMaxValue(int arr[], int size);
// Classes โ PascalCase
class StudentManager { };
class BankAccount { };
// Private members โ with underscore or m_ prefix
class Employee {
string m_name; // m_ prefix style
double salary_; // trailing underscore style
};
// Enums โ PascalCase type, UPPER values
enum class Color { RED, GREEN, BLUE };
enum class Status { ACTIVE, INACTIVE, PENDING };
// File names โ snake_case
// student_manager.cpp
// bank_account.h๐ง Debugging Techniques
1. Print Debugging
Add cout statements to trace variable values and execution flow. Remove them after fixing.
2. Rubber Duck Debugging
Explain your code line by line to an imaginary listener. The act of explaining often reveals the bug.
3. Binary Search Debugging
Comment out half your code. If the bug disappears, it's in the commented half. Repeat.
4. Read the Error Message
Compiler errors tell you the file, line, and what's wrong. Read from the first error โ later errors are often cascading.
5. Check Edge Cases
Test with: empty input, one element, very large values, negative numbers, and boundary values.
6. Use a Debugger
Learn GDB or your IDE's debugger. Set breakpoints, step through code, and inspect variables at runtime.
// Using print debugging to trace a sorting bug
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
cout << "[DEBUG] Pass " << i + 1 << endl; // Track passes
for (int j = 0; j < n - i - 1; j++) {
cout << " Comparing arr[" << j << "]=" << arr[j]
<< " with arr[" << j+1 << "]=" << arr[j+1] << endl;
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
cout << " โ Swapped!" << endl;
}
}
// Print array state after each pass
cout << " Array: ";
for (int k = 0; k < n; k++) cout << arr[k] << " ";
cout << endl;
}
}โ ๏ธ Common Mistakes
// โ MISTAKE 1: Using = instead of == in conditions
if (x = 5) { } // WRONG โ assigns 5 to x (always true)
if (x == 5) { } // CORRECT โ compares x to 5
// โ MISTAKE 2: Off-by-one errors in loops
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i <= 5; i++) { } // WRONG โ accesses arr[5] (out of bounds!)
for (int i = 0; i < 5; i++) { } // CORRECT โ stops at arr[4]
// โ MISTAKE 3: Forgetting to close files
ofstream file("data.txt");
file << "Hello";
// WRONG โ file not closed, data may not be written!
file.close(); // CORRECT โ always close your files
// โ MISTAKE 4: Integer division when you want decimal
int a = 7, b = 2;
double result = a / b; // WRONG โ result is 3.0 (integer division)
double result = (double)a / b; // CORRECT โ result is 3.5
// โ MISTAKE 5: Memory leaks with new/delete
int* p = new int(42);
p = new int(100); // WRONG โ lost pointer to first allocation!
delete p; // Only deletes the second one
// โ MISTAKE 6: Forgetting break in switch
switch (x) {
case 1: cout << "One"; // WRONG โ falls through to case 2!
case 2: cout << "Two";
}
switch (x) {
case 1: cout << "One"; break; // CORRECT
case 2: cout << "Two"; break;
}
// โ MISTAKE 7: Dangling else
if (a > 0)
if (b > 0)
cout << "Both positive";
else // This else belongs to inner if, not outer!
cout << "a is not positive"; // MISLEADING
// CORRECT: Always use braces
if (a > 0) {
if (b > 0) {
cout << "Both positive";
}
} else {
cout << "a is not positive";
}