Making Your iOS Application Easy to Read With These Simple Steps.


Making Your iOS Application Easy to Read With These Simple Steps.

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 simply 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/herself 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-explanatory.

The Outcome

A well written 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 vague way “handleRedView()” will raise many questions about what “RedView” stands for? What is the main goal of this function?.

It seems that in some cases the function's 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:

1 delegate.dataHasUpdated()

2

3 func dataHasUpdated()

4 {

5 //Someone is informing you that something has happened

6 }

1 // Informer Functions

2 override func engineStarted()

3 {

4 super.engineStarted()

5 handleCarStarted()

6 }

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

Mostly used as delegate triggered 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.

1 // Management Function

2 func handleCarStarted()

3 {

4 turnLights(on: true)

5 turnAC(on: true

6 }

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.

1 // Router Function

2 private func turnLights(on shouldTurnLightsOn: Bool)

3 {

4 if shouldTurnLightsOn

5 {

6 turnExteriorLightsOn()

7 checkForBurnedBulbs()

8 }

9 else { turnExteriorLightsOff() }

10 // When an if statment has only 1 thing to execute i like to write it

11 // at the same line with the "if" "else" word, it makes reading your code more fluent.

12 }

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.

1 // Execution Function

2 private func turnExteriorLightsOn()

3 {

4 leftFrontLight .isOn = true

5 rightFrontLight .isOn = true

6 leftBackLight .isOn = true

7 rightBackLight .isOn = true

8 }

9 private func checkForBurnedBulbs()

10 {

11 for lightBulb in bulbs where !lightBulb.isUseable

12 {

13 Dashborad.display(errorType: .lights)

14 break

15 }

16 }

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.

1 class Car: Vehicle

2 {

3 // Informer Functions

4 override func engineStarted()

5 {

6 super.engineStarted()

7 handleCarStarted()

8 }

9 // Management Functions

10 private func handleCarStarted()

11 {

12 turnLights(on: true)

13 turnAC(on: true)

14 }

15 // Router Functions

16 private func turnLights(on shouldTurnLightsOn: Bool)

17 {

18 if shouldTurnLightsOn

19 {

20 turnExteriorLightsOn()

21 checkForBurnedBulbs()

22 }

23 else { turnExteriorLightsOff() }

24 // When an if statment has only 1 thing to execute i like to write it

25 // at the same line with the "if" "else" word, it makes reading your code more fluent.

26 }

27 private func handleTurnAC(on shouldTurnACOn: Bool)

28 {

29 if shouldTurnACOn

30 {

31 let tempeture = currentTemptureSelected()

32 let toggleFocus = currentACToggleFocus()

33 startAC(with: tempeture, aimedTo: toggleFocus)

34 }

35 else { turnACOff() }

36 }

37 }

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

1 class Car

2 {

3 // Execution Functions

4 private func turnExteriorLightsOn()

5 {

6 leftFrontLight .isOn = true

7 rightFrontLight.isOn = true

8 leftBackLight .isOn = true

9 rightBackLight .isOn = true

10 }

11

12 private func checkFormBurnedBulbs()

13 {

14 for lightBulb in bulbs where !lightBulb.isUseable

15 {

16 Dashboard.display(errorType: .lights)

17 break