Writing expressive, meaningful, and readable code in Swift 4

Let’s talk about creating understandable and maintainable code in Swift 4, code that can be easily read by other programmers, can be readily debugged, can be reused, and can be enhanced and extended in the future. We’re going to limit today’s discussion to: 1) how best to come up with good names for functions and how best to name their arguments, parameters, and argument labels, and 2) how to use meaningful and descriptive variable (var) names — and constant (let) and enumeration (enum) names, etc. The goal is to create code that reads as to close to English as possible.

You may believe that this topic is overly simplistic or pedantic, but sometimes it’s the “little things” in life that really matter — especially when you have applications that are made up of millions of lines of code, made up of “little things” like function definitions and function calls.

I’m not a purist who’s bought into the thinking that one can write code that is entirely “self-documenting.” I know from sheer experience that there’s almost always a need for inline code commentary as well as other forms of documentation (e.g., requirements analysis, algorithmic, design, etc.). Programmers who just bang on a keyboard without doing any type of design and planning; who write single functions that go on for four pages; who use variable names like “x,” “y, “z,” and “i;” who never write any inline comments; and who write phrases like “new code” when committing and pushing to their repos are just plain lazy. Their code is very difficult to read, let alone support or, G-d forbid, extend/enhance. I’m a computer scientist.

With all that being said, I do believe that I should still strive to write code that is readable on it’s own without supplementary documentation, fully well knowing there are times, like in a function that realizes a complex algorithm, when inline comments will be necessary.

Functions, functions everywhere
Apple Swift documentation contains a wonderful definition: “Functions are self-contained chunks of code that perform a specific task.” As developers, we spend much of our time writing code in functions — and rightfully so as we’re encoding tangible activities, algorithms if you will, in our space-time continuum.

Note: I’m not going belabor why you should use descriptive variable names. If the reason for doing so is not obvious to you, leave a comment. Hint: variable (var) names — and constant (let) and enumeration (enum) names, etc. — should read like English, too.

Before moving on, let’s agree on what the terms “function name,” “parameter” and “argument” mean because these are a constant source of confusion, especially the later two. Here’s Apple definition, and let’s use that definition throughout this article:

Every function has a function name, which describes the task that the function performs. To use a function, you “call” that function with its name and pass it input values (known as arguments) that match the types of the function’s parameters. A function’s arguments must always be provided in the same order as the function’s parameter list.

I’m going to use real Swift language code, code that can be compiled, to reinforce the meaning of the terms “parameter” and “argument” (and “argument label”). Try this code yourself in an Xcode project or playground.

Swift functions have this structure — and don’t you fret about those danged-ed underscore characters (_) right now; we’ll get to those later:

The gist of Apple’s quote and my code is this: Parameters are placeholders for the values that you pass to your function. Parameters also show how, in the function body, again as placeholders, that the values they represent will be used in the algorithm that your function materializes. Arguments are the actual values, or contain the actual values, that will be substituted into your function parameters when calling your function. Above, for example, the arguments 2 (argument1) and 2 (argument2) will be substituted into — passed into — functionName’s parameter1 and parameter2.

Again, I know this sounds pedantic, but to be the best of the best, you truly need to understand what’s going on in your Swift code. Let me show you some more real Swift code, which you can compile and try, to solidify the “parameter” and “argument” concepts. I’m also introducing you to the “argument label” concept while simultaneously reinforcing the basic Swift function structure:

For me, one of the most important Swift 4 features is “The use of argument labels [which] can allow a function to be called in an expressive, sentence-like manner, while still providing a function body that is readable and clear in intent.”

Functions from the prehistoric to Swift
For those of you who’ve been around for awhile, you’re probably used to seeing function calls like this C language example:

C is still very useful, even essential sometimes, but in terms of expressivity, ah, it’s OK.

While Swift allows us to write bare-bones, C-like code, it encourages us to write more readable, expressive, meaningful, and maintainable code. Let’s start with what Swift permits in terms of a minimal function definition:

Notice what Xcode’s auto-complete shows me when writing a call to the “multiplyTwoIntegers” function:

Notice that, compared to C, Swift spurs me to make my call to the “multiplyTwoIntegers” function more expressive by encouraging me to label my parameters. If I try to call “multiplyTwoIntegers” without parameter labels, the Xcode IDE warns me in the editor…

… and warns me at the console:

I have to specifically tell Swift to drop the requirement for parameter labels, or rather “argument labels.” To hide argument labels, I use the underscore (_) character which suppresses them:

Notice what Xcode’s auto-complete shows me when writing a call to the “multiplyTwoIntegers1” function:

Watch what the Xcode IDE shows me if I try to use parameter labels…

… and what the Xcode console reports:

Getting expressive with Swift
I created a class that allows you to experiment with writing expressive and readable function and variable names, fully recognizing that beauty is in the eye of the beholder. There’s no perfectly “right answer.” There is a strongly creative aspect to software development and the decision as to what constitutes “more readable” code needs to be made based on common sense, taking into account subjective as well as objective criteria.

(Note that I’ve introduced the Swift 4.0.3 concept of a “string that spans several lines… a multiline string literal.”)

Here is some code representing ideas for Swift code readability with which you can review and experiment:

Console output from the code shown above:

Documenting Swift functions
When discussing our Swift code in written format, say in emails between developers or in formal design and/or code documentation, there are some conventions to follow. For this function:

we would write multiplyTwoIntegers1(_:_:).

For this function:

we would write multiplyTwoIntegers(first:second:).

For a function signature with mixed arguments, like Apple’s

where we’re omitting the first argument’s label but providing a label for the second parameter, we would refer to this function as collectionView(_:shouldHighlightItemAt:).

What the future holds
So we’ve explored Swift’s expressiveness to achieve the lofty goal of writing code that can be read without supplementary comments. We’ll, er, ah, work on that one. As I said, give me a call when you can maintain or enhance projects with hundreds of thousands of lines of code with no supplementary documentation, whether code comments or meta-documents. We are an evolving species (hopefully). What’s coming down the pike years ahead?

We’ve seen it or read about out it in science fiction: computers that can fully understand the syntax, semantics, grammar — all the subtle context and nuances of human language. How many of you have watched, for example, Star Trek, and seen a character like Geordi create a simulation to solve a problem? See the YouTube clip below. He actually creates software-based simulations within the holodeck, itself a simulation. Geordi creates programming logic just by talking. And he falls in love with a simulation of a “real-life” engineer, Dr. Leah Brahms. Hey… whatever cranks your gears…

And all we’re trying to do in this article is write code that reads like English. Software that can understand human language and turn it into code? That time is not now. We are working towards that lofty goal, but technology keeps getting more and more complex, and for the foreseeable future, we’re going to need people who understand how to solve problems by creating software solutions. Don’t worry about your jobs just yet.

Wrapping up
I hope you enjoyed today’s discussion. Remember that our goal is to create code that reads as to close to English as possible.

Author: Andrew Jaffee

Avid and well-published author, software engineer, designer, and developer, now specializing in iOS mobile app development in Objective-C and Swift, but with a strong background in C#, C++, .NET, JavaScript, HTML, CSS, jQuery, SQL Server, MySQL, Oracle, Agile, Test Driven Development, Git, Continuous Integration, Responsive Web Design, blah, blah, blah ... Did I miss any fad-based catch phrases? My brain avatar was kindly provided by http://icons8.com under a Creative Commons Attribution-NoDerivs 3.0 Unported license.

Leave a Reply

Your email address will not be published. Required fields are marked *