Starting the series of articlesIn order to turn the source code reading into profit generator, we need to know why different persons - developer, reviewer, and maintainer - read the code at all. We'll analyze typical reading scenarios and elaborate a set of reading-friendly software development techniques. Those techniques will allow you to accomplish reading tasks faster and cheaper than your competitors.
Why the developer reads the source code The short answer is because the developer makes sure that just written code does what it is supposed to do.
Implementing the functionWhen you are in the developer position and write the body of the function X (assuming the design work is already done), your tasks are:
1. Find the sequence of elementary steps you need to perform in order to complete the task. For example, in order to create memory-mapped file in Windows, you need first open the file, then create the memory mapping section linked to that file, and then create the range of addresses ("view") over the memory mapping section. The time here is spent when you:
• Read background topics in the Operating System API documentation.
• Search for ready samples in API documentation.
• Search for algorithms in books and in the Internet.
2. Write the inline code, the call to API function, the call to third-party library function, or the call to your own function implementing each step. You spend the time on following topics:
• Search for the function doing the required task in the Operating System API documentation.
• If previous search failed, try to find a function doing the required task in your project or previous projects.
• If previous search failed, try to find a function doing the required task in third-party library (including libraries already bought or to-be-bought).
• If there is no such function, or if the library is too expensive for your task, you need to write the function yourself. Generally, it means dividing the task to subtasks and repeat previous steps for subtasks.
Calling the function When you write the call to the function Z, your tasks are:
1. Gain basic knowledge about the function: type and purpose of return value and parameters, prerequisites, special conditions, errors. Your occupation is:
• Read the official documentation of Z provided by authors or vendors.
• If the official documentation is missing, getting the description from the Internet.
• If there is no shared description (which by itself is very bad sign), read source code. At least the header file to this function should exist, or else you should not use that function.
2. Transfer the function description from a genuine or surrogate documentation to the call site in the source code. That includes:
• Copying the function signature and adapting it to your coding conventions.
• Obtaining values to be used as function arguments, and passing them to function parameters.
• Analyzing results and processing errors.
3. Integrate supporting libraries into your build system:
• Copy libraries and correspondent C++ headers into your source code tree.
• Include header files into correspondent C++ files.
• Include paths to libraries and header files in your build configuration.
• Add library object files to your linker configuration.
4. Make sure the function does compile:
• Verify that all formal parameters have matching actual arguments.
• Verify that types of correspond to types of formal parameters.
DebuggingWhen you go through your code step by step in the debugger, your tasks are:
1. Determine what particular function does:
• Analyzing the function name.
• Analyzing the names and types of passed arguments and return value.
• Analyzing how parameters are passing.
• Reading comments, if available.
2. Determine how the function execution affects the system:
• Determine what data should change.
• Determine how the data should change.
• Examine which data are in fact changed.
• Examine how data are in fact changed.
Why the reviewer reads the source codeThe short answer is because the reviewer prevents the code with undesirable effects to be stored in the master source repository.
ReviewingWhen you are in the reviewer position and look at new code fragment, your tasks are:
1. Understand what the code fragment does. Time passes when you:
• Determine which parts of fragment are known/unknown.
• Determine the origin of unknown parts: written by developer, parts of Operating System API, and parts of third party API.
• If unknown parts are written by developer, search and read the implementation.
• If unknown parts come from some API, read the documentation. That is similar to how the developer gains base knowledge about the function.
2. Determine whether the actual behavior of the fragment is the desired behavior:
• Look for visual symptoms of frequently occurring bugs - resource leaks, buffer overflow, possibility of bad pointers to pass in, disabled compiler warnings, etc.
• Look at compiler warnings for symptoms of frequently occurring bugs: variables used without being initialized, assignment in conditions, type cast with truncation, etc.
• Compare actual behavior of the fragment with the functionality required by project documentation.
• Compare the fragment implementation with known similar fragments in other parts of the source code.
• Ask the developer to explain parts that are difficult to understand.
3. Ensure that new fragment follow the project's coding style. The time is mostly spent by visual searching for formal mismatches in the new text.
Why the maintainer reads the source codeThe goal of maintainer is to make desired change in the existing functionality.
Maintaining When you are in the maintainer position and look at the project's source code, your tasks are:
1. Understand the purpose of the project, module, or file. Time eaters are:
• Read the project documentation: requirements and design documents.
• Read the test documentation: acceptance checklists and step-by-step test cases.
• Read the reference information accompanying the shipping product: manuals, instructions, help system.
• Read the source code. That is similar to understanding of code fragment by reviewer.
• Search the description of intended behavior in transcripts of developer's communication with a customer.
• Read the source code of test client applications.
2. Determine what parts of the module to be changed are risky:
• Look in the version control system for files that change often or experience big changes.
• Reading bug reports.
• Reading product release notes and frequently occurring problems reported by help desk.
• Talk with testers, developers, and managers.
3. Find the place in the code where the change will be made:
• Read the code from the "just do it" perspective.
• Read the code from "minimal change" perspective.
• If the part to be changed is risky, read the code from the "minimal harm" perspective.
4. Apply the change. It is similar to developer's tasks.
5. Document your change. The time consuming operations are:
• Update the project documentation.
• Update the reference information accompanying the shipping product.
Try it at homeCould you analyze these tasks yourself? Why the reading requires so much time? How to make the source code, and optionally other documentation, readable? Invent your own solutions of that problem. Which relationship between tasks will help you? What can be automated? This is your homework today.