January 31, 2007

Why and How of Reading

Starting the series of articles
In 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 function
When 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.

Debugging
When 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 code
The short answer is because the reviewer prevents the code with undesirable effects to be stored in the master source repository.

Reviewing
When 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 code
The 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 home
Could 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.

January 29, 2007

Readability: the Key to Big Income

Power of global code base
During the history of computers, about of 350 million different computer programs were written around the world. Each year brings to life about of 10 million new programs, including new versions of existing ones.
Most of those programs were compiled from source codes written on different programming languages. And those source codes still exist today. There are about of 200 trillions of source code files stored in the Internet.

Can you get advantage of reuse?
There are hundreds of ready solutions for literally any information technology task available in the Internet in the form of source code. It seems very attractive and profitable to use the knowledge collected by others. Just steal the appropriate source code file, add it to your program, and enjoy the success. Your information processing task solved, the program sells. Easy money!

Oops, not so easy.

Write-only code
A random pick of 60 code files doing particular task - getting the function name by its address - shows that source files are in general:
• unreadable due to ugly coding style,
• hard to understand due to obscure logic and lack of explanation,
• difficult to reuse due to numerous explicit and implicit dependencies between code parts.
Code maintainers call this kind of source code "write-only".

Unreadable code breaks the business
The reuse of the source code stolen from Internet is just an example of the problem related to write-only code. Another problem, more important to you, regards the code written by yourself. If the source code of your own program is write-only, you cannot maintain the program - in other words, your business cannot grow. Did you heard about the operating system OS/2? Its development stopped because nobody at IBM could understand its sources.

When the source code is read
In order to write readable source code, you should understand what "readable" means.
Any source code line of any computer program is read at least four times:
• when the developer creates new fragment of the source code containing this line,
• when the developer walks the code fragment line-by-line in the debugger after writing and compiling the fragment,
• when the lead engineer or code buddy reviews it in the difference utility before storing into source version control system,
• and when the maintainer searches for the code to be changed due to extension or bug fix.
The maintainer in turn writes new fragments, and the history repeats.
Each of those activities requires the person in charge to spend some time. Big time is big money. Preventing the time loss is equal to gaining money. Soon we'll see where and how you may earn a few bucks for bread and butter.

January 22, 2007

Laws of code maintenance

Law of additional effort
The greater the quality, the greater the amount of work.

If the quality is not your goal, you just ask what is the code goal, write the source code, compile it and throw away (I mean, give it to customer).

If you want to keep the customer happy, you also write project documents, do code reviews, perform step-by-step debugging, add prerequisite and invariant checking to the code, write test client applications, ensure complete code coverage, profile the code and optimize the performance, determine memory usage trends and reduce the program working set… And so on, and so on.

Law of additional typing
Most program maintenance problems are caused by poor communication ability of the source code. If the code does not express the intent of the author, the maintainer cannot determine the purpose of code fragments, and cannot change the code properly.

Any maintenance problem may be solved by additional explanation, which in fact means additional typing. Additional typing is the cost of understandability. And poor understanding it is the reason of 80% of maintenance failures, as my experience in code reviews shows.

Two sides of code fragmentation
1. The less is the size of the function or class, the less are chances to make error, the more are chances to write correct implementation from first time, and the more are chances to reuse that code in other projects.
2. The less is the size of the function or class, the more your project is fragmented to small pieces, the harder it is to understand it, and the more are chances to make error establishing interfaces.

January 19, 2007

Model Of Your Reader

An importance of looking well
Artificial beings, such as software building the program and OS runtime, parse the program source code and the compiled binary automatically. So turn your face to your human readers - reviewers and maintainers. Remember, the program is you. Spend a bit of efforts to represent yourself smoothly. Make your code looking well.

Listing 1. Excerpt from the source code of real program
void
RescanFile(
HWND hwnd
)
{
COMPITEM ci=NULL;
int iStart;
int iEnd;
int i;

if (selection_nrows < 0 && DisplayMode == MODE_EXPAND) {
if (DisplayMode == MODE_EXPAND) {
iStart = 0;
iEnd = 1;
} else {
iStart = selection;
iEnd = iStart + selection_nrows;
}
for (i = iStart; i < iEnd; i++) {
ci = view_getitem(current_view, i);
if (ci != NULL) {
compitem_rescan(ci);
}
}
} else {
sdkdiff_UI(TRUE);
MessageBox(hwndClient,
LoadRcString(IDS_NOTHING_RESCANNED),
szSdkDiff, MB_ICONSTOPMB_OK);
sdkdiff_UI(FALSE);

return;
}
PostMessage(hwndClient, WM_COMMAND,
IDM_UPDATE, (LPARAM) ci);
} /* RescanFile */


Quiz
Try to answer following questions, while looking at the Listing 1:
• What is i?
• What is the purpose of variable selection?
• Why the function is called RescanFile?
• Which variable represents the file?
• What does the function compitem_rescan()?
• What is the effect of the expression sdkdiff_UI(FALSE) ?
• What is hwnd?
• Can hwndClient be invalid? What are consequences?
• Which operator is executed after last compitem_rescan(ci) ?
• Does the message box mean success?

Analysis
By reason I'll explain in another place, I did not compile and test the code containing that fragment. I assume the code compiles and even works, but I don't like how it looks. For me, this code is hard to read, hard to understand, and hard to maintain.
1. Three different naming conventions mixed together: WinAPI notation (names like "typeName"), C++ notation (names like "something_somethingelse"), and UNIX guru notation (names like "ci"). The code looks inconsistent.
2. Variables with names starting from i are defined and used by rules of C. The variable ci is initialized as in C++, but used like in C. The code is inconsistent.
3. The names of variables and functions do not tell me, what is going on.
4. Although the source code calls WinAPI functions MessageBox and PostMessage that may fail, it does not analyze their return values.
There is no notion of successful completion and failure.
The execution flow is not contiguous.
5. Most variables processed by the function RescanFile come from nowhere and go to nowhere. Data flow is implicit, the inputs and outputs are not reflected in the function's parameter list.
6. I have to look outside the function in order to understand types of DisplayMode, current_view, etc.
7. Real meaning of conditions tested by ifs is not clear.
Each of those little inconveniences may lead to big time loss and even to bugs introduced during the maintenance.

Program is you. Or your user?
Believe or not, the developer writing the code (especially in a hurry) writes for an ideal reader - the best reader in the world, who is capable to understand completely every line of each source file, its purpose, and the reason why it was implemented in that particular way. Now the time for an interesting fact: the more experienced the developer is, the less mental power is expected from the ideal reader. Experienced developers give the reader more hints, than beginners do.

Write as if your ideal reader is less capable than you. Or, at least, write for the person like you. You are the most powerful model of your ideal reader.

Recommendations
I recommend following steps to make the code readable:
1. Don't force you reader to scroll the program back and forth. Describe the function parameters explicitly. Declare, define and initialize variables inside block scope where they are used. Make the code flow more linear, contiguous.
2. Use names that help to understand the code.
3. Use consistent naming notation.
4. Process the code returned by platform API functions.
5. Have clear notions of success and failure of the function.
6. Express the meaning of conditions.

Listing 2. Corrected source code
enum HowToCombineThreadInput
{
THREAD_INPUT_DETACH = 0,
THREAD_INPUT_ATTACH = 1
};

void CombineCurrentThreadInputWithMainThread(
HowToCombineThreadInput combination
)
{
BOOL attach = ( THREAD_INPUT_ATTACH == combination );
sdkdiff_UI( attach );
}

compitem * GetComparisonByRowNumberOrGetCurrentComparison(
view * currentView,
long rowNumber
)
{
return view_getitem( currentView, rowNumber );
}

void RedoChecksumBasedComparisonForRepresentation(
compitem * comparisonOfTwoFilesRepresentation
)
{
compitem_rescan( comparisonOfTwoFilesRepresentation );
}

bool ChecksumBasedComparisonForSelectedRows(
HWND differenceViewerMainWindow,
int displayMode,
long selectedRowInTable,
long numberOfRowsInSelection,
view * currentView
)
{
if ( ! ::IsWindow(differenceViewerMainWindow) )
{
return false;
}
if ( ! currentView )
{
return false;
}

const bool atLeastOneRowSelected = ( numberOfRowsInSelection > 0 );
const bool viewIsExpandedViewOfOneFile = (displayMode == MODE_EXPAND);

if (
! atLeastOneRowSelected && ! viewIsExpandedViewOfOneFile
)
{
CombineCurrentThreadInputWithMainThread( THREAD_INPUT_ATTACH );

LPCTSTR messageText = LoadRcString( IDS_NOTHING_RESCANNED );
// TODO: add resource IDS_PROGRAM_TITLE
LPCTSTR programTitle = LoadRcString( IDS_PROGRAM_TITLE );
UINT contentsAndBehaviorOfDialogBox = MB_ICONSTOP or MB_OK;

if ( ! ::MessageBox(
differenceViewerMainWindow,
messageText,
programTitle,
contentsAndBehaviorOfDialogBox
) )
{
// TODO: process fatal error
}

CombineCurrentThreadInputWithMainThread( THREAD_INPUT_DETACH );

return false;
}

long selectedRowFirst = selectedRowInTable;
long selectedRowAfterLast = selectedRowFirst + numberOfRowsInSelection;
if ( viewIsExpandedViewOfOneFile )
{
selectedRowFirst = 0;
selectedRowAfterLast = 1;
}

compitem * comparisonOfTwoFilesRepresentation = NULL;
for (
long rowNumber = selectedRowFirst;
rowNumber < selectedRowAfterLast;
++rowNumber
)
{
comparisonOfTwoFilesRepresentation =
GetComparisonByRowNumberOrGetCurrentComparison(
currentView,
rowNumber
);
if ( comparisonOfTwoFilesRepresentation != NULL )
{
RedoChecksumBasedComparisonForRepresentation(
comparisonOfTwoFilesRepresentation
);
}
}

if ( ! ::PostMessage(
differenceViewerMainWindow,
WM_COMMAND,
IDM_UPDATE,
(LPARAM)comparisonOfTwoFilesRepresentation
) )
{
return false;
}

return true;
}

void RescanFile(
HWND // hwnd
)
{
if ( ! ChecksumBasedComparisonForSelectedRows(
hwndClient,
DisplayMode,
selection,
selection_nrows,
current_view
) )
{
// TODO: process error
}
}


Maintenance complexity
I had to look in a lot of places in order to complete the sample. Particularly, I had to know about author-defined types: compitem, COMPITEM, view, and VIEW. I had to read comments to the functions and look into implementations, because comments are not always informative.
I don't apologize for names like GetComparisonByRowNumberOrGetCurrentComparison,
because they describe what those functions really do - by desire of their author.
The rewrite of code revealed bugs in the implementation:
• misuse of types int and long,
• fatal error in the code processing error situation,
• hard-coded (non-localized) program title.

Don't trouble the trouble
Although Listing 2 gives more hints to potential reader, I would not like to maintain it. Potential sources of problems are more visible now, but prevention of problems requires making change in other parts of the program. The code fragment now is 4 times longer (The function that does main work is 2 times longer than Listing 1). More things to remember, more chances to introduce an error.

Rewriting the bad code makes sense only if the bad fragment is encapsulated.

January 18, 2007

Tool vs. Brain

What that tool automates?
You have to do a lot of routine operations manually before even trying to use the tool, which is supposed to automate those operations. Only in this case you can understand what kind of your efforts is saved by tool, an in what way. Often the tool requires you to pay too much - or to do too many operations unnecessary for task solution.

Brain still required
Note that automatic tools do not reduce the need of the software engineer to use brain. Tools may verify the syntax, but they cannot write syntactically correct code that solves your task. Tools can find that some code has been changed, but they won't say what the change is for. Tools can notice that since version 1.23.4685 the function Baz returns not the same value as earlier, but they cannot know why. It is the human, not the tool, who makes a decision.

Make you code understandable
A person, which makes the decision about your code, should have enough information to be sure. Main source of information is the code itself. The same briefly: source code. Even with the best tools on the Earth, the maintainer still has to look into your sources. So make them easy to understand.

January 15, 2007

The Program Is You

The program you write is you
The program consists of commands you issue to solve the customer's problem. Notice again: you issue commands, not the computer. You solve the problem, not the compiler. When the user complains "when I press the button, nothing happens", it's you who forgot to process WM_BUTTON_PRESS, not the operating system. Computer, OS, and compiler just store your solution in the form that hardware and software can process. The program is digitized content of your mind.

The program is the representation of you that is "shown" to customer, like distorted sounds of your voice is the representation of you that is "shown" to person calling you by the phone.

So that #%$^& product our team finished last year is me?
Yes, it is.

And that #%$^& blob of #%$^& code I wrote Friday evening is me?
Yes, it is.

World of code
Several hours of each workday you live in the world created by code authors. It's somehow like reading the book or watching the spectacle - you are in. The difference is that you can take other book if the author makes you feel boring. Quit the theater during the action is harder, but still possible. Quitting the boring source code is unfeasible by the reason of salary you are receiving for maintenance of that code.

Don't annoy your readers.

Simple rules of ethics
Don't make silent assumptions. Always articulate your assumptions explicitly. If the C++ syntax doesn't allow you express the assumptions in code, make them in comments.
Don't even try to save a little of your coding time by the cost other people will pay. You are here to make the life of code clients and product users easier, not harder.

Programming is issuing commands
The programmer does not "make" the software package. (Software package, by the way, is the most important part of the product.) The programmer just issues the orders how the package should be organized and how it should behave. Programming is all about orders and commands.
As a programmer, you did issue much more commands to the build system, runtime system and OS than all your managers to you.

You are responsible
You are personally responsible for each command you wrote. Even if the code is generated by the "code wizard application", you are the author because you pressed the button "Generate the code". If the particular code in the program is not attributed to particular person, you are responsible for a whole program.

How the human differs from computer in executing commands
Very often commands you have receive from leaders were unclear or simply dumb. Sometimes you did not know what to say and said - er, um, hm, etc.
Imagine for a moment, that all the manager tells you is recording and can be replayed. No one manager will like it. Even the best manager sometimes contradicts to himself. However, you may vary the way you execute the order and as a result you come with a solution that satisfies the manager.

Computer cannot do that.

Even if the manager speaks to you in artificial language (see "Software for Your Head" by McCarthy), you can stop participating in the discussion. Computer cannot. From other hand, the computer, or the software product, can break/crash/hung.

Be careful writing the code
The source code of the program is the testament graved in stone. It is your trace in the memory of the human race. Often it is the only trace you leave.

January 12, 2007

An art of expression

Programming language expresses all
Due to lack of automated tools verifying contract obligations of the source code, modern developers have to express those obligations in a form of programming language expressions. The source code becomes the contract regulating the use of the source code. Got it? See the recursion?

The source code of modern program has multiple purposes:
• to solve user's task;
• to express the designer intentions;
• to regulate data flow and control flow between client and server parts of the program;
• to catch the mistakes that occur during development;
• to implement non-functional requirements.

The code is written by the developer - for whom? Who consumes the source code?

Three views to the code consumer
The beginner programmer often thinks that the consumer of the source code is the compiler. Respectively, beginners attempt make the program "easy to compile". In other words, they try to fit the program into their, often wrong, expectation of how compiler works.

The average programmer often thinks that the consumer of the source code is the author. Respectively, more or less advanced programmers attempt to express their ego programmatically. They use esoteric C++ constructs and create own variant of function SetStringInComboBox, often as a private member of some class.

And only the experienced programmer, creating design documents by source code, surviving code reviews lead by (incompetent) manager, and leading code reviews of (incompetent) subordinates, understands that that the ultimate consumer of the source code is random unprepared reader.

Brothers and sisters! You write programs for yours poor tired brothers and sisters. Please, help them easily understand your code. Source code is a communication medium. If other people easily understand your code, then you and the compiler will understand it too.

Source code is a communication medium. Assume your boss, or your grandfather, or your daughter will read your source code. Make it clean.

The code is better than conversation
To be more precise, the code stored under the source control is better than the poorly remembered conversation that occurred six months ago.

As a study (*) shows, "many problems arose because developers were forced to invest great effort recovering implicit knowledge by exploring code and interrupting teammates and this knowledge was only saved in their memory".

Face-to-face meetings with teammates represent an interruption that is hard to recover from.

Instead of trying to draw the implicit knowledge from humans, use explicit, written repositories of code-related knowledge:
• Project documentation,
• Bug databases,
• Source history,
• Comments,
• Books and magazines,
• Internet.

Write down mental models. Scan the napkin where the author explained the idea, and store the picture in the source control system.

(*) Thomas D. LaToza, Gina Venolia, Robert DeLine. Maintaining Mental Models: A Study of Developer Work Habits. ICSE'06, May 20-28, 2006, Shanghai, China.

January 10, 2007

$500 For Stopping My Wrong Program To Compile

Callable entity
Anything the C++ programmer can call - functions, operators, constructors and destructors - are the callable entities. The callable entity is anything that has parenthesis in its definition.
The callable entity is the server providing useful work, the caller is the client delegating the efforts to server.
Victor Shtern recommends to programmers do push responsibilities to the server.

The callable entity has contractual obligations
The work with each callable entity involves you in relationship of several kinds:
1. Between you (server) and your client.
2. Between you (client) and callable entities functions your code calls.
3. Between you (developer) and the originator of the idea why the entity doing so and so should be written.
4. Between you (developer) and maintainer of your code.
5. Between you (maintainer) and inventors of ideas behind the original code.
6. Between you (author of current code version) and the user of the software product.
7. Between you (author of current code version) and the vendor of development tools: compiler, linker, and so on.
Each relationship is regulated by specific contract.


Client-server contract describes:
· Pre-conditions that should be met before client calls the server.
· The data passed between client and server (entity's interface).
· Effects of the server execution other than client-server data exchange.
· Post-conditions that should be met after the server completes the call.


Inventor-developer contract describes:
· What should be done, and why.
· What should be not done, and why.
Developer-maintainer contract describes:
· What the code in fact does, and why.
· What the code in fact does not, and why.
· How the wrong program behavior is reported to maintainer.


Author-user contract describes:
· Guarantees of fitness for particular purpose (functionality, stability, performance, security).
· How the wrong program behavior is reported to user.


Author-tool vendor contract describes:
· Rules of programming language.
· Deviations from standard rules.
· Application programming interface (API).


"- So my function BeepAndExitProgram() five lines long is the subject of all those contracts?"
Yes, it is.

Bad contracts
Unfortunately to most participating parties, often contracts of any particular callable entity are:
· unwritten;
· or stored separately from the callable entity code;
· or ill-formed (incomplete, ambiguous, contradictive), so they allow multiple interpretations;
· or cannot be executed to force parties behave according to contract.

Good contracts
You should avoid such careless approaches to contracts. Keep your assumptions and requirements about callable entity explicitly written in the form of the source code.

The rule is simple: the code that violates contract should not compile.

What I pay for
The problem of modern software engineering is the lack of tools that:
· verify various contract obligations,
· and do not allow the product to build if it violates obligations.
Just find the way to express contracts in C++ (or otherwise integrate contract verification with a build process), and I'll pay $500 for that tool.
Start with a simple C++ preprocessing tool (parser), that detects only one of hundreds possible pre-conditions: that COM function could be invoked without preceding CoInitialize(). I'll pay $25 for that tool. Anybody will.

January 9, 2007

Getting Paid to Hello, World

Regular operating system users definitely will have no profit from the program, which source code is:
#include <Windows.h>

#include <string>
#include <iostream>

int main()
{
try
{
std::string greeting( "Hello, world!" );
std::cout << greeting << std::endl;

DWORD frequencyHertz = 880;
DWORD durationMilliseconds = 400;
::Beep( frequencyHertz, durationMilliseconds );

return 0;
}
catch(...)
{
return 1;
}
}

However, software developers have benefits from the program itself and from the process of its implementation. Developers use them as technology test tools.
Developers know well: even the production of such a simple program is a challenge, and the resulting string output on the command line terminal may be considered a victory. And money will follow the winner.

What are details?

First, the program source code must be stored.
"Stored" in our era means not merely "saved on the disk", but also "put under source version control" and "regularly backed up".
Give the simple, seamlessly working storage system to developers, and they will pay.

Second, you should have libraries supporting the programming language. In our case, this is C++ Standard Library represented by and header files, which, in turn, include other header files.
This is where std::string, std::cout, and std::endl came from.
There are several known realizations of the C++ Standard Library. Writing your own one requires significant intellectual effort, so for starters you may just re-implement a part of the library or make your own extension. If it makes the client's life easier, clients will reward you in casso.
Going in another direction, you could sell by competitive price the detailed comparison of different C++ library implementations. Your recommendations, which one is good for particular usage scenario, will make someone's day.

Third, you need the libraries connecting your program to resources of your operating system. The use of function Beep requires the inclusion of , which requires the installation of Windows Platform Software Development Kit (often called Windows SDK or Platform SDK).
On my Windows box I have 4 different versions of Platform SDK. Offer me a way to manage them easily, and I'll refund your efforts.

Next, the program source code must be accessible to build tools: compiler, linkage editor, and librarian.
Open the program text above in your latest super-powerful Integrated Developer's Environment (IDE) and try to "just build" it. You can't. In order to build, you need to provide command line parameters for build tools. In big IDE that means you should set up the infrastructure: project file, makefile, build configuration, or whatever the manufacturer calls it. You may conquer the market with the tool that generates the project by single source file. Or the utility that converts Autotools makefiles or project files made by XCode to solutions usable from Visual Studio.

Most important, the program must compile.
It should be written according to the rules of the programming language: C++ in our case.

To be continued...