I realized this while doing further research into Google’s Go language. The design of Go is the definition of a language that surpasses Java and C++ in the area of productivity while maintaining many of the high performance attributes of the C language. I am not switching to Go because while it is a major language at Google that is responsible for powering their multi-billion dollar operation, there is still a few years left before it will be known if it is truly solid. I plan to experiment with it in the meantime. The Go language will probably hit critical mass when it “genuinely” makes it to its third generation.
A downside to aggressively applying a language early in a production environment is you learn workarounds or rules of thumb that becomes part of your instinctive use of the language. In later versions of that language, those same improvement measures can become liabilities in the effective use of a more solid language and platform implementation. Of course some approaches remain timeless in their application but keeping informed of which methods are sound and which have become cargo cult practices can be obscure.
Pardoning that aside, lessons and insights in the design of Go may inform a person’s use of other languages. I see Go as successfully achieving a minimal subset of imperative programming languages broadly applicable to real-world software. An in-depth description of how Go achieves sustainable, high performance, real-world software is covered in a document from Google titled, Go at Google: Language Design in Service of Software Engineering. I will not repeat all of that here. The point of this article is to highlight an insight.
Passing Your Scope
The most effective practice I have found to write C++ code faster and with less error is to pass your scope. Where you declare a variable matters. Variables at a global scope, module or class, are convenient to access but can complicate matters in the form of coupling, dependency management, and run time resource management. Issues you clearly do not want. Local variables are the total opposite, they just work.
The effective technique in C++ is to migrate data from one local scope to another. I have not found this documented anywhere and I may not have looked hard enough, but C++ actually enforces this implicitly. Declare a variable local to a stack bound function allocated from the heap and then return that variable on function exit. You can make it work, usually not by default, and usually not consistently. The compiler will warn how bad an idea that is, subtle allocation errors can surface that become memory leaks at best or result in a crash or a vector for malware at worst.
On the other hand, that same heap allocated reference can be passed to a downstream targets, and its targets and so on. The key is to intelligently design your call graph. When you do it that way, you not only gain efficient use of resource but efficient management of object lifetimes.
Caller allocates and caller reclaims from a root local scope. Applied consistently and with unwavering adherence, code writing productivity improves and code revision errors can decrease. Languages like Java and C# don’t require this but applying this approach makes identifying resource usage more exact and potentially easier to maintain even in those languages.
Google Go is Local Only
Section 11 of the document, Go at Google: Language Design in Service of Software Engineering, shows that Go applies the local only concept rigorously. It is shown that a compact hierarchy results and that speeds up the ability to compile code, change code, and put new updates into production more quickly. You could probably reason about code more easily. I say could because none of the large code bases I created in the past (100,000+ LOC) ever applied this concept but more recent code that I have created is much closer to this concept in form. I can say that while I like the flexibility you have in deviating from a local only approach, the local only approach does have the benefits the author of the cited document asserts.
Passing Your Scope Seems the Right Choice
I cannot say it is 100% the right approach. Other experts with 30 years more experience than I either implicitly or explicitly emphasize this approach. The only thing I am doing here is giving it the name, Passing Your Scope. I call it that because part of your definition of code involves the scope at which data and functions become available and that matters in terms of how you apply those things. My experience, at times grudgingly, has evolved to show that observing this concept leads to less complication in the production of software that is fast and reliable.