Quality – swifting.io http://swifting.io Sharing passion in Swift Tue, 25 Jun 2019 07:51:48 +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 Quality – swifting.io http://swifting.io 32 32 #52 XP – Speaking the same language http://swifting.io/blog/2019/06/18/52-xp-speaking-the-same-language/ http://swifting.io/blog/2019/06/18/52-xp-speaking-the-same-language/#respond Tue, 18 Jun 2019 19:28:22 +0000 http://swifting.io/?p=1080 我不说你说的语言

A few months ago I finished my 17 months long stay in Singapore. It was an amazing time during which I met brilliant people, sweated a lot in tropical weather and worked on a messaging application for iOS.

The company I worked for used eXtreme Programming methodologies for software development. We used XP every business day for 8 hours. Because of that TDD became a habit, lack of companion when programming became a burden, and the legacy code became no fear to me. Let me tell you why XP is useful and why pair programming is helpful when working on a project.

eXtreme Programming

We live in times in which everything changes rapidly. Not longer than 5 years ago (June 2014) majority of production code for iOS apps was written in Objective-C only, whereas today many companies try to minimise Objective-C code in favour of Swift. Not only technology and tools we use evolve and change, but also business requirements for our apps. Companies that can adapt to changing conditions and can develop quality software in an agile way can survive and ship valuable products.

Extreme programming (XP) is a methodology for creating software of high quality in a responsive way to changing requirements. It values a set of good practices and pushes using them to their limits:

  • Unit tests are great, they verify that app components behave in a desired way. XP uses TDD approach – tests are written before production code.
  • Integration & Deployment can be done manually – code is tested and build locally on our computer and archived to be deployed to Appstore. With XP it is done automatically and continuously on integration servers after every push to the repository.
  • Code review catches bugs and improves the design and quality of our code. XP pushes it to extremes too – pair programming is used to conduct continuous code review.

Pair programming = 2 people doing one person’s job

I heard about this wrong perception that pair programming is 2 people doing one person’s job. What actually is pair programming?

Setup

Graphic - workstation with 2 screens, 2 mice and 2 keyboards
Graphic – workstation with 2 screens, 2 mice and 2 keyboards

Two people in front of 2 screens, 2 keyboards and 2 mice connected to a single computer working on the same thing. Pair programming is mainly a discussion about how to solve a certain problem. It leads to coming up with a better design and doing it right the first time. Pair members get instant feedback on their ideas thanks to the continuous conversation about the task at hand and its implementation.

Getting quality fast

Have you ever had this feeling that it takes ages to merge your PR (Pull Request) to the main development branch? You implement your new functionality, push changes to a remote branch, create a PR and then you wait… and wait… and finally somebody reviews your changes, leaves some comments. You apply them to your work, and then you wait for feedback again… With continues code review a.k.a. pair programming you get feedback right away. It’s a faster way of working and getting better quality of code. You can push directly to the master because the code you worked on with your pair is considered reviewed. Of course, crucial parts can still go through PR if you need another opinion. Be agile and change approach if needed 🙃!

Ramping up and spreading knowledge

We had these new guys joining our development team. If they had to dive into our legacy codebase solo, they wouldn’t have become effective quickly. Pairing allowed them to ramp up fast. The project’s legacy codebase was extremely complicated, old and lacking unit tests for crucial parts. When they worked with experienced peers they could learn about the project from them. Good practices were spread right away and a knowledge about the project was shared on the job.

Some new teammates didn’t have experience in Objective-C, nor in TDD. If you learnt Objective-C you know how difficult it probably was for you at the beginning and how different it is from Swift. If you practice TDD, you understand that it demands perseverance and skill in unit testing. Our teammates could learn from the experience of other peers thanks to pair programming.

It would be great if knowledge of application components was distributed evenly, i.e. every team member would feel comfortable and capable of working on any part of the app. You can achieve that by rotating pairs. At every daily standup, people would tell what they planned to work on. Then peers agree on what and whom they want to work with. And hey – not every task makes sense to be done in pair programming mode 😉.

Pair rotation teaches the skill of adaptation to new tasks easily. One person from the initial pair working on the task stays with it till it’s finished and the other person can step back from the task and work with someone else on another task. It also spreads the knowledge and gives fresh look and opinion on solutions when new people joined to pair with you.

Distraction free

Nowadays it’s extremely easy to get distracted. Phone buzzing with notifications, e-mail needs to be answered, new blog post on “XYZ” needs to be read. After an hour you can find yourself still not having started the work…

While you’re pairing, you’re actively involved in the task. You discuss the code and you don’t answer sms or watch YouTube.

A few days ago I was thinking through how to solve a certain problem in the application. Then my colleague waved at me and ask some question about the app. I needed to navigate to a different part of the project and talk about it for a while. When we finished I needed a few minutes to get back on track…

When programmers are pairing people see that they are actively involved in their work. People will wait for the appropriate moment to approach them to discuss things through. What’s also great about pairing is that when somebody approaches the pair one member can handle the interruption while another will stay focused and work on the task.

Rewarding way to work

Pair programming is just fun and rewarding way to work. You have a mutual goal and pursue with your pair to achieve it. This pursuit is accompanied with a lot of laughter and it allows you to get to know your colleagues more and to make this special connection with them.

Glimpse of an eye

When you do pair programming you never end up in situations when people start arguing about who will use the keyboard. Of course you have two sets of them, but usually only one is used at a time. Pair agrees on the way they want to work. It can be that one person writes the test and the other implements the code. It can be communicated verbally that one wants to write code – “Hey, let me do it!” 😉.

But there is more than that. When you practice pair programming constantly for some period you start understanding non-verbal communication.

When you type on a keyboard and you notice by a glimpse of an eye a subtle movement of your peer’s hand approaching their keyboard, you immediately know that it means that they want to start typing and to introduce their concepts so you can react to this non-verbal language right away. You understand your pair with no words.

Speaking the same language

Sometimes even if we speak the same language we don’t understand each other. Language can mean many aspects – Objective-C/Swift, Polish/English, body language, language of shared experienced.

I spent 17 months where Chinese is one of spoken languages and my friends taught me some of it:

我不说你说的语言

Wǒ bù shuō nǐ shuō de yǔyán in Chinese means I don’t speak the same language that you speak.

Pair programming allowed me to learn non-verbal language, to understand people coming from different backgrounds and cultures. It allowed me to “speakthe same language, share my experience and learn a lot from others.

Summary

I can’t sum up pair programming by not quoting my previous manager. It’s just a rewarding way to work. You have a lot of fun while working with others. It’s an exciting adventure which gives new experience. With pair programming you get better code and higher quality much faster than in a standard approach to software development.

pair programming
wait ages for PR review instant feedback
slow solo discover fast developer ramp up
distraction threat focus on the job

TL;DR;

If you want go fast, go alone.
If you want to go further, go together.

African proverb

Links

]]>
http://swifting.io/blog/2019/06/18/52-xp-speaking-the-same-language/feed/ 0
#50 Synchronous Unit Tests http://swifting.io/blog/2018/03/03/50-synchronous-unit-tests/ http://swifting.io/blog/2018/03/03/50-synchronous-unit-tests/#comments Sat, 03 Mar 2018 07:37:21 +0000 http://swifting.io/?p=1017 Asynchronous Expectations

Mobile applications are usually multi-threaded. We perform UI operations on the main thread and dispatch heavy tasks (e.g. network requests, JSON parsing, writing to a file on a disk) on background threads. The iOS allows us to use backgrounds threads for example by using Grand Central Dispatch API (GCD), i.e. by performing operations on DispatchQueue objects. Work dispatched to a background DispatchQueue is usually done asynchronously with queue.async{} call.

If we wanted to test an object that uses a queue to perform work in background, we would use an XCTestExpectation and wait for an async operation to finish. We can fulfil the expectation in a callback.

func testCompletionGetsAtLeast1Message() {

    //Arrange
    let laoder = MessageLoader()
    let expectation = XCTestExpectation(description: "should call completion handler with at least 1 message")

    //Act
    laoder.load { messages in
        //Assert
        XCTAssertFalse(messages.isEmpty)
        expectation.fulfill()
    }
    
    wait(for: [expectation], timeout: 5)
}

In autumn I asked on Twitter about the best way to wait for an XCTestExpectation. The interface of XCTestCase class declares a few methods:

I didn’t get a clear answer, but the reply gave food for thought…

Asynchronous drawbacks

Unclear AAA pattern

It’s a good practice to divide test into 3 phases:
Arrange – setup a subject under test, set it in the desired state
Act – perform an action on the subject
Assert – test if a desired behaviour or change happened

In an asynchronous test the phases aren’t clearly visible. How would you name the last phase? A Wait phase?

func testCompletionGetsAtLeast1Message() {

    //Arrange
    let laoder = MessageLoader()
    let expectation = XCTestExpectation(description: "should call completion handler with at least 1 message")

    //Act
    laoder.load { messages in
        //Assert
        XCTAssertFalse(messages.isEmpty)
        expectation.fulfill()
    }
    
    //???
    wait(for: [expectation], timeout: 5)
}

Overhead

In the code snippet above we wait 5 seconds for the expectation. It means that our unit test can take up to 5 seconds in the worst case scenario (i.e. if execution of load(:) method took more that 5 seconds). XCTest framework would fail the test after 5 seconds of waiting.

wait(for: [expectation], timeout: 5)

Waiting for 5 seconds for a unit test seems too much… Even 1 second seems! Imagine we had 1200 unit tests with asynchronous expectations fulfilment and because of some mistake in our code all of them fail. The framework needs to wait for each of them for 1s. Math is like that:

1s * 1200 tests = 1200s = 20min

We would have to wait 20 minutes for results of our unit test suite execution. Feels like eternity… Even Swift apps compile faster nowadays… 😉

wait(for: [expectation], timeout: 0.1)

Typically the waiting time should be set to 100ms. But even 100ms is a bit too much. In the case of failing tests we would have to wait for 2 minutes…

100ms * 1200 tests = 120s = 2 minutes

No control

But the main drawback is that we have NO CONTROL over DispatchQueue.main singleton used. We don’t know how much time the execution of our code will take. But we can regain the control. How? By running code synchronously!

Synchronous Assertions

Let’s assume we have a MessageLoader class that performs some operations on a background DispatchQueue:

class MessageLoader {
    let queue: DispatchQueue
    
    init(queue: DispatchQueue) {
        self.queue = queue
    }
    
    func load(_ completion: @escaping ([Message])->Void) {
        queue.async {
                        var messages: [Message] = []
                        //NOTE: fetches messages in background
                        completion(messages)
        }
    }
}

In this approach we cannot test in other way than using an XCTestExpectation that completion closure gets called after our function finishes doing stuff.

We can create a Dispatching protocol that declares a single method – dispatch(:).

protocol Dispatching {
    func dispatch(_ work: @escaping ()->Void)
}

Let’s create a Dispatcher class that gets initialised with a queue. It will serve as a superclass for other dispatchers.

class Dispatcher {
    let queue: DispatchQueue
    
    init(queue: DispatchQueue) {
        self.queue = queue
    }
}

We can hide async dispatch of a job to a DispatchQueue by creating an async dispatcher – let’s call it AsyncQueue. The class conforms to our Dispatching protocol and performs action asynchronously on a queue that an instance is initialised with.

class AsyncQueue: Dispatcher {} //inheritance gives an initialiser with a queue

extension AsyncQueue: Dispatching {
    func dispatch(_ work: @escaping ()->Void) {
        queue.async(execute: work) //IMPORTANT!
    }
}

We can also create a SyncQueue that would dispatch a job synchronously on a queue.

class SyncQueue: Dispatcher {} //inheritance gives an initialiser with a queue

extension SyncQueue: Dispatching {
    func dispatch(_ work: @escaping ()->Void) {
        queue.sync(execute: work) //IMPORTANT!
    }
}

Ok, but what is this all for? We wanted to test synchronously! So we need to upgrade our MessageLoader to use the Dispatching queue to perform a job.

class MessageLoader {
    let queue: Dispatching
    
    init(queue: Dispatching) {
        self.queue = queue
    }
    
    func load(_ callback: @escaping([Message]) -> Void) {
        queue.dispatch { //NEW!
            var messages: [Message] = []
            //TODO: fetch messages in background
            completion(messages)
        }
    }
}

Instead of using sync or async method on a DispatchQueue we call dispatch on our Dispatching type. How to test synchronously that completion closure gets called? We just need to initialise MessageLoader with a SyncQueue.

Before that, let’s create some queues just like DispatchQueue gives access to commonly used queues:

extension SyncQueue {
    static let main: SyncQueue = SyncQueue(queue: .main)
    static let global: SyncQueue = SyncQueue(queue: .global())
    static let background: SyncQueue = SyncQueue(queue: .global(qos: .background))
}

extension AsyncQueue {
    static let main: AsyncQueue = AsyncQueue(queue: .main)
    static let global: AsyncQueue = AsyncQueue(queue: .global())
    static let background: AsyncQueue = AsyncQueue(queue: .global(qos: .background))
}

Let’s write a unit test for our completion closure being called. We need to initialise MessageLoader with a background queue on which jobs are dispatched synchronously. Imagine we are writing a messaging app. Our product manager gave us a task to welcome a user with a “hello” message even if there are no other messages.

let welcome = Message(author: "The App", text: "Welcome in the app!")

So we need to assert that we have at least one message in the array given as an argument to the completion handler. We can create an array outside a completion closure and assign a value to it in the completion.

func testAtLeast1MessageOnLoad() {

    //Arrange
    var messages: [Message] = []
    let background = SyncQueue.background
    let loader = MessageLoader()
    loader.queue = background
               
    //Act
    loader.load { fetched in
        messages = fetched
    }
    
    //Assert
    XCTAssertFalse(messages.isEmpty)
}

Thanks to the synchronous nature of this testing approach we also benefit from it by enhancing test readability. We have clearly visible Arrange, Act and Assert phases.

TL;DR;(1) – making things clear

We don’t have to use the XCTestExpectation because our code executes synchronously with SyncQueue. Unit test is run on the main thread and then load(:) executes it’s job synchronously on a background thread. The sync dispatch means, that the calling thread waits until execution of the job dispatched on a background thread finishes.

Beware of the 🐕 deadlock!

OK, let’s refactor. Or make things more difficult… But look out for a deadlock!

Imagine we have a loader that dispatches work on a background queue but calls completion closure on the main queue. If we used DispatchQueue objects our code would look like this:

func load(_ completion: @escaping ([Message])->Void) {
    
    DispatchQueue.global().async {
        //fetch messages on a background thread
        
        DispatchQueue.main.async {
            completion([ ]) //on the main thread
        }
        
    }
 }

Again, as in previous example, we can use the Dispatching protocol to hide a use of a DispatchQueue.

class MessageLoader {
    let main: Dispatching
    let background: Dispatching
    
    init(main: Dispatching, background: Dispatching) {
        self.main = main
        self.background = background
    }
    
    func load(_ callback: @escaping([Message]) -> Void) {
    
        background.dispatch { //NEW!
            
            var messages = [ Message.welcome ]    
                    
            //TODO: fetch messages in background
            
            self.main.dispatch { //NEW!
                callback(messages)
            }
        }
    }
}

If we wanted to test that completion closure gets called and we didn’t pay attention to what queue we dispatch jobs during a unit test we might end up with a deadlock.

What is the deadlock? In a multi-threaded application it occurs when a thread enters a waiting state because a requested system resource is held by another waiting thread.

We want to test our new loader with a simple test that calls load(:) method on MessageLoader instance. We initialise our loader with SyncQueue.main and SyncQueue.background objects that perform work synchronously on the main queue and on a background queue respectively.

func testAtLeast1MessageOnLoad() {

    //Arrange
    var messages: [Message] = []
    let loader = MessageLoader(main: SyncQueue.main,
                               background: SyncQueue.background)
               
    //Act
    loader.load { fetched in
        messages = fetched
    }
    
    //Assert
    XCTAssertFalse(messages.isEmpty)
}

Just to remind you – unit test is run on the main thread and then load(:) executes it’s job synchronously on a background thread. When the job on the background thread finishes the method dispatches work synchronously to the main thread to call completion closure. Do you see an issue with this approach?

A synchronous dispatch means that a dispatching thread waits for a work to be finished on a thread it dispatches the job to. In the load(:) we dispatch work synchronously from the main thread to a background thread and then we perform another synchronous dispatch to the main thread. Because the previous synchronous dispatch is not finished and we try to do another synchronous dispatch to the same queue we end up with a deadlock.

How can we fix that? We need to use a different queue than main, e.g. SyncQueue.global 😉.

let loader = MessageLoader(main: SyncQueue.global,
                               background: SyncQueue.background)

And now we use threads as following and no deadlock occurs:

Summary a.k.a TL;DR;(2)

Asynchronous tests are unreadable, might give an overhead to test execution and we don’t have full control over them.

Using a protocol to “hide” dispatching jobs to different threads allows running tests synchronously. It gives us FULL CONTROL over unit tests execution and prevents us from waiting for too long in the case of their failure. We can also clearly see the Arrange, Act and Assert phases of a unit test.

You can check our sample code on GitHub.

Special thanks to Paweł Dudek for a review!

Links

]]>
http://swifting.io/blog/2018/03/03/50-synchronous-unit-tests/feed/ 2
#42 Review all the things! http://swifting.io/blog/2017/05/17/42-review-all-the-things/ http://swifting.io/blog/2017/05/17/42-review-all-the-things/#respond Wed, 17 May 2017 11:46:42 +0000 http://swifting.io/?p=942 Today we’d like to share a talk presented on May 14th at the UIKonf conference in Berlin.

The world has gone crazy. It has made us extremely busy nowadays. Product owners want us to write code fast, to ship new features even faster. Because of that we don’t have time for self-improvement.

We are programmers that may be great in their craft, that may write top notch source code, but we are also – humans. We make mistakes, all the time. We also want to become better people, better engineers. But how can we do that? Why should we review our work?

You know, I have a vision, where unit testing and code review are a standard, not an opt-in feature in iOS development. I’ve been fighting a lot to introduce them at my workplace. Let me tell you what things get reviewed in other industries and why it is so. Join the talk if you want to start code review practices at your company, but you don’t know how to kick it off.

]]>
http://swifting.io/blog/2017/05/17/42-review-all-the-things/feed/ 0
#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
#30 Cyclomaticly Complex Settings View Controller http://swifting.io/blog/2016/12/11/30-cyclomaticly-complex-settings-view-controller/ http://swifting.io/blog/2016/12/11/30-cyclomaticly-complex-settings-view-controller/#respond Sun, 11 Dec 2016 19:00:41 +0000 http://swifting.io/?p=720 Simple screens evolve

In every project simple screens can happen. Let’s think for example of a simple Settings screen. Customer wanted a Settings screen on which a user would be able to Set Option 1 and 2 and to Logout from the application. It seemed so simple so developers used a UITableView with 1 section, hard-coded text displayed in cell and actions invoked directly from tableView(didSelectRowAtIndexPath:).

But it was ok, after all it was just three options, no big deal. When a few weeks passed by, customer came back and decided that the user has to be able to set another two options in the app and that all non-related options should be visually separated. So developers added those options and separated non-related ones by using multiple sections in a UITableView with .grouped style.


But developers used this long switch statement in many methods that dealt with tableView. They also had been using SwiftLint (a tool for code quality mentioned in issue #11 and issue #26) that indicated that their cyclomatic complexity limits for those methods were overreached.


Wait! Cyclo-what?!

Cyclomatic complexity

Documentation for codebeat (another tool for code quality assurance) mentioned by us in issue #10 has a great explanation of what cyclomatic complexity is:

The cyclomatic complexity of a section of source code is the number of linearly independent paths within it. For instance, if the source code contained no control flow statements (conditionals or decision points), such as if statements, the complexity would be 1, since there is only a single path through the code. If the code had one single-condition if statement, there would be two paths through the code: one where the if statement evaluates to true and another one where it evaluates to false, so complexity would be 2 for a single if statement with a single condition. Two nested single-condition ifs, or one if with two conditions, would produce a cyclomatic complexity of 4. (…)

OK, now when we know what cyclomatic complexity is, we can see some code and resolve its problems!

Cyclomaticly Complex Settings View Controller

So in the end, developers ended up with tableView(:cellForRowAtIndexPath:) method implementation that looked like this:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
        let section = indexPath.section
        let row = indexPath.row
        switch (section, row) {
        case (0, 0):
            cell.textLabel?.text = .SetOption1
            cell.accessoryType = .disclosureIndicator
        case (1, 0):
            cell.textLabel?.text = .SetOption2
            cell.accessoryType = .disclosureIndicator
        case (2, 0):
            cell.textLabel?.text = .SetOption3
            cell.accessoryType = .disclosureIndicator
        case (3, 0):
            cell.textLabel?.text = .SetOption4
            cell.accessoryType = .disclosureIndicator
        case (4, 0):
            cell.textLabel?.text = .Logout
        case (4, 1):
            cell.textLabel?.text = .LogoutAndResetData
        case (4, 2):
            cell.textLabel?.text = .LogoutAndRemoveAccount
        default:
            fatalError("Wrong number of sections")
        }
        return cell
    }

Their UITableView had 5 sections, 4 of them contained only 1 row and navigated to a different screen, 1 of them had 3 rows with different option to logout from the app.

The developers had set rigid cyclomatic complexity rule that will invoke a warning when the rule reaches 5 possible paths of execution through the method.

SettingsViewController.swift:58:5: warning: Cyclomatic Complexity Violation: Function should have complexity 4 or less: currently complexity equals 8 (cyclomatic_complexity)

SettingsViewController.swift:90:5: warning: Cyclomatic Complexity Violation: Function should have complexity 4 or less: currently complexity equals 8 (cyclomatic_complexity)

There is also tableView(:didSelectRowAtIndexPath:) method with high complexity. You can check this example project to see full source code.

Cyclomaticly Simple Settings View Controller

OK, but how can we design source code to resolve complexity issues?

This one simple trick can clean up our code and simplify complex methods. We can use a ViewModel struct to represent cell’s looks and behaviour.

fileprivate struct ViewModel {
    let name: String
    let indicator: UITableViewCellAccessoryType
    let action: () -> Void
}

For the Settings View Controller, the struct contains a name and an accessory indicator to be displayed in a cell. It also stores an action to be performed when user taps the cell. For first row in Settings View Controller we would write such a code:

ViewModel(name: .SetOption1, indicator: .disclosureIndicator, action: 
    { [unowned self] in 
        self.push(SetOption1ViewController()) 
})

Since method called in action closure is defined in Settings View Controller (self), there is a problem. First of all, a capture list has to be used. Secondly, we cannot construct let viewModel: [[ViewModel]] property before initialization of superclass, because the closure uses self.

To solve that problem, the property can be declared as fileprivate var viewModel: [[ViewModel]] = [] and filled with appropriate data after init of a superclass or in viewDidLoad() method:

fileprivate func setupViewModel() {
        viewModel = [
            [ViewModel(name: .SetOption1, indicator: .disclosureIndicator,
                       action: { [unowned self] in self.push(SetOption1ViewController()) })],
            [ViewModel(name: .SetOption2, indicator: .disclosureIndicator,
                       action: { [unowned self] in self.push(SetOption2ViewController()) })],
            [ViewModel(name: .SetOption3, indicator: .disclosureIndicator,
                       action: { [unowned self] in self.push(SetOption3ViewController()) })],
            [ViewModel(name: .SetOption4, indicator: .disclosureIndicator,
                       action: { [unowned self] in self.push(SetOption4ViewController()) })],
            [ViewModel(name: .Logout, indicator: .none,
                       action: { [unowned self] in self.showLogoutPrompt() }),
             ViewModel(name: .LogoutAndResetData, indicator: .none,
                       action: { [unowned self] in self.showLogoutAndResetDataPrompt() }),
             ViewModel(name: .LogoutAndRemoveAccount, indicator: .none,
                       action: { [unowned self] in self.showLogoutAndRemoveAccountPrompt() })],
        ]
    }

Now implementation of tableView(:cellForRowAtIndexPath:) is as simple as that:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
    let section = indexPath.section
    let row = indexPath.row
    guard let model = viewModel[safe: section]?[safe: row] else { return cell }
    cell.textLabel?.text = model.name
    cell.accessoryType = model.indicator
    return cell
}

You can find full sample project here.

TL;DR;

Simple screens with naive implementation can grow fast through time and turn into complexity burden. It’s good to have a code quality guard to warn you by saying Fix it!. If you don’t have a clue how to fix an issue, ask your colleagues, switch your thinking from switch statement to some abstraction, watch Swift Talks and read blog posts to be more creative in problem solving!

References

]]>
http://swifting.io/blog/2016/12/11/30-cyclomaticly-complex-settings-view-controller/feed/ 0
#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
#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
#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
#11 SwiftLint http://swifting.io/blog/2016/03/29/11-swiftlint/ http://swifting.io/blog/2016/03/29/11-swiftlint/#comments Tue, 29 Mar 2016 16:44:19 +0000 http://swifting.io/?p=348 Should the opening brace of a function or control flow statement be on a new line or not ?:) This and many other questions cross my mind when I think about coding style. I love the comment from Ray Wenderlich’s Swift style guide:

"You like braces on new lines @elephantronic ? This will strain our friendship!" …hehe, so it really does matter!:)

But coming back to the main subject: This year one of the items on my to do list is a task to learn more about static code analysis tools: linters, Sonar and everything else that can fight against bad smells. In our previous post Maciej mentioned more about code quality and about Codebeat. Today I would like to concentrate on SwitLint, which can help us keep cohesion in our code without straining friendships in our project team:)

SwiftLint checks the source code for programmatic as well as stylistic errors. This is most helpful in identifying some common and uncommon mistakes that are made during coding. SwiftLint is based on guidelines from Swift style guide. Simply saying it can just helps us with:

  • maintaining a higher level of code discipline,

  • increasing the reliability of the code.

Installation

  • using brew:

$ brew install swiftlint

  • or by downloading and installing a fresh release.

Necessary after installation check version using command swiftlint version and compare it to the latest version available on website.

Running

We have two options:

  • just type the following command in the Terminal:

$ swiftlint lint

  • or we can integrate SwiftLint with Xcode:
RunScript
RunScript

Just for the test I have run SwiftLint with default options in my current project and I wish I had been using it from the beginning of the project 😅 :

SwiftLintRun
SwiftLintRun

SwiftLint Rules

All available rules which you can use are here.

If you want to have a possibility to control which rule is disabled/enabled and to set thresholds for warnings and errors for a given rule, just create a .swiftlint.yml file in your project directory:

swiftlintYML
swiftlintYML

You can download the example configuration file from here.

Now by typing in the Terminal swiftlint rules you can check your settings:

SwiftLintRules
SwiftLintRules

Running Options

Sometimes running options can be very useful. Let’s focus on them:

  • -- path The path to the file or directory. For example if you want to lint only one file:

$ swiftlint autocorrect --path just_this_file.swift

  • -- config The path to SwiftLint’s configuration file .swiftlint.yml:

$ swiftlint lint --config .swiftlint.yml

  • -- use-script-input-files read SCRIPT_INPUT_FILE* environment variables as files. When using this parameter can be useful? For example when we only would like to lint modified files and new files tracked in our github repository. Example of usage which I found here:

if which swiftlint >/dev/null; then
    count=0
    for file_path in $(git ls-files -om --exclude-from=.gitignore | grep ".swift$"); do
        export SCRIPT_INPUT_FILE_$count=$file_path
        count=$((count + 1))
    done
    for file_path in $(git diff --cached --name-only | grep ".swift$"); do
        export SCRIPT_INPUT_FILE_$count=$file_path
        count=$((count + 1))
    done
    
    export SCRIPT_INPUT_FILE_COUNT=$count

    swiftlint lint --use-script-input-files
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

- git ls-files: outputs the filenames in working directory
- o: (others: Show other (i.e. untracked) files in the output) 
- m: (modified) Show modified files in the output
- exclude-from=.gitignore: it omits ignored files 
- grep ".swift$" : search only .swift files

  • -- quiet flag that prevents status messages like ‘Linting ‘ & ‘Done linting’ from being logged.

  • -- reporter generates report with selected format: JSON, Checkstyle, CSV, Xcode. For example:

$ swiftlint lint --reporter json

{
    "reason" : "Opening braces should be preceded by a single space and on the same line as the declaration.",
    "character" : 23,
    "file" : "../ViewController.swift",
    "rule_id" : "opening_brace",
    "line" : 50,
    "severity" : "Warning",
    "type" : "Opening Brace Spacing"
  },
  ...

Autocorrect

Very nice feature of SwiftLint is the auto-correction swiftlint autocorrect, which can automatically fix violations in your code. What type of violations can we fix?

  • Closing brace. Closing brace with closing parenthesis should not have any whitespaces in the middle:
closingBrace
closingBrace
  • Colon. Colons should be next to the identifier when specifying a type:
colonRule
colonRule
  • Comma Spacing. There should be no space before and one after any comma:
commaRule
commaRule
  • Legacy Constant. Struct-scoped constants are preferred over legacy global constants:
legacy_constant

Very nice article explaining the why.

  • Legacy Constructor. Swift constructors are preferred over legacy convenience functions:
legacy_constructor
  • Opening Brace Spacing. Opening braces should be preceded by a single space and on the same line as the declaration:
opening_brace
  • Statement Position. Else and catch should be on the same line, one space after the previous declaration:
statement_position
  • Trailing Newline. Files should have a single trailing newline:
trailing_newline
  • Trailing Semicolon. Lines should not have trailing semicolons:
trailing_semicolon
  • Trailing Whitespace. Lines should not have trailing whitespace:
trailing_whitespace

Cyclomatic Complexity

In SwiftLint you can find very nice rules, for example:

  • File length rule: Files should not span too many lines.
  • Function Parameter Count: Number of function parameters should be low.
  • Type Body Length: Type bodies should not span too many lines.
  • Type Name Rule: Type name should only contain alphanumeric characters, start with an uppercase character and span between 3 and 40 characters in length.

But when I first looked at the rules list my attention was captured by the Cyclomatic Complexity rule. What is this? Wiki says:

"is a software metric (measurement), used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program’s source code."

This parameter just says how complex our functions are. To many ifs are not recommended. If you add 3rd nested if, you should wait a moment and reconsider your solution. This is my weakness, because sometimes I propose really overcomplicated solutions for quite easy problems: it can always be done much simpler… great rule for using by me:) How to add this bodyguard to your config file? Just add it on the end on .swiftlint.yml:

cyclomatic_complexity:
  warning: 2 # two nested ifs are acceptable
  error: 5   # six nested ifs shows warning, 6 causes compile error

Summary

I think that the use of such a tool from the start of the project can be very useful. By setting up together configuration file with considering parameters for each rule, you can be sure that everyone will have to use the same style and for sure it will decrease the amount of bad smells.

For sure I will user this tool in my next project! Hope to hear about your experience with using SwiftLint or similar tools!:) I can’t wait for your comments!

Don’t forget to visit also:

]]>
http://swifting.io/blog/2016/03/29/11-swiftlint/feed/ 5