Swift – swifting.io http://swifting.io Sharing passion in Swift Sun, 09 Sep 2018 09:07:59 +0000 en hourly 1 https://wordpress.org/?v=5.2.2 http://swifting.io/wp-content/uploads/2016/10/swift_4_ptak_40px-1.png Swift – swifting.io http://swifting.io 32 32 #45 Can you sing well? http://swifting.io/blog/2017/08/07/45-can-you-sing-well/ http://swifting.io/blog/2017/08/07/45-can-you-sing-well/#comments Mon, 07 Aug 2017 21:57:51 +0000 http://swifting.io/?p=964 Remark

After reading this post you will find out if you can sing or not. If you want to stay not aware about it please don’t read this post further.

Story

I’m passionate about music. I have played violin for 3 years. One year ago I bought a digital piano to make first steps as a composer. Also I’m very interested in human voice, especially because I have always wondered: how it is that some people can sing and some can’t?

My girlfriend is a professional musician and she have played violin since her childhood. People who are experts in this business have developed their hearing to master level. They can say without any problem if you can sing very well or very badly. If you have never been involved in playing instruments or singing, it can be probably very hard for you to say that someone sings in tune or not.

One day my girlfriend and I were traveling by car (I have to say that I love singing while driving:P)

And after a while she said, Bartek… hmmm, it’s not good…

Her comment made me think: even though I have some music experience it’s not easy for me to be aware of my singing and I totally don’t know if I sing in tune or not. This day when I came back to home I started thinking: hmmm… it would be great to create some mobile app for checking if you can sing. Maybe it would be great to install this application before you decide to go to some voice talent show 😛

How to test your sing abilities?

I have never been in a music school and that’s why I used to wonder how teachers check kids vocal predispositions?

Algorithm steps are the following:

1) Teacher plays few sounds on a piano, by pressing single keys.

2) Then a student has to sing the sound in the same order by singing syllable (for examle ‘la’) on each note.

3) Teacher hears and says if sounds are correct.

So generally the best way to check if you can sing is just to ask an expert about that. But what if you don’t have an expert in your neighborhood, or you are too shy to ask someone? What then? That’s why I started to thinking about a mobile app solution to solve those problems 🙂

Idea

The idea is to create an iOS application available on the AppStore which can tell you if you have predisposition to sing or not. But even if you were not born as the Michael Jackson the application would show you your mistakes and in that way you can become more aware about your voice.

Some background

If you are familiar with music theory and you are only interested in technical issues: please go directly to the chapter iOS Application. But if you aren’t, I have prepared for you a few chapters which will be helpful to understand the way how application works.

Note

A note is a sign used in musical notation to represent the relative duration and pitch of a sound (♪, ♫). The pitch of the note means how high or low a note is (pitch is described by frequency in Hz). Below some examples:

Octave and music scales

Octave is an interval between one musical pitch and another with half or double its frequency. For example, if one note has a frequency of 440 Hz, the note one octave above is at 880 Hz.

Music scales, are typically written using eight notes which represent an array of pitches. The interval between the first and the last note is an octave. Below is an example of C scale:

C D E F G A H C
16.35 Hz 18.35 Hz 20.60 Hz 21.83 Hz 24.50 Hz 27.50 Hz 30.87 Hz 32.70 Hz

Second C in the array starts a new octave with the same note names but with doubled frequencies:

C D E F G A H C
32.70 Hz 36.71 Hz 41.20 Hz 43.65 Hz 49.00 Hz 55.00 Hz 61.74 Hz 65.41 Hz

and so on and so on….

How many octaves exist?

We humans can hear sounds from 20 to 20 000 Hz, so there in no sense for us to care about octaves beyond this range. Below you can find examples of 9 next octaves:

Octaves

Octave C D E F G A H C
0 16.35 Hz 18.35 Hz 20.60 Hz 21.83 Hz 24.50 Hz 27.50 Hz 30.87 Hz 32.70 Hz
1 32.70 Hz 36.71 Hz 41.20 Hz 43.65 Hz 49.00 Hz 55.00 Hz 61.74 Hz 65.41 Hz
2 65.41 Hz 73.42 Hz 82.41 Hz 87.31 Hz 98.00 Hz 110.0 Hz 123.5 Hz 130.8 Hz
3 130.8 Hz 146.8 Hz 164.8 Hz 174.6 Hz 196.0 Hz 220.0 Hz 246.9 Hz 261.6 Hz
4 261.6 Hz 293.7 Hz 329.6 Hz 349.2 Hz 392.0 Hz 440.0 Hz 493.9 Hz 523.3 Hz
5 523.3 Hz 587.3 Hz 659.3 Hz 698.5 Hz 784.0 Hz 880.0 Hz 987.8 Hz 1047 Hz
6 1047 Hz 1175 Hz 1319 Hz 1397 Hz 1568 Hz 1760 Hz 1976 Hz 2093 Hz
7 2093 Hz 2349 Hz 2637 Hz 2794 Hz 3136 Hz 3520 Hz 3951 Hz 4186 Hz
8 4186 Hz 4699 Hz 5274 Hz 5588 Hz 6272 Hz 7040 Hz 7902 Hz 8372 Hz
Frequency range of voices and instruments

Vocal range is a measure of the breadth of pitches that a human voice can phonate. For an untrained voice range is between 1.5 – 2 octaves. For a trained voice it’s about 2.5 – 3 octaves. Let’s look on vocal ranges of famous sing stars:

  • Axl Rose: 5 octaves range
  • Dawid Bowie: 4 octaves range
  • Bob Marley: 3 octaves range

to see more visit this website. On the other hand … what with instruments? Instruments have generally a defined range:

  • piano: 7 ¼ octave range
  • violin: more than 4 octaves
  • guitar: 4 octaves

You can find more examples here.

Men vs women

Voices of women are divided into 3 categories:

  • alto (about F3-A5): is the lowest female voice type
  • soprano (about A3-C6): is the highest female voice type.
  • mezzo-soprano (G3 – A5): in between, is a type of classical female singing voice

Note: F3 meaning: F represents note and 3 says from which octave the note is. Knowing that and looking at the Octaves table we know that the frequency of this sound is 174.6 Hz.

Among men, the broad categories are:

  • bass (about E2-F4): is the lowest male voice type and thus a bass voice type sings the lowest notes possible for a human.
  • baritone (about G2-A4): is the most common male voice type
  • and tenor (about B2-C5): is the highest male voice type you will find in a typical choir

As we see men and women have different range of octave, generally women sing higher than men (more or less one octave).

Great image to show differences between voices:

Image is baaed on the source: https://www.becomesingers.com/wp-content/uploads/2013/03/Vocal-Range-Classification.jpg

Childs scale

Childrens voices from approximately 7 years of age can be classified in the same way as female voices: into altos and sopranos.

Vocal range is not everything…

Why do I prefer to listen Frank Sinatra than Freddie Mercury?

Of course our voice is described by more than only one parameter such as:

  • vocal weight,
  • vocal registration,
  • scientific testing,
  • speech level,
  • physical characteristics,
  • vocal transition,
  • vocal timbre,
  • and vocal tessitura.

A combination of all those factors is utilized to determine a singer’s voice, and categorize it into a specific type of voice type.

iOS Application

Inspiration

Have you ever played a SingStar game on a PlayStation? I haven’t, but I saw on YouTube how people play:

SingStar requires players to sing along with music in order to score points. The game analyzes a player’s pitch and timing which is compared to the original track, with players scoring points based on how accurate their singing is.

Goal

Main goal of my application is to give easy access to everyone to test their sing abilities. Especially for those who don’t have music background.

How application works?

Application compares frequency of a voice wiath a pitch frequency defined in a sing test and then it visualizes the difference between them. Let’s look step by step on application flow to understand it better.

1. The first thing is to choose a test from the list:

2. After choosing an item from the list application plays the sing test:

Each bar represents a note. The highrer the note is the higher a bar is located.

3. Then by clicking the next button a timer gets started to count 3 seconds. It’s a time for preparation:

4. After that time you should start singing. There is no matter what text you sing, you can help yourself with singing syllable ‘la’ on each note.

If you sing properly application shows that you are on track:

If you sing too high the application shows that your voice is upper the right tune:

When you sing too low, then samples appear below the right tune:

Whole application flow below:

App Architecture

The application is based on two libraries:

ResearchKit

ResearchKit is an open source framework introduced by Apple that allows researchers and developers to create powerful apps for medical research. You can easily create visual consent flows, real-time dynamic active tasks.

In my case ResearchKit gave me for free an easy interface for supporting application which is based on steps.

AudioKit

AudioKit is an audio synthesis, processing, and analysis platform for iOS, macOS, and tvOS.

This framework gave me great tools for analyzing pitches from device microphone.

Project Source

You can download the whole project from here and test it by yourself. I will appreciate any comment ([email protected]) for this project or any pull request which could develop this application.

What’s next ?

My goal is to develop current application and make it available to everyone via AppStore and maybe also someday on Google Play:)

Resources

Great website about vocal ranges

AudioKit example application for microphone analysis

AudioKit Library

Pitchy library which provides a simple way to get a music pitch from a frequency

Accessing heart rate data ResearchKit study

]]>
http://swifting.io/blog/2017/08/07/45-can-you-sing-well/feed/ 2
# 40 How to swiftly dequeue a cell? http://swifting.io/blog/2017/04/19/40-how-to-swiftly-dequeue-a-cell/ http://swifting.io/blog/2017/04/19/40-how-to-swiftly-dequeue-a-cell/#comments Wed, 19 Apr 2017 09:04:07 +0000 http://swifting.io/?p=920 The UITableView and UICollectionView classes serve table-like and matrix-like layout for content to be displayed on screen. Both components display their data in corresponding UITableViewCell and UICollectionViewCell subclasses. Both components contain mechanisms for reusing a cell, that was initialised earlier and is not visible on the screen, e.g. when user scrolled the content. You can find a nice description and visualisations on that subject here.

Reusing a UITableViewCell – an old way

In order to reuse a cell in a tableView, the cell has to be registered for reuse with an identifier. Usually it is done at the time you configure your views, e.g. in viewDidLoad.

lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain)

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
}

To reuse a cell it has to be dequeued from a tableView. Dequeueing is done by dequeueReusableCell(withIdentifier:for:) method. It dequeues a cell or initialises a new one if none is queued for reuse.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
    as? MyCell else { return UITableViewCell() }
    //Configure cell
}

Have you noticed the "MyCell" duplicated in viewDidLoad and tableView(cellForRowAt:)? It felt ugly to me so I have decided to refactor that code, when I repeated it in a few view controllers.

I refactored the code so that a cell I registered for reuse from a stored cellClass and a computed property cellIdentifier.

let cellClass: AnyClass = MyCell.self
var cellIdentifier: String { return String(describing: cellClass) }

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(self.cellClass, forCellReuseIdentifier: self.cellIdentifier)
}

Actually, this approach is kinda nice if we have a few cells to be registered for reuse. We can do some functional magic 🔮, like this:

let cellClasses: [AnyClass] = [MyCell.self, MyOtherCell.self, UITableViewCell.self]
var cellIdentifiers: [String] { return cellClasses.map{ String(describing: $0) } }

override func viewDidLoad() {
    super.viewDidLoad()
    let reuse = zip(cellClasses, cellIdentifiers)
    for (cell, cellIdentifier) in reuse {
        tableView.register(cell, forCellReuseIdentifier: cellIdentifier)
    }
}

The cellIdentifier property is of course used in tableView(cellForRowAt:). What I still don’t like in this code is that I still have to cast the reused cell to an appropriate type, even though I stored a cellClass 😭.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
    as? MyCell else { return UITableViewCell() }
    //Configure cell
}

Finally, my colleague Alek has invented a great solution to my problem!

Extending UITableViewCell

First of all, it is a tedious work to write cellIdentifier property in every view controller. Why not to extend the UITableViewCell?

public extension UITableViewCell {
    public static var identifier: String { return String(describing: self) }
}

Then we can further extend a UITableView with a new version of register method to make use of identifier property on a UITableViewCell.

public extension UITableView {
    public func register(_ cell: UITableViewCell.Type) {
        register(cell, forCellReuseIdentifier: cell.identifier)
    }

But the most beautiful magic 🔮 happens when we extend UITableView with new version of dequeueReusableCell(...) method! It uses generics, takes as an argument a class of a cell, an indexPath and a configure closure to which a cell of desired type (i.e. of CellClass.Type) is passed. No more guard and casting in tableView(cellForRowAt:)! Yuppii 😊!

public func dequeueReusableCell(of
        class: CellClass.Type,
        for indexPath: IndexPath,
        configure: ((CellClass) -> Void) = { _ in }) -> UITableViewCell {
            let cell = dequeueReusableCell(withIdentifier: CellClass.identifier, for: indexPath)

            if let typedCell = cell as? CellClass {
                configure(typedCell)
            }
            
        return cell
    }
}

So now we can easily dequeue a cell of an appropriate type! How neat is that 😀 !?

let cellClass = MyCell.self
//... register a cell for reuse
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return tableView.dequeueReusableCell(of: cellClass, for: IndexPath(row: 0, section: 0)) { cell in
        cell.textLabel?.text = indexPath.description
    }
}

Wrap up

The presented approach simplifies cell registration for reuse and allows to avoid guard-cell-casting. The same approach can be used for UICollectionView.

What you cannot do with the presented solution is taking cellClass from an array, because a compiler doesn’t know type at compile time.


class TableViewDataSource: NSObject, UITableViewDataSource {
    let cellClasses: [AnyClass] = [MyCell.self, UITableViewCell.self]
    func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(of: cellClasses[indexPath.section], for: indexPath) { cell in
        //ERROR: Cannot convert value of type '()?' to closure result type 'Void' (aka '()')
            cell.textLabel?.text = indexPath.description
        }
    }
}

What you can do with that is of course using a switch statement, e.g. over section, to infer a cell type.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
        case 0:
            return tableView.dequeueReusableCell(of: MyCell.self, for: indexPath) { cell in
                cell.textLabel?.text = indexPath.description
      }
        default:
            return tableView.dequeueReusableCell(of: UITableViewCell.self, for: indexPath) { cell in
                cell.textLabel?.text = indexPath.description
            }
    }
}

You can play with the solution by downloading our playgrounds or by grabbing gists from links section.

Links

]]>
http://swifting.io/blog/2017/04/19/40-how-to-swiftly-dequeue-a-cell/feed/ 2
#36 ObjectiveC2Swift Review http://swifting.io/blog/2017/02/14/36-objectivec2swift-review/ http://swifting.io/blog/2017/02/14/36-objectivec2swift-review/#comments Tue, 14 Feb 2017 22:24:51 +0000 http://swifting.io/?p=866 Today we will dive deeper into a quite unusual topic for us – Objective-C. Don’t be scared though as what we have got for you is a review of Objective-C to Swift tool.

Full disclaimer: we have recently received a full access to the tool from ObjectiveC2Swift Team! Thanks!

Challenge Accepted!

Tweet

We all have some big and small legacy projects written in Objective-C, who doesn’t right? That’s why we have felt obliged to try this tool out and share with community how it worked for us.

All that being said I will stay as objective as possible when reviewing the tool in this subjective post. All the good things mentioned in this article are an appraisal to the team for their great job. All bad things are tips to help developers and for the Swiftify Team to make their product even better!

Hang on! Let’s rock!

How to do it?

It’s an online tool. No need to install anything. Code is transmitted securely and is not stored anywhere. Free tier enables you to convert pieces of code up to 2KB. Then there are paid versions that allow you convert whole files and even entire projects. There is also an Xcode plugin. Everything is neat and self- explanatory. No need for any long tutorials.

Converter

Playground

To make a full use of the license we have received, we have converted an entire project. This is a simple demo app to display the Game of Thrones (referred as GoT) data from Wikia’s API. It has some networking, a model and Masonry (a layout DSL, link in references) as Pod. As an additional difficulty it was a piece of code that I have never seen before. The app is small but uses some very specific patterns like Configurator, Loaders and blocks. Seems just enough to test.

NOTE: Objective-C2Swift converter does not promise a perfect conversion. There is a list of supported Swift and Objective-C features on their page.

Process

I have followed this process to test the tool:

  1. Zip Objective-C project
  2. Convert using Swiftify tool
  3. Unzip converted Swift project
  4. Fix it until it builds
  5. Run it
  6. Fix it until it works
  7. Run it
  8. Blog about it 😉

As a result we have a GitHub repository with 3 folders. One with the original Objective-C project, another one with converted project and last one with fixes. You can find a link in references.

Results

My first impression after unzipping converted project was:

Wow, it looks like a perfect Swift Code.

And it quite is one.

Let’s build it!

Ok… 12 errors, not bad. Let’s see what impressed me most and what could be done better.

The good
1. It can get an entire file right

The first file that looked into in the converted project was AppDelegate.swift. It was converted 100% correctly. We can probably expect that for simple and small files. You may notice now, that good architecture and KISS pays off.

Good start.

// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
...
2. It gets nullability annotations right

The original GoT Objective-C code was using nullability to support Swift interoperability. It is good to know that our tool converts nullable attributed properties to Swift optionals.

// Article.h
@property(nonatomic, strong, nullable) NSData *thumbnailData;
- (nullable UIImage *)imageFromThumbnailData;
// Article.swift
var thumbnailData: Data?
func imageFromThumbnailData() -> UIImage?
3. It handles private (set) well

I would give another plus for translating readonly property attribute into private (set) var.

In the example below, we get both optional and private setter right.

// AsyncLoadConfiguration.h
@property(nonatomic, readonly, nullable) NSString *webserviceQuery;
// AsyncLoadConfiguration.swift
private(set) var webserviceQuery: String?

I was wondering for a while if having let would be a better option here, but quickly reminded myself that there is no such thing as Objective-C const properties . Converter works well enough with Objective-C consts:

// Objective-C const
NSString *const MyFirstConstant = @"FirstConstant";

// Swift const
let MyFirstConstant: String = "FirstConstant"
4. Global vars

As ugly using global vars are, they were converted properly!

// Article.m
static NSString *kArticleIdentifier = @"privateIdentifier";
static NSString *kArticleTitle = @"privateTitle";
// Article.swift
var kArticleIdentifier: String = "privateIdentifier"
var kArticleTitle: String = "privateTitle"
5. Initializers converted to Swifty syntax

It is good to see nice separation of parameters in init functions created from Objective-C initWithXYZ format.

// Article.m
- (nonnull instancetype)initWithArticle:(nonnull Article *)article
                              favourite:(BOOL)favourite {
// Article.swift
init(article: Article, favourite: Bool)
6. Makes typealiases from typedef

Might seem pretty straightforward but it is nice to see attention to such details.

// DataSource.h
typedef void (^CellConfigureBlock)(UITableViewCell *_Nonnull cell,
                                   NSIndexPath *_Nonnull indexPath,
                                   id _Nonnull item);
// DataSource.swift
typealias CellConfigureBlock = (_ cell: UITableViewCell, _ indexPath: IndexPath, _ item: Any) -> Void
7. GCD

Although GCD is a framework not a part of Swift language it was converted properly.

// DataSource.m
dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData];
        });
// DataSource.swift
 DispatchQueue.main.async(execute: {() -> Void in
                self.tableView.reloadData()
            })
8. Pods were untouched

I have uploaded the zipped GoT project including fetched Pods directory. Luckily it was not touched at all and left in its Objective-C form.

9. Awkward calls to Masonry library were almost perfectly transformed

The GoT project uses Masonry for autolayout purposes. Even in Objective-C Masonry calls felt weird. Having Masonry in Swift project (while SnapKit is available) is even weirder. To make fixes I had to take a look at sample repository Swift-Masonry to make it work.
Kudos for converter for taking it that far!

// DetailsViewController.m
        [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.equalTo(self.imageView.superview);
            make.top.equalTo(self.imageView.superview).offset(10);
            make.width.height.equalTo(@100);
        }];
// DetailsViewController.swift
        self.imageView?.mas_makeConstraints({(_ make: MASConstraintMaker) -> Void in
            make.centerX.equalTo(self.imageView?.superview)
            make.top.equalTo(self.imageView?.superview?)?.offset(10)
            make.width.height.equalTo(100)
        })
// DetailsViewController.swift - after fixes
_ = self.imageView?.mas_makeConstraints({(make: MASConstraintMaker?) -> Void in
            _ = make?.centerX.equalTo()(self.imageView?.superview)
            _ = make?.top.equalTo()(self.imageView?.superview)?.offset()(10)
            _ = make?.width.height().equalTo()(100)
        })
10. Deals very well with simple files of moderate size

This one is to echo the AppDelegate one. Custom FavouriteTableViewCell was almost perfectly converted (apart from crazy Masonry stuff and dispatch_once). This file is larger (100 lines) than AppDelegate and still converted nicely.

11. Do-catch, try support

Do-catch error handling is supported. Some APIs became throwing APIs in Swift and converter wraps it in do-catch, try statement. On the little con side it rendered one these for me in an incomplete state.
It’s probably too much to ask, so just note what may happen:

// Data+JSON.m
- (id)JSONObject {
    return [NSJSONSerialization JSONObjectWithData:self
                                           options:NSJSONReadingAllowFragments
                                             error:nil];
}

In swift JSONSerialization is a throwing API. It was wrapped in this way.

func jsonObject() -> Any {
        do {
            return try JSONSerialization.jsonObject(withData: self, options: NSJSONReadingAllowFragments)!
        }
        catch {
        }
    }

All in all, this went into positive side.

The could be better

Now let’s see what may go wrong. It is not written to condemn creators of this awesome tool. Treat it as tips.

Update 24/03/2017: Look into comments. Swiftify team was working hard to address issues mentioned below.

1. An entire method may disappear

This goes as number one as I was not expecting that when converter trips over at one of early lines it may swallow the entire method. 41 lines of code were turned into merely 3 and the rest was thrown outside of class scope in broken pieces:

// MainViewController.m
- (void)loadTableView {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        self.tableView = [[UITableView alloc] initWithFrame:CGRectZero
                                                      style:UITableViewStylePlain];
        self.tableView.dataSource = self.dataSource;
        self.tableView.delegate = self;
        [self.tableView registerClass:[FavouriteTableViewCell class]
               forCellReuseIdentifier:self.dataSource.cellReuseIdentifier];
        [self.view addSubview:self.tableView];
...
// 40 lines in total
// MainViewController.swift

    func loadTableView() {
        var onceToken: dispatch_once_t
        dispatch_once
        onceToken
    }
2. This nasty ‘abstract’ word

Somehow the word ‘abstract’ that was used throughout the GoT project as a variable name (property in model) or an initializer parameter caused many troubles to the converter. Funny enough neither Objective-C nor Swift have ‘abstract’ keyword.
Could be some internal implementation detail.

// Article.h
@property(nonatomic, readonly, nonnull) NSString *abstract;
- (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier
                                     title:(nonnull NSString *)title
                                  abstract:(nonnull NSString *)abstract
                                 urlString:(nonnull NSString *)urlString
                        thumbnailURLString:(nonnull NSString *)thumbnailURLString;
// Article.swift
private(set) var: String = "" // this is in place of property
...


override init(identifier: String, title: String, urlString: String, urlString: String, thumbnailURLString: String) // look at doubled urlString param
 
...
override func abstract() -> String { // this is added somewhere in code
        return self.privateAbstract
    }
3. Long inits with blocks not translated correctly

Another problem occurred with long init with block parameter. This piece of code gave a really hard time to the converter. Take a look at it:

// AsyncLoadConfiguration.m
- (nonnull instancetype)
initWithResponseParsingBlock:
(nonnull id _Nullable (^)(NSData *_Nonnull result))block
webserviceEndpoint:(nonnull NSString *)endpoint
webserviceQuery:(nullable NSString *)query  {
   self = [super init];
    if (self) {
        self.parsingBlock = block;
        self.endpoint = endpoint;
        self.query = query;
    }
    return self;
}
// AsyncLoadConfiguration.swift
override init(responseParsingBlock Nullable: Any) {
        block
                (endpoint as? String)
                (query as? String)
        do {
            super.init()
            
            self.parsingBlock = block
            self.endpoint = endpoint
            self.query = query
        
        }
        var: ((_ Nonnul: Data) -> Any)?
        responseParsingBlock
        do {
            return self.parsingBlock
        }
...

When trying to reproduce this in the Swiftify web tool I have found that there is a tiny console that shows all lexer, parser and converter messages. In the case of our unfortunate and weird initializer, it showed:

Lexer and Parser messages:
(unknown): (3:12) Missing RP at '_Nullable'
(unknown): (3:50) Mismatched input ')'
(unknown): (13:1) Missing '}' at 'EOF'

Converter messages:
(unknown): (3:51) Unable to convert: 
(unknown): (13:0) Unable to convert: 
4. Problems when calling complex inits with blocks

This point is related to previous one. Trying to call such a complex initializer resulted in similarly broken code.

5. Unnecessary overrides

In many places throughout the code there were unnecessary override keywords.

// DataSource.m
- (nonnull instancetype)
initWithCellConfigureBlock:(nullable CellConfigureBlock)configureBlock
cellReuseIdentifier:(nonnull NSString *)reuseIdentifier


- (void)addItems:(nonnull NSArray *)items

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
// DataSource.swift

override init(cellConfigureBlock configureBlock: CellConfigureBlock?, cellReuseIdentifier reuseIdentifier: String)

override func addItems(_ items: [Any])

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
6. Propagates self to method calls

While this is a safe option it is usually completely unnecessary and redundant piece. Still, better working code than optimized and broken.

// ArticleRepository.m
- (void)saveFavouriteArticle:(nonnull Article *)article {
    [self.articles addObject:article];
    [self saveFavouriteArticlesToDefaults];
}
// ArticleRepository.swift
func saveFavouriteArticle(_ article: Article) {
        self.articles.append(article)
        self.saveFavouriteArticlesToDefaults()
    }
7. Nil comparisons

Some Objective-C patterns are sometimes not converted properly to Swift. That’s not a big deal though. Take a look at nil comparison:

// ArticlesRepository.m
if (!set) {
        set = [[NSMutableSet alloc] init];
    }
// ArticlesRepository.swift
 if set.isEmpty {
            set = Set()
        }
  • To be fair it works in simpler cases:
// Objective-C
if (item) {
    self.cellConfigureBlock(cell, indexPath, item);
}
// Swift
if item != nil {
      self.cellConfigureBlock(cell, indexPath, item)
}
9. Problematic dispatch_once calls

I do not know why, but I was expecting to have it converted when I saw GCD converted properly. The dispatch_once calls have no equivalent in Swift and should be rewritten into some form of lazy vars:

DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")

The converter took no attempt to translate this call:

+ (UIImage *)avatarImage {
    static UIImage *avatarImage;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        avatarImage = [UIImage imageNamed:@"avatar"];
    });
    return avatarImage;
}
class func avatarImage() -> UIImage {
        var avatarImage: UIImage?
        var onceToken: dispatch_once_t
        dispatch_once(onceToken, {() -> Void in
            avatarImage = UIImage(named: "avatar")
        })
        return avatarImage!
    }
10. Some changes in APIs are not picked yet.

Swift 3 imposes new style of writing. It affected many APIs and made them shorter. I have noticed that converter is not picking that up.

// DetailsViewController.m
self.abstractTextView.editable = NO;
// DetailsViewController.swift
// Should be 'isEditable'
 self.abstractTextView.editable = false
// Article.m
   [aCoder encodeObject:self.privateIdentifier forKey:kArticleIdentifier];
// Article.swift
// Should be just 'encode'
aCoder.encodeObject(self.privateIdentifier, forKey: kArticleIdentifier)

While looking into code we could probably find some more tiny wins and losses. But this trip was long already!

Process Step no 6: Fix it until it works

At this point of my process I was mostly working on strong typing of Set‘s and Array‘s so that everything was more type-safe and Swifty. Other tasks included handling optionals with guard let‘s and similar. It really didn’t take too much time until app was building and running correctly. Neat!

One last shot

As you may notice project had properties and parameters marked with nullable and nonnull attributes that are there to help conversion to Swift optionals.

There is one more feature introduced in Xcode7 that I wanted to give a try and that was not in our sample project: Objective-C Lightweight Generics.

Let’s jump directly into Objective-C code and code converted using online tool:

@property NSArray *dates;

@property NSCache> *cachedData;

@property NSDictionary > *supportedLocales;
var dates = [Date]()

var cachedData: NSCache!

var supportedLocales = [String: [NSLocale]]()

Looks good to me. Good job Swiftify!

Summary

All in all I am very impressed with the results I was able to achieve using Swiftify to convert the entire project. There are few flaws but most of them are minor. They are picked by compiler and can be self-corrected quickly.

Clearly the fact that the project is building does not mean you are at home. There is still a high probability of runtime errors as the languages are very different. It is necessary to stay focused and analyze the results but all the tedious work and hours of typing are done for you! Now I just wonder whether unit tests could help in this converted project.

I have to admit that this project has a lot of unusual solutions. But only in this way we could get to the limits of the tool and give you some valuable tips and feedback.

Update 09/09/2018

It’s been more than a year since this review was created. If you are interested in converting Objective-C codebases into Swift you can follow up with this article from Swiftify.

References

]]>
http://swifting.io/blog/2017/02/14/36-objectivec2swift-review/feed/ 5
#26 SwiftLint, SonarQube and CheckMarx… what else? http://swifting.io/blog/2016/10/25/26-swiftlint-sonarqube-and-checkmarx-what-else/ http://swifting.io/blog/2016/10/25/26-swiftlint-sonarqube-and-checkmarx-what-else/#comments Tue, 25 Oct 2016 08:45:13 +0000 http://swifting.io/?p=602 Today we would like to talk about news from SwiftLint and also look at different static analyzers frameworks like:

  • SonarQube
  • Checkmarx

Concentrating on some basics, best practices, tips and just personal feelings about each one.

Important: if you would like to learn more about SwiftLint I recommend visiting our previos post about SwiftLint.

Ready?


Let’s start!

SwiftLint

A tool to enforce Swift style and conventions, loosely based on GitHub’s Swift Style Guide.

Basics
  • Current version: 0.12
  • 38 rules available here
  • It’s free
  • Developed and supported by Realm
  • 76 Contributors
What’s new in 0.12 version?

New version has a few new rules, options and fixes. For example:

  • MARK Rule – MARK comment should be in valid format (to enforce //MARK: syntax):

  • Private Outlet Rule – IBOutlets should be private to avoid leaking UIKit to higher layers:

  • Vertical Whitespace Rule: Limit vertical whitespace to a single empty line:

  • Private Unit Test Rule: Unit tests marked private are silently skipped:

  • Legacy NSGeometry Functions Rule – Struct extension properties and methods are preferred over legacy functions (available for SDK: macOS 10.10+)

  • New junit report option:

swiftlint lint --report junit

In result we can get a report like the one below:

...

warning:
Line:16   
    
warning:
Line:20   

...

It can be very useful for continuous integration system like Bamboo where you can have online dashboard of SwiftLint results:


Lessons learned

After almost one year of using it, personally I think it’s a very great tool! Below are main thougts about my experience:

  • Use it from the start of your project. Every single build will correct your tiny mistakes and will inform you about violations.
  • Meet with your iOS team and establish your own rules (according to your company guidelines).
  • Experiment with values for different rules and change it during development of your project, because sometimes very strict rules can change your coding into a fight with a tool:/.
  • It’s very useful especially when you work in a big iOS team to have consistent codebase.
  • Very easily configurated in just one file: .swiftlint.yml.
  • Can be integrated with continuous integration systems (like Bamboo or Jenkins).
Tips
  • You can also integrate SwiftLint with your Xcode by using SwiftLintXcode plugin (unfortunately it doesn’t have seamless installation process for Xcode 8):

  • Move .swiftlint.yml configuration file to Xcode project file structure:

In this way you can configure it very easily.

SonarQube

SonarQube is an open source platform for continuous inspection of code quality. Supports more han 20 languages: Java, C/C++, Objective-C, C#, PHP, Flex, Groovy, JavaScript, Python, PL/SQL, COBOL, Swift, etc. Unfortunately plugins for some of the languages are commercial, as is the plugin for Swift. Additionally it has available more than 50 plugins.

Basics

Sonar at this moment has 92 rules for Swift, which are divided into three groups:


They can be marked in aspect of severity as:
Blocker, Critical, Major, Minor, Info:


Some examples below:

  • Bugs:
    • URIs should not be hardcoded (Critical)
    • Optionals should not be force-unwrapped (Major)
    • Functions and closures should not be empty (Major)
  • Vulnerabilities:
    • Credentials should not be hard-coded (Critical)
    • IP addresses should not be hardcoded (Major)
    • Access control should be specified for top-level definitions (Major)
  • Code smells:
    • Files should not have too many lines (Major)
    • Source files should not have any duplicated blocks (Major)
    • "self" should only be used when required (Minor)
Metrics

Sonar uses following metrics:

  • Security: Number of vulnerabilities.

  • Maintability: Number of code smells.

  • Reliability: Number of bugs.

  • Duplications: Number of duplicated blocks of lines.

  • Complexity: It is the complexity calculated based on the number of paths through the code.

  • Documentation: Number of lines containing either comment or commented-out code.

What we can also see is:

  • Technical debt:

Wikipedia: "Technical debt is a concept in programming that reflects the extra development work that arises when code that is easy to implement in the short run is used instead of applying the best overall solution. Technical debt is commonly associated with extreme programming, especially in the context of refactoring"

In Sonar technical debt is calculated based on algorithm below:

Debt(in man days) = cost_to_fix_duplications + cost_to_fix_violations +
    cost_to_comment_public_API + cost_to_fix_uncovered_complexity +
    cost_to_bring_complexity_below_threshold


Lessons learned
  • SonarQube has a Web dashboard which can be easily shared and custiomized to your needs in development team
  • Has a lot of rules
  • Establish rules and their severity with your team
  • Can be really helpful in a situation when you work on a legacy code to check its quality
  • Can be integrated with continuous integration systems
  • A lot of plugins (SwiftLint)
  • But unfortunately it is quite expensive: 5,000 euro per year

If you would like to test SonarQube by yourself before buying it, you can visit this demo website

Checkmarx

Checkmarx is a security platform providing several tools for introducing advanced static security analysis into applications written in C#, Java, jscript, native C/C++ or APEX.

Basics

Checkmarx scanner interprets Swift to Objective-C in the backend before scanning the code. As a result, Checkmarx scans Swift code for over 60 quality and security issues, including twelve of the most severe and most common issues that cannot be left unfixed.

On Checkmarx website you can find a lot of interesting articles dedicated to mobile application, for example:

Checkmarx offers a Web dashboard on which you can find summary for all vulnerabilities found in your projects:


Lessons learned

Checkmarx misses rules typical for Swift. I think that it is because Swift is a new and rapidly changing language. For sure there are still a lot of possibilities for defining new rules like they did for the others languages.

Other frameworks

At this moment there are not many different libraries for linting Swift. I have only found this one:

I hope that in the future we will see much more alternatives.

Summary

In my opinion static code analyzers can make your codebase more consistent, and for sure can really help during your daily coding and speed up the process. Of course we should remember about golden mean in using such libraries. It would be good not to turn our job into a nightmare by using very strict rules:)!

]]>
http://swifting.io/blog/2016/10/25/26-swiftlint-sonarqube-and-checkmarx-what-else/feed/ 1
#24 Architecture Wars – A New Hope http://swifting.io/blog/2016/09/07/architecture-wars-a-new-hope/ http://swifting.io/blog/2016/09/07/architecture-wars-a-new-hope/#comments Wed, 07 Sep 2016 18:38:09 +0000 http://swifting.io/?p=581 A long time ago in a galaxy far, far away… Or maybe not that far away…

Have you ever had a feeling, as I have had many times, that the design of your app seemed so brilliant at first, but suddenly adding more and more features to it made your source code more complicated and eventually, unmaintainable. Presumably you hadn’t written unit tests because there hadn’t been time for that. You wish you hadn’t chosen standard MVC approach, but MVVM or VIPER instead, that you had heard so many times about. After all they’re so brilliant, so shiny and bright and give A New Hope to all developers. They’re so cool and they’re so many other things… Or are they?

What is this all about?

For a few years of my professional career I have been creating apps in different architectures (MVC, MVVM, VIP) and have been searching for the best one. Recently at work, I have been having a roaring discussion about architecture used in the current project. My team and I had decided to try out VIP (a.k.a Clean-Swift) architecture and after two months of development we have argued about its pros and cons.

This blog post is an initial comparison of all architectures that the swifting.io team has used in the past in their applications. In this issue, I will explain basic concepts of MVC (does it even need to be explained 😉 ?), MVVM, VIPER and VIP (a.k.a. Clean-Swift) and point out their advantages and drawbacks.

I hope you will find these thoughts useful and helpful, wether you’re about to fight your own battles in Architecture Wars at your workplace or you just want to select right solution for your own app 😎!

MVC

Probably many developers started their adventure with iOS applications with the CS193P Stanford course on iTunes U, as I did. In the course, one can get to know basic Cocoa Touch concepts, as long as the Model – View – Controller architecture hailed by Apple.

The basic concept of it is that an object called Controller responds to events triggered by a View. It can update a Model upon an action, and update the View when the Model changes. In the worst-case scenario, the Controller, or rather the View Controller in Cocoa Touch, deals with animations, data persistence and network calls, growing into a so called Massive View Controller. If we extracted some of the logic into separate objects, such as Core Data (Persistence) and Network services, the architecture would look as follows:


The MVC architecture is used all the time by Apple and the majority of developers follow the lead. When for Apple it’s the easiest way to explain their API concepts, for developers it’s the fastest way to develop an application. I think that Apple knows that Massive View Controllers are a problem, so to improve testability of MVC components Apple mentioned dependency injection as a good practice on WWDC 2016’s Improving Existing Apps with Modern Best Practices session. I interpret this as if they said "Hey, it’s not good to put all of the code to a View Controller, inject some dependency objects that do certain things and test interactions with them" 😉.

MVVM

MVC is not the only valid app architecture. There are also other, and amongst them there is a Model – View – View Model. It assumes existence of a View Model, which is an additional layer that a View Controller communicates with. It contains business logic and to tackle with it, it can contain other objects, such as e.g. Network and Core Data services. It exposes a Model as formatted data in its properties, so that the View Controller can bind the data to a View. Usually the View Controller observes changes in those properties and updates its View on a property change.


As every approach to application design, MVVM has its drawbacks. In our project, proverbial 1000 lines of View Controller became 1000 lines of View Model. Of course, View Controller got rid of other responsibilities than responding to View events and animations, but enormously huge business logic made our View Model to swell a lot.

With MVVM you can also use some reactive extensions, that allow to observe changes in View Model’s properties and act upon those changes. You can either bind a View Model’s property to a View directly or put a block of code that executes when property value changes and bind its output to a View. I have used Swift Bond for that, which contains extensions for UIKit objects that simplify binding View Model properties to views. It is no longer maintained, but you can tap into ReactiveKit, which is a successor of Swift Bond.

There is also a more known framework called RxSwift, which is a part of ReactiveX family. It contains RxCocoa, which are reactive extensions for Cocoa and CocoaTouch. What’s great about RxSwift is that if you have created an Rx app in the past in other language, the rules, operators, functions and keywords in RxSwift are the same. You can check RxMarbles website to get familiar with Rx operators and functions.

VIPER

We’ve already written the whole issue about View – Interactor – Presenter – Entity – Router. It is another way of setting up your app’s architecture. VIPER divides View Controller’s responsibility in standard MVC to different objects. A View Controller sets data from its Presenter to a View. Presenter formats data from Interactor and asks Router to perform navigation to a different module. Interactor contains business logic on data manipulation, performs network requests and saves Entities (model) to a persistent store via proxy objects. View, Interactor, Presenter, Entity and Router components of a View Controller, along with it, are called a module.


This architecture clearly enforces to write code in a structured way and divides View Controller’s responsibilities onto smaller objects. When compared to MVVM, business logic and data presentation was split from View Model to Interactor and Presenter. There is also an additional component called Router (a.k.a Wireframe), which deals with setting up other view controllers, wiring up their dependencies and setting delegations which allow communication with other scenes. After all, a View Controller shouldn’t have knowledge on what the next view controller is and how to set it up.

Using VIPER for code of your app is hard at first. The architecture is hard to understand, there are too little materials on the topic for iOS world and there is a large entry barrier for new developers in the team. Architecture adds code overhead, components of a module rather cannot be reused. Communication is based on protocols which hardens navigation between many files in Xcode. But c’mon, protocols facilitate testing, which is the thing you should probably use in your apps 😉.

VIP (Clean Swift)

This architecture was proposed by Raymond Law on his Clean Swift blog. In my opinion, VIP (a.k.a. Clean Swift) can be considered as a variation of VIPER. It gets its name from View (Controller) – Interactor – Presenter uni-directional cycle. VIP diverges from VIPER but yet it nicely divides responsibilities and propagates data among components. View Controller interacts directly with an Interactor by sending Requests to it. The Interactor responds to those requests by sending a Response with data model to a Presenter. The Presenter formats data to be displayed, creates a View Model and notifies the View Controller that it should update its View based on the View Model. View Controller decides when the navigation to a different scene should happen by calling a method on a Router. The Router performs setup of the next View Controller and deals with wiring, passing data and delegation setup. VIP components belonging to a single View Controller form a scene.


Clean Swift has a very good documentation and reasoning behind its concept explained on the Clean Swift blog. Clean Swift concepts are rigid, especially namespaces created for every scene, data passing in Request, Response and ViewModel objects, which are rather non-reusable within scene, because they correspond to a specific Request-Response chain. Sometimes Interactor methods doesn’t have to take any arguments, yet the architecture enforces usage of empty Request params. Communication between objects is again based on protocols, but it has some overhead in protocol declaration.

Clean Swift assumes, that View Controller has an output that implements methods from ViewControllerOutput protocol. The Interactor is ViewController‘s output, but methods that View Controller calls on Interactor are its input, hence it implements methods from InteractorInput. In code it would look as following:

protocol ViewControllerOutput {
    func doSomehtnig(_ request: Request)
}
protocol InteractorInput: ViewControllerOutput {}

Although Clean Swift imposes strict rules, it appropriately divides responsibilities and creates uni-directional cycle. When compared to VIPER, another difference is that now the View Controller itself contacts Router for navigation, which is in my opinion a nice improvement (no routing of navigation request through VIPER’s Presenter). Currently, we use a slightly modified VIP architecture for a project and we are quite fond of it.

Comparison

It’s time for a comparison of MVC, MVVM, VIPER and VIP. For some of the metrics, MVC is a baseline. We take into consideration the following aspects:

  • Responsibilities – describes if there is an object that plays all roles or if there are many objects with different liabilities
  • View Controller– describes the role of a View Controller
  • Data flow – describes how data flows in the scene
  • Testability – evaluates how easy it is to test components
  • Entry – rates how easy it is for a person to dive into a project or to start developing an app in a certain architecture
  • Collaboration – rates how easy it is to collaborate on a scene written in a certain architecture
  • Reusability – evaluates if scene components can be reused in a different scene
  • Refactoring – rates how many components are affected during refactoring process
  • Number of files – evaluates number of files in the project
  • Lines of code in a single file – evaluates number of lines in the single file

MVC MVVM VIPER VIP
Responsibilities entangled dispersed dispersed dispersed
View Controller does everything passes actions to and binds data from View Model passes actions and binds data from Presenter passes actions and displays data from Presenter, decides when to navigate to the next scene
Data flow multi-directional multi-directional multi-directional uni-directional
Testability hard (too many responsibilities) better best best
Entry easy hard (when starting with reactive extensions) hardest hard, but good documentation exists
Collaboration hard better best best
Reusability rather none rather small ok ok
Refactoring normal normal (affects View Controller – View Model boundary) worse (can affect many boundaries due to multi-directional flow) normal (affects one boundary due to uni-directional flow)
Number of files normal additional View Model for every View Controller many many
Lines of code in a single file too many many most-satisfactory most-satisfactory

Summary

It’s not easy to select the best architecture for an app. I hope that this issue will enlighten differences between a few architectures and help you choosing the one that suits you best. As a curiosity, recently I came across Flux architecture for iOS, which develops Facebook’s Flux concept for web apps. I haven’t tried it yet, but the main idea is that application state is passed through a uni-directional flow that allows views to update accordingly and store history of app states. Let us know if you have already tapped into it!

Sometimes we have to fight fiercely for the chosen architecture. Not all developers in the team will like it, not everything will be easy at first, but it is worth discussing and worth using a nice architecture. In the discussion, you can get to the point where you realise that certain aspects of the architecture do not suit or are redundant and you can compromise. After all, it’s better to have a good atmosphere in the team, where developers are friends rather than enemies that feel resentment to each other because of this new and stupid architecture you write your application in. Remember that, if you happen to battle in your Architecture Wars, eventually source code will look as usual…


This issue is just an introduction to architectures realm. We will continue the topic with a sample app written in MVC, MVVM, VIPER and VIP. Stay tuned!

References

]]>
http://swifting.io/blog/2016/09/07/architecture-wars-a-new-hope/feed/ 12
#18 Do pure Swift objects have load() method? http://swifting.io/blog/2016/06/13/18-do-pure-swift-objects-have-load-method/ http://swifting.io/blog/2016/06/13/18-do-pure-swift-objects-have-load-method/#comments Mon, 13 Jun 2016 07:00:10 +0000 http://swifting.io/?p=486 I’m pretty sure this day, or actually the whole week, will be pretty exciting due to the start of WWDC 2016. Before that happens I’d like to share my finding from unit testing of one of my view controllers. If you’re not familiar with unit testing, check out our last issue Unit Test all the things!.

Unit test all the things!

We encourage you to test all the things 😉 ! But mainly interactions between objects. I also like to test communication of view controllers with their dependencies. The example below shows how a sample test could look like:

context("ViewController") {
    var sut: ViewController!
    var dependencyOfSut: Dependency!
    
    beforeEach {
        dependencyOfSut = MockDependency()
        sut = ViewController(dependency: dependencyOfSut)
    }
    
    describe("when view loads") {
        beforeEach {
            sut.viewDidLoad()
        }
        
        it("setups something") {
            expect(dependencyOfSut.setupSomethingCount).to(equal(1))
        }
        
    }
}

The snippet should be self-explanatory. If it isn’t, let me elucidate it a bit. This is a test of ViewController class, that is initialised with a Dependency object in beoforeEach‘s closure argument. Test checks what happens when viewDidLoad method gets called. It is expected that setupSomething method is called once when view loads.

Ok, but what else can we test?

We can check if appropriate buttons are set on navigationItem:

it("has right button") {

    expect(sut.navigationItem.rightBarButtonItem)
        .to(beAKindOf(UIBarButtonItem))
        
    expect(sut.navigationItem.rightBarButtonItem?.enabled)
        .to(beTrue())
        
}

We can also assert if view controller is UITableView’s or UICollectionView’s delegate:

expect(sut.tableView.delegate 
    as? MyViewController).to(equal(sut))
    
expect(sut.collectionView.delegate 
    as? MyViewController).to(equal(sut))

Another super important thing to check is if an appropriate action takes place after a tap on a button. Last week we migrated an app from Swift 2.1 to 2.2 and we didn’t have tests for navigation bar buttons. Buttons simply stopped working. If we had tests for their actions we would have noticed the bug before releasing demo version of our app to client. Of course a tester could assert that everything works correctly, but you need to have one. Unit test all the things. Really! 🙂

What has changed in Swift 2.2? Among other things the syntax for selectors.

The old way:

navigationItem.rightBarButtonItem =
        UIBarButtonItem(barButtonSystemItem: .Add, target: self,
                        action: "doSomething")

Code in Swift 2.2:

navigationItem.rightBarButtonItem =
        UIBarButtonItem(barButtonSystemItem: .Add, target: self,
                        action: #selector(doSomething))

BTW, if you don’t know what’s your Swift version in Xcode you can check it out with the xcrun swift -version command in Terminal.

Ok, but how to test if an action is connected to a button? Look at the snippet below. Imagine we had a Helper class that could perform a tap on a button (more about it in a moment). In assert part of your test you simply need to check if a desired action happened, just like before, by using method counters.

What if you wanted to check if a new view controller was shown after action? You need to use toEventually function that is able to asynchronously assert the expectation. Your expectation is to check if presented view controller of tested object is of certain kind:

describe("tap on the right button") {
    beforeEach {
        Helper.tap(sut.navigationItem.rightBarButtonItem)
    }
    
    it("shows my other view controller") {
        expect(sut.presentedViewController)
            .toEventually(beAKindOf(MyOtherViewController))
    }
}

The Helper class actually exists. It was typealiased in the snippet. I’ve actually called it UnitTestHelper and its contents is available in this gist.

class UnitTestHelper {
    
    class func tap(button: UIButton?) {}

    class func tap(button: UIBarButtonItem?) {}
        
    //...
    
}

The tap function uses UIApplication‘s sendAction:to:from:forEvent method for sending an action to button’s target.

If you want to see more samples of UIViewController unit tests, check this gist. It contains snippet for testing a view controller with a view model and a table view. Ok but let’s go to the main question of this post.

Do pure Swift objects have load method?!

NSObject instances/subclasses have load() class function that is

Invoked whenever a class or category is added to the Objective-C runtime;

–Apple’s documentation

In my recent project I used MVVM architecture, where every view controller has its own view model (a component that deals with business logic and formats data to be displayed). One of the desired interactions of view controller with its view model was that view controller, in viewDidLoad, calls load method on view model to load data to be displayed.

class MyViewModel {
    func load() {}
}

class MyViewController: UIViewController {
    let viewModel: MyViewModel
    init(viewModel: MyViewModel = MyViewModel()) {
        self.viewModel = viewModel
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.whiteColor()
        viewModel.load()
    }
}

In terms of unit test spec the desired behaviour was asserted like this:

describe("when view loads") {
     beforeEach {
        sut.viewDidLoad()
     }
     it("calls load on viewModel") {
        expect(viewModel.loadCount)
        .to(equal(1)) 
    }
}

I ran tests, they failed, which was ok at that point. After all I use BDD and I was in the red phase. Then I implemented the code, ran tests again and the aforementioned assertion failed again. I started scrutinising my code, but I didn’t find any flaw. What had possibly gone wrong? The assertion looked like this:


I couldn’t believe my eyes. How?! Pure Swift object with load method called before I called it? Do pure Swift objects have load method?! I scrutinised my code again, put some breakpoints here and there. Then I realised that this method gets called after I called viewDidLoad:

func loadView()

The view controller calls this method when its view property is requested but is currently nil.

–Apple’s documentation

Do you know what’s called after loadView? The viewDidLoad method. Hence load was called twice on viewModel. And why on Earth was the loadView called? Because I touch view property for the first time during test runtime:

override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.whiteColor() //HERE view is touched for the first time during the unit test
        viewModel.load()
}

What’s the solution to this problem? Mine was to accept the loadCount to be greaterThan(0). Instead of calling viewDidLoad I could just access sut.view in beforeEach in order to call viewDidLoad only once. UPDATE July 9th 2016: Starting from iOS9 you can also use the loadViewIfNeeded method and remember not to touch view during initialisation 😉! Thx for Kakamil for the tip!

Maybe you have other solution to the problem, or have experienced other unit testing story. I encourage you to share them in comments :)!

TL; DR

Pure Swift objects don’t have load method.


]]>
http://swifting.io/blog/2016/06/13/18-do-pure-swift-objects-have-load-method/feed/ 4
#17 Unit test all the things! http://swifting.io/blog/2016/06/06/17-unit-test-all-the-things/ http://swifting.io/blog/2016/06/06/17-unit-test-all-the-things/#respond Mon, 06 Jun 2016 06:58:49 +0000 http://swifting.io/?p=404 There is always a half

When I was at the 3rd year of my BEng studies I had a chance to visit Turin, Italy, and to take part in Erasmus student’s exchange programme. At Politechnico di Torino I attended "Operating Systems" course on which the lecturer used to ask participants wether they had ever done some programming in C or not, had used selected linux commands and etc. Then he would count all the hands in the air to check how many of us had had a knowledge about the certain topic. No matter how many hands were up he always wittingly said a half.

Recently I did the same on iOS Developers Meetup in Poznań, Poland. And of course, the result was that a half of attendants had done the activity I asked about 😉. I wonder to which group you belong. So now I’m asking you:

Are you a person who has never written a unit test in Xcode?

If not, maybe you are a person who would answer positively to this question:

Have you 🙊ever written a unit test in Xcode?

Regardless of your answer, this post is for you 💡! It will cover basic topics in BDD🔮, explain my Swift toolset🔧🔨 for unit testing and summarise benefits🍓 of performing unit tests in your project.

3 types of programmers

When I started my professional career I didn’t know what unit tests are. But after a few years I can easily point out three groups of programmers.

There is a small group of unit test lovers who say that unit testing is cool ❤️ and they couldn’t live without testing all the things. Really, a really small group!

There is also the majority that says that real men 👨🏻 test on PRODUCTION. Kinda risky but good luck for them 🍀!

And there are many, especially in iOS world, that don’t know how the 🙊 they can start doing it? I was one of them two years ago. Thanks to interesting people I have met now I know …

… WT🙊 a unit test is?

If you have ever tried out searching on Wikipedia what a unit test is you would be surprised what its standard bla, bla, bla says.

In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use.

–Wikipedia

It didn’t illuminate me a bit. So based on my experience I have created my own definition:

code that tests source code

–Maciej Piotrowski


To understand the definition🔮 profoundly we have to understand a few terms at first.

What’s an app?

There are a few equations that can define an app. Let’s look at them.

First of all we should know that the app is a set of behaviours. By behaviour one can understand certain actions that take place, e.g. when user taps a button in our app it shows another view controller, etc.

  • App = Set(behaviours😄😭)

Application consists of components. If not, you’re probably doing it wrong 😉!

  • App = component 🎁 + … + component 🎁

Those components interact with each other in order to fulfil a certain behaviour.

  • component ← interaction 👏🏻 → component

Our code that tests source code can test that particular interaction between components took place. This is called behavioural unit testing.

  • unit test = checks(🎁interaction 👏🏻🎁) == ✅

Of course we can also test function’s output when sticking to BDD. BDD!? Wait. What’s BDD?

TDD & BDD

BDD stands for Behaviour Driven Development. It’s built upon TDD, Test Driven Development. Basic rule of TDD is:

Don’t you dare writing code before writing a test for it!

Namely, you have to write testing code to assert what component code should do and then implement the component itself. TDD flow distinguishes three steps: RED, GREEN, REFACTOR.


What’s different in BDD? Behaviour-driven development tells that tests of any unit of software should be specified in terms of the desired behaviour of the unit. Basically, a behaviour is what a component does when a certain action (i.e. method call) takes place. When you call a function it probably communicates and interacts with other components. When writing a unit test we can just test if an interaction took place (as mentioned earlier).

Behaviours😄😭

Imagine we have to write a component which deals with CoreBluetooth API. Let’s call it BluetoothModule. It’s main responsibility is to start and stop advertising Bluetooth Services. It will support only that, hence our iPhone would become a Bluetooth Low Energy Peripheral (information for curious readers)

Ok, so let’s write down our expected Behaviours 😄😭.

"BluetoothModule"
            "when turned on"
                "advertises services"
    
            "when turned off"
                "doesn't advertise services"

What the 🙊 spec?!

I kinda looks like a specification 📋 of our source code. There is a nice BDD framework to write testing code with a 🔮DSL. It’s called Quick and we can create specs with it! :). An excerpt from a spec would looks like this:

context("BluetoothModule") {
    describe("when turned on") {
        it("advertises services") {}
    }
    describe("when turned off") {
        it("doesn't advertise services") {}
    }
}

Normally a spec contains assertions 🔔 (testing code). Quick has a counterpart, called Nimble – it has a set of matchers handy in writing expectations. More on that in a moment, but before let’s have a look on how to write a QuickSpeck:

import Quick
import Nimble
@testable import <#Module#>
class <#TestedClass#>Spec: QuickSpec {
    override func spec() {
        //🔮Magic goes here 🙈🙉🙊
    }
}

First and second lines import Quick (BDD DSL) and Nimble (matchers) frameworks. The @testable directive introduced in Swift 2.0 let’s us import our app’s module in a ‘testable’ manner, i.e. we can access components’ internal methods and properties.

All tests should be contained in spec() method overriden in QuickSpec subclass. Inside the method we use Quick DSL to describe component’s specification and assert its behaviours.

Arrange, Act, Assert

Ok, but now a question should have already crossed your mind – how to write asserting (testing) code?

Every test consists of three phases:
– Arrange – arrangement of our ‘scene’, i.e. initialisation of tested object and its dependencies (components that it interacts with)
– Act – execution of an action, i.e. a method call on a tested object
– Assert – actual testing code, an assertion that checks that the expected behaviour/interaction took place

Let’s assume our component to be tested has this simple interface:

class BluetoothModule {
    init(peripheralManager: CBPeripheralManagerProtocol)
    func turnOn()
    func turnOff()
}

It has two methods and takes an object that implements CBPeripheralManagerProtocol as its dependency. Why CBPeripheralManagerProtocol and not just CBPeripheralManager? More will be explained in I wish we had mockingjays 🐦 section of this article. We can arrange testing "scene" for with mock object as in the snippet below:

class BluetoothModuleSpec: QuickSpec {
    override func spec() {
        context("BluetoothModule") { //i.e. newly initialised
            var sut: BluetoothModule!
            var peripheralManager: CBPeripheralManagerProtocol!
            beforeEach {
                peripheralManager = MockPeripheralManager()
                sut = BluetoothModule(peripheralManager: peripheralManager)
            }
            afterEach {
                peripheralManager = nil
                sut = nil
            }
        }
    }
}

Quick gives us a few functions we can use to arrange a "scene":

  • context – description of object’s state (e.g. object is newly initialised), takes String with a description and a closure as argument
  • beforeEach – takes a closure argument to setup local variables (corresponds XCTest’s setup)
  • afterEach – takes a closure argument to cleanup local variables (corresponds XCTest’s tearDown)

When we have all objects set up the Act phase approaches. It’s the phase in which we invoke certain methods on the tested object:

context("BluetoothModule") {
    //...
    describe("when turned on") {
        beforeEach {
            sut.turnOn()
        }
    }
    describe("when turned off") {
        beforeEach {
            sut.turnOff()
        }
    }
}

Again, Quick gives us a few functions we can use to perform actions on the arranged object:

  • describe – used for description of an action performed on the subject, takes String with a description and a closure as argument
  • beforeEach – used for performing an action on the sut (subject of unit testing a.k.a. system/subject under test – choose what suits you best)

The last, but not least, is Assert phase. In this part we write actual testing code (code that tests source code):

context("BluetoothModule") {
    describe("when turned on") {
        //...
        it("advertises services") {
            expect(peripheralManager.isAdvertising)
                .to(beTrue())
        }
    }    
    
    describe("when turned off") {
        //...
        it("advertises services") {
            expect(peripheralManager.isAdvertising)
                .to(beFalse())
        }
    }    
}

Quick comes in handy with it function – takes a String with a description of desired outcome of a test and closure with a test of an expected behaviour. Nimble gives as a way to write some expectations. But what and how to expect?

What and how to 🙊 expect?

Of course you can Expect the unexpected. Sometimes test outcome will surprise you remarkably. In the next issue I will write about one of surprises I had with my testing code.

In our code that tests source code we use expect() method from Nimble 💥 framework, which also provides a number of matchers to fulfil the expectation. Matchers are used in it blocks to assert the expectation ✅. Let’s have a look at some example expectations:

expect(sut.something)
    .to(equal(5))
    
expect(sut.somethingDifferent)
    .toNot(beAKindOf(MyClass))
    
expect(sut.somethingElse)
    .toEventually(beNil())

As you can easily see, the expect() function takes as an argument an expression to be evaluated by using a matcher provided in to*() function. We can expect e.g. a property on our tested object to equal some value, to be a certain kind of class, or to eventually be Optional(.None) 😉.

The to() and toNot() functions are rather straight forward – they test the actual value of expectation with the matcher. The toEventually() function is used for asynchronous tests. It continuously checks the assertion at each pollInterval until the timeout is reached.

Hey, if an object needs to be checked ✅ with equality with other object, we need to implement Equatable protocol! To do so, we just need to implement the ==() operator:

extension MyClass: Equatable {}

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
    return lhs.propertyX == rhs.propertyX 
    && lhs.propertyY == rhs.propertyY
    && lhs.propertyZ == rhs.propertyZ 
}

When the above approach is suitable for structs, for classes we could be lazier and compare arguments’ ObjectIdetifier() instead of comparing different properties:

extension MyClass: Equatable {}

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
    return ObjectIdetifier(lhs) == ObjectIdentifier(rhs)
}

If you happen to be a super lazy person, this approach is for you. Just allow your class to inherit from NSObject, or probably any Cocoa/CocoaTouch class, because all of them are NSObject subclasses, and you get equality comparison for free🎁!

class class1: NSObject {}
class class2: NSObject {}

let c1 = class1()
let c2 = class2()

it("should not be equal") {
    expect(c1).toNot(equal(c2))
}

It’s important to implement Equatable or use the approach for super lazy people, if we do not, we won’t be able to compare objects for equality with Nimble and will get a confusing message from compiler 😢.


I wish we had mockingjays 🐦

Remember our BluetoothModule object? It takes in init() an object that implements CBPeripheralManagerProtocol as its dependency. There are at least two reasons why the dependency is declared in terms of protocol instead of pure CBPeripheralManager instance.

In unit testing we want to have full control over dependencies injected to tested object. To have it we inject test doubles as dependencies. We distinguish a few types of test doubles:

  • stub – fakes a response to method call
  • mock – allows to check if a call was performed
  • partial mock – actual object altered a bit (some responses faked, some not)

W🙊W. Out of the box mocks are not possible in Swift

In Objective-C we were able to easily mock objects thanks to its dynamism and access to run time. But Swift is currently read-only 📖. There is no way to change class types & objects at run time 😢. So …

Communicate with objects through protocols:

protocol CBPeripheralManagerProtocol: class {
    
    //...
    weak var delegate: CBPeripheralManagerDelegate { get set }
    
    func startAdvertising()
    func stopAdvertising()
}

If you don’t you will end up with inheritance and partial mocks, which is not recommended. Bad things can happen when you inject real CBPeripheralManager instances or partial mocks made by subclassing it.

So we have an interface defined by protocol. Why not to implement it in our Mock?

class MockCBPeripheralManager: CBPeripheralManagerProtocol {
    
    //...
    var startAdvertisingCount = 0
    
    func startAdvertising() {
        startAdvertisingCount += 1
    }     
    
}

Of course we can leave some methods or properties with an empty implementation. Implement just those you need. E.g. to check if a method was called add a method call counter and assert it’s value in a test:

context("BluetoothModule") {
    describe("when turned on") {
        //...
        
        it("advertises services") {
            expect(peripheralManager.startAdvertisingCount)
                .to(equal(1))
        }
        
    }    
}

What is it all f🙊r ?

Unit testing is still not common in iOS development. If someone asks TDD/BDD gurus about how much time they spend on writing tests when developing an app, they answer a half⌛️. That’s a lot, isn’t it? But it pays off in the end by having:

  • better understanding 🔍 a codebase
  • 📈 well thought architecture
  • properly documented assumptions 🔮
  • no fear of making changes 💥
  • getting to know 🍏 Apple frameworks better
  • ❤️ fun !!! ❤️

If you don’t know how to start, on June 18th Mobile Academy organises Swift TDD training in Poznań. Let’s meet there :)!

TL; DR

The time to start writing unit tests❤️ is now!


Resources

]]>
http://swifting.io/blog/2016/06/06/17-unit-test-all-the-things/feed/ 0
#15 Nested enums or rather never ending posts about enums:) http://swifting.io/blog/2016/05/16/15-nested-enums-or-rather-never-ending-posts-about-enums/ http://swifting.io/blog/2016/05/16/15-nested-enums-or-rather-never-ending-posts-about-enums/#respond Mon, 16 May 2016 13:05:56 +0000 http://swifting.io/?p=377 Today I would like to discuss how to present UITableViewCell contents by using enums. A simple switch statement can help us with displaying data on our tableView. What scenario would I like to focus on?

PlaceInfoView
PlaceInfoView

To be more precise, I have created a simple schema of this screen:

PlaceInfoScheme
PlaceInfoScheme

By the way, have you had a chance to use Sketch for prototyping? Quite a nice tool!!!

The question is: what is the best proposal of enum configurations and functions, which can help us with displaying data when using tableView:cellForRowAtIndexPath: method for an example above?

My first proposal was:

enum PlaceInformation: Int { // Used on UISegmentControl
    case General
    case More
}

enum GeneralInfo: Int {//Cells for General Info Segment (Tab)
    case Description
    case HowToGoHere
    case Hotel
}

enum MoreInfo: Int {//Cells for More Info Segment (Tab)
    case CurrentWheather
    case InterestingPlacesNearby
}

class PlaceInformationViewController: UIViewController, UITableViewDataSource {
    
    var tableView: UITableView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView = UITableView()
        ...
    }

    let selectedTabIndex = 0 //selected segment on UISegmentedControl
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = UITableViewCell()
        let row = indexPath.row
        let selectedInformationTab: PlaceInformation = PlaceInformation(rawValue: selectedTabIndex)!
        
        switch selectedInformationTab {
        case .General:
            guard let informationCellType = GeneralInfo(rawValue: row) else { break }
            switch informationCellType {
            case .Description:
                print("Setup Description Cell")
            case .HowToGoHere:
                print("Setup HowToGoHere Cell")
            case .Hotel:
                print("Setup Hotel Cell")
            }
        case .More:
            guard let informationCellType = MoreInfo(rawValue: row) else {  break }
            
            switch informationCellType {
            case .CurrentWheather:
                print("Setup Wheather Cell")
            case .InterestingPlacesNearby:
                print("Setup InterestingPlacesNearby Cell")
            }
        }
        return cell
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
}

Some statistics of the above code:

  • Lines of code of tableView:cellForRowAtIndexPath: function: 28
  • What did SwiftLint say?
SwiftLint
SwiftLint
  • Codebeat rated the code to 3.97 GPA (Function too long)

My intuition prompted that it can be done better:). So I have started thinking of how to refactor the code.

First refactoring

So here we go with first refactoring. Below is my to do list to make this enum better:

  • Remove white spaces according to SwiftLint
  • Reduce cases in enum to one line
  • Use nested enums
  • Necessarily I wanted to check if enum associated values can improve code metrics. I don’t know why, but I hoped that it will improve my situation:)

enum PlaceInformationCellModel {
    // returned cell depends on selectedTab and tableview section
    case Header(selectedTab: PlaceInformation, section: Int)

    enum PlaceInformation: Int { // Used on UISegmentControl
        case General
        case More
    }
    
    enum PlaceHeader {
        case Description, HowToGoHere, Hotel, CurrentWheather, InterestingPlacesNearby
        static let allGeneralHeaders = [Description, HowToGoHere, Hotel]
        static let allMoreHeaders = [CurrentWheather, InterestingPlacesNearby]
    }

    var value: PlaceHeader {
        switch self {
        case .Header(let tab, let sectionIndex):
            switch tab {
            case .General:
                return PlaceHeader.allGeneralHeaders[sectionIndex]
            case .More:
                return PlaceHeader.allMoreHeaders[sectionIndex]
            }
        }
    }
}

class PlaceInformationViewController: UIViewController, UITableViewDataSource {

    var tableView: UITableView?

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView = UITableView()
        ...
    }
    
    let selectedTabIndex = 1 //selected segment on UISegmentedControl

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let cellModel: PlaceInformationCellModel = PlaceInformationCellModel.Header(selectedTab: PlaceInformationCellModel.PlaceInformation(rawValue: selectedTabIndex)!, section: indexPath.row)
        let header = cellModel.value
        let cell = UITableViewCell()

            switch header {
            case PlaceInformationCellModel.PlaceHeader.Description:
                print("Setup Description Cell")
            case PlaceInformationCellModel.PlaceHeader.HowToGoHere:
                print("Setup HowToGoHere Cell")
            case PlaceInformationCellModel.PlaceHeader.Hotel:
                print("Setup Hotel Cell")
            case PlaceInformationCellModel.PlaceHeader.CurrentWheather:
                print("Setup CurrentWheather Cell")
            case PlaceInformationCellModel.PlaceHeader.InterestingPlacesNearby:
                print("Setup InterestingPlacesNearby Cell")
            }
        return cell
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
}

Is it better? I hoped so, so I have asked my friends about feedback:

  • Lines of code of tableView:cellForRowAtIndexPath: function: 20

  • What did SwiftLint say?

SwiftLint
SwiftLint
  • What did codebeat say?: 4.00 GPA

Second refactoring

I still had a feeling that the code was too complicated. I thought that getting rid of associated values would make it simpler.

enum PlaceInformation {

    case General, More

    enum PlaceHeader: Int {
        case Description, HowToGoHere, Hotel, CurrentWheather, InterestingPlacesNearby
        static let allGeneralHeaders = [Description, HowToGoHere, Hotel]
        static let allMoreHeraders = [CurrentWheather, InterestingPlacesNearby]
    }

    var placeValues: [PlaceHeader] {
        switch self {
        case .General:
            return PlaceHeader.allGeneralHeaders
        case .More:
            return PlaceHeader.allMoreHeraders
        }
    }
}

class PlaceInformationViewController: UIViewController, UITableViewDataSource {

    var tableView: UITableView?

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView = UITableView()
    }
    
    let selectedInformationTab: PlaceInformation = .General

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let header = selectedInformationTab.placeValues[indexPath.row]
        let cell = UITableViewCell()

        switch header {
        case .Description:
             print("Setup Description Cell")
        case .HowToGoHere:
            print("Setup HowToGoHere Cell")
        case .Hotel:
            print("Setup Hotel Cell")
        case .CurrentWheather:
            print("Setup CurrentWheather Cell")
        case .InterestingPlacesNearby:
            print("Setup InterestingPlacesNearby Cell")
        }
        return cell
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
}

Feedback:

  • Lines of code of tableView:cellForRowAtIndexPath: function: 18
  • SwiftLint:
SwiftLint
SwiftLint
  • Codebeat gave me 4.00 GPA for this code. codebeat badge

It seems that the easiest solution is the best:

GitHub Logo
GitHub Logo

Third refactoring

I would like to leave the next iteration of refactoring for you. What would you change to improve the solution?

Resources

]]>
http://swifting.io/blog/2016/05/16/15-nested-enums-or-rather-never-ending-posts-about-enums/feed/ 0
#14 Code Review – Tips & Swifts http://swifting.io/blog/2016/04/24/14-code-review-tips-swifts/ http://swifting.io/blog/2016/04/24/14-code-review-tips-swifts/#comments Sun, 24 Apr 2016 21:20:22 +0000 http://swifting.io/?p=368 Last week, in issue #13, we introduced a definition of Code Review. Today we’ll get deeper into the topic, present some tips & swifts & tricks when performing a review and focus on some mistakes found when reviewing a 🐦Swift code.

General Tips 🔍

It is said that a review goes best when conducted on less than 400 lines of code at a time. You should do a proper and slow review, however, don’t spend on it more than 90 minutes 🕑 – you definitely will get tired after that time. It’s tiring to write and understand your own code and it’s even more tiring to understand someone’s. Other tips from the Internet are:

After some years of experience in software development you know what common programming mistakes are. You also do realise what solutions to common problems are most efficient. It’s a good practice to write it down and to check code being reviewed against a checklist ✅ – it leads improved results. Checklists are especially important for reviewers because, if the author forgets a task, the reviewer is likely to miss it too.

In the git flow mentioned in issue #13, code can get merged after receiving agreed number of approvals for a pull request. The number should depend on your team size, but it’s good to get at least 1️⃣ !😀

When you recommend fixes to the code, suggest their importance 💬. Maybe some of them could be postponed and extracted as separate tasks. Before approving a pull request, verify that defects are fixed 🔧🔨.

Foster in your company a Good Code Review Culture in which finding defects is viewed positively 😀. The point of software code review is to eliminate as many defects as possible, regardless of who "caused" the error. Few things feel better than getting praise from a peer. Reward developers for growth and effort. Offer as many positive comments as possible. I always try to put a line saying that a solution is good and clever (if it really is 😉).

You can also benefit from The Ego Effect 💎. The Ego Effect drives developers to write better code because they know that others will be looking at their code and their metrics. No one wants to be known as the guy who makes all those junior-level mistakes. The Ego Effect drives developers to review their own work carefully before passing it on to others.

And don’t bother with code formatting style …

… there are much better things on which to spend your time, than arguing ☔️ over the placement of white spaces.

Looking for bugs and performance issues is the primary goal and is where the majority of your time should be spent.

So, what to review?

Much better things to look for should be a part of your checklist. When I scrutinise a piece of code I look especially:

  • at if conditions, for and while loops for "off-by-one" errors
  • for interchanged < versus <= and > versus >=
  • for accidental interchange of && with || or bitwise operators like & and | UPDATED 11.06.2016 Swift compiler ensures that expression evaluated in a condition returns a Bool value, hence there’s no possibility not to catch compilation error if one interchanges operators
  • at operators importance and execution UPDATED 11.06.2016 If you happen a "million" of operators in one expression you’re probably doing something wrong by overcomplicating the solution… 😉
  • if dependancy injection is possible (for the sake of unit testing).
  • if variable names as verbose as needed
  • if method names express what they do
  • if a file contains commented out code
  • if a file contains a single class (this one is arguable, depends on agreement with your team and company’s guidelines)
  • for code duplication, function length and class length < x lines – SwiftLint or codebeat mentioned in issue #11 and issue #10 is an option to point out such a code without your participation

When performing a review, one can also get extra points 💎 for pointing out a more efficient implementation of used algorithm 😉.

You should also check for readability. Is the code easy to understand? Do you have to pause frequently during the review to decipher it?

Some 🐦swifts

Boom! Time for some loosely coupled Swift code examples that I look for when reviewing Swift code❗️Wait a moment, this exclamation mark looks strangely familiar … ❗️Look out for code that uses it …
Swift
var foo: Object!
print("\(foo.someString)")

Make sure that your peers (and you as well) use the force unwrapping operator wisely in their code.

If you have ever ended up with code like the one below, then probably something went wrong … 💣💥

override init(_ objectId: String?, 
viewModel1: ViewModel1, 
viewModel2: ViewModel2, 
viewModel3: ViewModel3, 
viewModel4: ViewModel4, 
viewModel5: ViewModel5, 
viewModel6: ViewModel6, 
viewModel7: ViewModel7, 
viewModel8: ViewModel8, 
viewModel9: ViewModel9, 
viewModel10: ViewModel10,
isSomething: Bool = false) { ... }

This is an excerpt from from one of my projects, object types and names are changed . It’s an initialiser of a ‘container’ view model that encapsulates ‘child’ view models used by a container view controller. If you happen to achieve this and there’s no way to change it, probably usage of a configurator facade, default argument values or convenience initialisers are the best solution to live up with your legacy.

class Configurator {
    class func mainViewController() -> MainViewController {
        let dependency1 = Configurator.dependency1()
        let dependency2 = Configurator.dependency2()
        let dependency3 = Configurator.dependency3()
        let dependency4 = Configurator.dependency4()

        return MainViewController(dependency1: dependency1,
            dependency2: dependency2,
            dependency3: dependency3,
            dependency4: dependency4)
    }
}

The off-by-one errors and interchanged greater than & less than were my favourite mistakes at some point of time. I’ve caught myself a few times last year with using if i > array.count instead of if i < array.count ☔️.

Remember local autoreleasepool? For those who answered ‘what!?’ here is some explanation. I pay attention when reviewing body of a loop to check if local autoreleasepool could be used to reduce peak memory footprint.

for i in 1...100
autoreleasepool {
    NSString *superImportantString = "Super \(i)"
    //strange operations take place
    //superImportantString can be released earlier thanks to local autoreleasepool
}

More than a year ago, when Swift was still in its early days, I hated when my team members overused var. It’s ok when needed, but not all the time! Thanks god that now Swift compiler warns about not mutated var.

Another matter is your object’s properties. If it depends on some values, never ever use var. Use let. Always value more immutable state over var! I wonder how many people would argue with me about that☔️😉. And if your property really have to be mutable, expose it ‘to the public’ as immutable like that:

private(set) var foo: AnyObject
let bar: AnyObject

Swift’s protocols are a great deal – do you prefer composition over inheritance? Is such an inheritance chain ok for you? One superclass would be probably ok, but this becomes an exaggeration:

class ChildViewModel: TableViewModel {}
class TableViewModel: CRUDViewModel {}
class CRUDViewModel: BaseViewModel {}
class BaseViewModel {}

Final thoughts

Kofi Annan, Ghanaian ex-Secretary-General of the United Nations, when in primary school, was attending a weekly lesson in ‘spoken English’. He and his peers were asked by the teacher what did they see at the picture:


All shouted together, that they saw a black dot! Professor stepped back and said ‘So, not a single one saw the white sheet of paper. (…). This is the awful thing about human nature. People never see the goodness of things, and the broader picture. (…)’.

It’s also true for code review. We perceive better differences than loads of new code when using a merge tool. We get a cognitive overload if flooded with more content. Have that in mind and use the first rule – review for less than 90 minutes 🕑, take breaks. Remember that:

  • new code is more difficult to understand
  • not all bugs can be caught during a review
  • hot fixes 🔩 without review can happen … 😉

And always – Review your own code first! Before committing a code look through all changes you have made!


Let us know in comments or on Twitter what is on your checklists for code review!

The only true measure of code quality


]]>
http://swifting.io/blog/2016/04/24/14-code-review-tips-swifts/feed/ 1
#13 Code Review – are we too busy to improve? http://swifting.io/blog/2016/04/18/13-code-review-are-we-too-busy-to-improve/ http://swifting.io/blog/2016/04/18/13-code-review-are-we-too-busy-to-improve/#comments Mon, 18 Apr 2016 07:38:37 +0000 http://swifting.io/?p=363 Issue #10 has had a very good perception by the community. For this reason we will blog about code quality topics from time to time. Today we’d like to discuss code review process, challenges one may encounter when introducing it in their workplace and what to consider when reviewing one’s source code.

What is a code review?

The good old Wikipedia once wrote:

Code review is systematic examination (often known as peer review) of computer source code.

It is intended to find and fix mistakes overlooked in the initial development phase,  

improving both the overall quality of software and the developers' skills.

Far enough. I want to do it! 💥Wait, but …

How to do it?

Reviews can be done in various forms such as pair programming, informal walkthroughs, and formal inspections. The most known is probably this one – show me your code (aka informal review)! Simply ask your peer to have a look at your code.


Formal code reviews can be performed by using e.g. Atlassian’s Crucible/Fisheye (I don’t like this tool, bad UX, hard to navigate and even start a review) or a pull request on Stash/BitBucket/GitHub or whatever you use. Thanks to those tools you get a nice visualisation of what changes were made to source code, you can comment on them, ask author some questions and they can explain their code in return. It’s like a conversation you would have in real life, but documented – what has been agreed should be performed before merging into develop. Wait, what merging?! We were just talking about a review …

Git flow

When developing different parts of an application at work we use Git and Git Flow to merge all changes into a parent branch. Once a feature of an app is finished we create a pull request that contains changes to be added to a predecessor branch (usually develop). The best picture showing the flow comes, in my opinion, from GitHub. I still don’t get what the squirrel on it represents… ⁉️


The flow goes like this:

  • create a branch from e.g. develop
  • apply your changes to the source code
  • create a pull request to be merged into e.g. develop
  • discuss changes with your peers, explain your point of view & apply suggested improvements
  • a squirrel⁉️ approves your changes (or your peers, depends on the setup of your team and agreements, could be a squirrel in some cases … 😉)
  • merge your code into source branch

What to consider when doing a review?

You definitely should check code integrity – does the style match previous solutions, does it follow agreed conventions? Are features implemented correctly, does the old source code work correctly after changes?

Why to tap into code review in your development process?

For sure because it ensures code integrity 😀, catches what others’ eyes didn’t see. It allows to learn and share your knowledge and expertise, strengthens communication in the team and builds good relationships due to conversations about what you have in common – code and programming skills ;)!

Unfortunately, from my experience, unit tests and code review are first things that get removed from project scope 😢. It takes too much time and there’s no budget for that. Do you encounter the same problems?

Consider code review as an investment into the future. If you don’t catch bugs now you will definitely have to conquer them in the future.

What if you didn’t perform code reviews

Imagine a company X. It delivers mobile app solutions for multiple clients. Their team is small and at some point they cannot meet clients’ demands. So they decide to outsource some of the work to an external company. They give project requirements to this company and meet again after 3 months to receive app source code. But the app is useless – it freezes at network calls, CoreData.ConcurrencyDebug flag crashes all the time. The project is delayed for a few months, team has to start from a scratch. The wish they had reviewed outsourced code on a daily basis…

How to start the process at your place?

Code review culture wasn’t common for mobile teams at my workplace. It still isn’t for some of the due to rapid development and short lifecycle of some of the mobile apps. However, I wanted to improve myself by learning from others. I’ve started with a prank. I’ve developed changes on a branch and have created a pull request for my colleagues. And it got the ball rolling. Now all mobile projects within my division embed code review in their development process.

Do you want to perform code reviews?

This is usually the question that gets lack of enthusiasm from the audience :(. But really, are we too busy to improve??


This was an introduction to code review. In the upcoming weeks we’ll get deeper into the process. Stay tuned 📻😀!

]]>
http://swifting.io/blog/2016/04/18/13-code-review-are-we-too-busy-to-improve/feed/ 2