Software Documentation & Refactoring
Premise: Why Documentation Matters
Documentation is a key component in the maintainability, readability, and usability of software projects. It provides crucial context for future developers, stakeholders, and users.
Types of Documentation
Internal Documentation
- Written within the code as comments.
- Includes inline documentation, function headers, and variable explanations.
External Documentation
- Includes manuals, design documents, user guides, and API documentation.
- Typically maintained in separate files or documentation systems.
What Must We Document?
- What is the data?
- Data source/destination (e.g., database, API)
- Transaction and input validation logic
- What is the code doing to the data?
- Logic behind variable names
- Explanation of methods, functions, and procedures
Example: Poorly Documented vs Well Documented Code
Poorly Documented:
int foo(int n) {
if (n <= 1)
return 1;
else
return n * foo(n - 1);
}
Well Documented:
/**
* Calculates the factorial of a given integer using recursion.
* @param n The integer for which the factorial is to be calculated.
* @return The factorial of the given integer.
*/
int factorial(int n) {
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
Self-Documenting Code
Writing code that explains itself is often more effective than lengthy comments.
Guidelines:
- Descriptive Naming: Functions and variables should be named clearly (e.g.,
calculateAverage
instead ofcalcAvg1
). - Coding Style: Choose and consistently enforce a style guide.
- Minimal Comments: Use comments only to explain why, not what.
Documentation Extraction Tools
Tools help convert code comments into structured documents:
- JavaDoc for Java
- Doxygen for C/C++
- rdoc for Ruby
These tools use specially formatted comments to generate readable docs.
Your Organization Should Define and Enforce:
- Naming conventions:
- Variables:
snake_case
- Functions:
camelCase
- Variables:
- Avoid using numbers for variable differentiation
- Use standard abbreviations (
dept
,cust
) - Maintain modular code with consistent indentation and block structures
Code Structure and Style
Good structure includes:
- Modular functions
- Consistent use of braces
- Clear separation of logic
- Minimal global state
Fundamental Principles
- The best documentation is the code itself.
- Don't document bad code—refactor it instead.
Code Refactoring
Refactoring is the process of improving the internal structure of the code without changing its behavior.
Why Refactor?
- Increase readability
- Reduce complexity
- Eliminate duplication
Example: Poorly Written code vs Well Written Code
Poorly Written Code Example
#include<iostream>
using namespace std;
int main() {
int a, b;
cout << "Enter two numbers: ";
cin >> a >> b;
int sum = a+b, sub = a-b, mul = a*b, div = a/b, mod = a%b;
cout << "Sum: " << sum << endl << "Difference: " << sub << endl;
cout << "Product: " << mul << endl << "Division: " << div << endl;
cout << "Modulus: " << mod << endl;
return 0;
}
Refactored Version
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int multiply(int a, int b) {
return a * b;
}
double divide(int a, int b) {
if (b == 0) {
cout << "Error: Division by zero." << endl;
return 0;
}
return static_cast<double>(a) / b;
}
int modulus(int a, int b) {
return a % b;
}
int main() {
int num1, num2;
cout << "Enter two numbers: ";
cin >> num1 >> num2;
cout << "Sum: " << add(num1, num2) << endl;
cout << "Difference: " << subtract(num1, num2) << endl;
cout << "Product: " << multiply(num1, num2) << endl;
cout << "Division: " << divide(num1, num2) << endl;
cout << "Modulus: " << modulus(num1, num2) << endl;
return 0;
}
Technical Debt
Like financial debt, technical debt refers to short-term solutions in code that lead to long-term problems.
Causes:
- Business pressure
- Lack of documentation and testing
- Poor collaboration
- Long-lived development branches
- Incompetent or rushed decisions
Clean Code Principles
- Easy for other programmers to read
- No duplication
- Fully tested
- Easy and cost-effective to maintain
When to Refactor
- When adding new features
- When fixing bugs
- During code reviews
How to Refactor
- Make the code cleaner
- Avoid changing functionality
- All tests must pass post-refactor
Reflection Questions
- Why is version control critical for documentation?
- What is the primary purpose of inline comments?
- What kind of documentation serves end users?
Summary
- Good documentation improves code maintainability by clarifying what the code does, how data is used, and why certain decisions were made—for both internal (comments, naming) and external (manuals, API docs) audiences
- Self-documenting code and coding standards (clear naming, consistent formatting, modular design) reduce the need for excessive comments and make the code itself a primary source of truth
- Refactoring and clean code practices help eliminate technical debt, ensuring code remains readable, testable, and easy to update—without adding new features during the cleanup process
Disclaimer: Generative AI was used in part to generate these lecture notes.