Making your iOS application easy to read with these simple steps.

Alex Pinhasov
iOS App Development

--

Good programmers are the ones who explain what they do in the most simple way they can. Even physicists explain wormholes with a piece of paper and a pencil pinned in it. What makes us different?.

I have always tried to write my code as simple and well read as I could, everything from picking the right name for a variable to using code conventions, but something was still missing, a way to understand the code without trying to understand the “how” I did it, but rather the outcome I was trying to achieve.

You might even say the ability to read the code as a story, rather than a bunch of code.

Let’s address 3 main topics:

The Problem

Reading other programmers code can be a real struggle. Without providing the proper context one can simply find him self lost in finding the meaning of a function or a property.

The Suggestion

From 1’s and 0’s to low-level code to elite languages, it is noticeable that code syntax becomes more and more user-friendly, thus inviting new programmers to the developer’s universe. As the syntax becomes clearer to read in plain English so should our code be, simple,to the point and self-explaining.

The Outcome

A well writing code that masks itself as a story making it easy to read and understand (even without context).

Naming functions

How to do it the right way:

When we write function we assume that the person reading the function has enough context to understand what we were trying to achieve. Naming our function in a vage meaning “handleRedView()” will raise many questions about what does “RedView” stands for? what is the main goal of this function?.

It seems that in some cases the function purpose is vague and too complicated to understand without providing context.

We can separate our function proposes into 4 categories:

1. Informer   functions
2. Management functions
3. Router functions
4. Execution functions

1. Informer function

Usually triggers router/management functions.

function examples:

Call back function, inform that something did/will happen and gives you the option to react.

Mostly used as delegate trigged actions, or notification handling functions .

2. Management function

Used to unite multiple function to achieve 1 higher purpose without dependency, all the code inside the block will execute.

Reading this function we have all the information we need, execute this functions when the car has started, at this point we don’t care “how” its done rather the “what” it does.

3. Router function

Used to unite multiple functions to achieve 1 higher purpose with some sort of dependency, the code will execute only when intended to.

Router function mostly points to execution functions but in some cases can include logic itself only if the code won’t exceed 1 line.

4. Execution function

The implementation of the function name.

The logic itself could potently be complicated to understand but we already declared what the function does in the name, the function turns exterior lights on, the function checks for burned bulbs, understanding this may ease locating bugs in the future, and make it easier to add logic to the function without changing it’s name.

Eventually, after implementing these ideas into your application you should have organized objects with informer, management and router functions in your class segment.

and all the execution/logic in the extension block in the same file.

The outcome would be a clean short class, readable and easily maintained.

* Remember functions should always be written by the single
responsibly principle.

Avoid using "and" in function name:
playAndMinimize()
loadAndPlay()
This bad practice breaks the single responsibility principle and makes you write code suitable for both situations.

Avoid playing guessing games when naming a function:
moveRedViewIfNeeded()
This example guarantees future programmers would have to dive inside the function only to understand what the trigger for moving the Red View, which by the way also ambiguous.

* and no layoutIfNeeded() is not the same thing, in this case we know that self should re-layout its view's when setNeedsLayout bool is true. This example is universal to swift programming language while your function will probably remain private to your application.

Bonus (food for thought)

The first thing that comes in mind when thinking about readable code is using code convention, they are well known and commonly used, but using them does not necessarily makes your code better, it will make it cross-application but less readable.

“is” prefix should be used for boolean variables and methods to explain that the returned value is of type Boolean. #CodingConventions

“if” statement always addresses boolean values, then why do we need to declare “is” in each boolean property? why did apple changed swift syntax from view.hidden ~> view.isHidden ? there’s only one answer I could think of…. because “if view.isHidden” feels natural.

Let’s try implementing “is” prefix by this laws:

  • If a boolean property/method of a class used on an instance of that class (public) then “is” prefix is justified.
  • If a boolean property used inside the class (private) then the prefix is redundant.
  • if a boolean property/method used privately and publicly then a computed propery should return the private property value.

We could have used private(set ) and still use it publicly but think about the side effect achieved here, we have implemented encapsulation.

Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties’ direct access to them.

https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)

You might be asking your self what about booleans that don’t address self directly, in this case, we should write that property name like so:

private var playerIsPlaying: Bool

private var gridConstraintIsEnabled()

“is” needs something to refer to: view.isHidden, “is” refer to view. In the example above we have done that same thing, playerIsPlaying, “is” refers to the player.

Remember: Developers usually read the code inside the function to try and understand its purpose long before they even bother on reading the declaration of properties.

/if playerIsPlaying { }/ opposing to /if isPlayerIsPlaying {}/

which of this options sound natural?, I’ll let you decide.

--

--