You’ve made the decision to build your own iOS app. The app is being built to meet specific customer needs. If that’s all clear in your mind, you are at a point where you want to start thinking about iOS software architecture.

Software architecture is the term developers use to describe how major components of an app work together. Modern software structure and design are usually too complex for one person to easily think about all at once. So we use architecture as an abstraction, drawing parallels to traditional architecture, where software has inherited ideas of design patterns and user-centered design. In practice, software architecture means the parts of the app you need to get right.

Well-planned architecture for your iOS app starts with investing lots of time in planning and pays off over time. If you start early, you can create a clear, shared understanding between you and your developers around your app’s architecture. If you do it well, you save lots of time and money over the lifecycle of your app.

Patterns and Practices for Scalable Apps - YouTube

Tap to unmute

Patterns and Practices for Scalable Apps BrightDigit

BrightDigit845 subscribers

In this article, I cover three essential concepts for good iOS software architecture:

  • Patterns and Practices
  • Code Modularization
  • Code Quality

I’ll be explain a bit about each and how to implement them correctly in your app.

iOS Software Architecture Patterns

Choosing a certain architecture for your iOS app determines the design of different aspects of its software. Within that, you’ll also figure out what kind of design patterns you will want to use. A software pattern is essentially a common response to a recurring problem.

Patterns are particularly useful when working with a large team of developers. They can make your developers substantially more efficient at solving problems. It also guides new developers on how to add features to an app. Patterns ensure changes to the code are consistent and reduce risk when making major changes.

Good use of architecture patterns make it easy for developers to understand the software. If it’s easy for them to understand, it’s easier for them to make changes. This means new features can be delivered faster, with fewer bugs and simpler fixes.

There are a few architectural patterns that are very useful when making iOS apps:

Protocol-Oriented Programming

This is a fundamental pattern for developing any app written in Swift (i.e. all native apps on any Apple platform). Protocols allow you to group functionality and define how your data and objects work together. This pattern is sometimes referred to different names, most popularly Interface and Contract or Design By Contract.

Protocols are useful for creating functionality in your app while making the lives of your developers easier. Instead of building a whole new object you can define protocols for new developers to implement. This makes it really easy to reuse objects throughout your code. Protocols also make it easy to separate your app’s behavior from its data, usually referred to as separation of concerns.

Finally, designing your app around protocols makes it easy to test the different parts of your app for the purposes of Test-Driven Development, which I cover below.

Reactive Programming in iOS Software Architecture

This pattern has become popular since the introduction of SwiftUI, which encourages developers to use both functional and reactive programming. Similar to functional programming, reactive programming is the concept of designing your app around events. An event is anything where an input of data triggers a routine within your app. This could be a keystroke from the user, a signal from a connected device such as a sensor, or an alert generated by the software itself.

Apple introduced the Combine framework in 2019 and the Observation framework in 2023 to help iOS developers with reactive programming. These allow you to modify and update values as they come in within your UI. Additionally, these can be used with Model-View-ViewModel (MVVM), which removes the Controller in the MVC pattern mentioned above. WithMVVM, the Controller is replaced with a ViewModel. The ViewModel automates how the Model can be rendered directly into the View by making changes to the Model data and reacting accordingly. This is particularly useful for iOS apps that need to use a resource library that isn’t written in Swift. It allows you to bridge from another programming language into Swift.

Modularizing in Xcode with Abbey Jackson - Audio player

Empower AppsTrailerBonusEpisode 23Season 1

Modularizing in Xcode with Abbey Jackson

Modularizing in Xcode with Abbey JacksonModularizing in Xcode with Abbey Jackson

101X30

00:0052:43

Visit Transistor.fm - Podcast Hosting and Analytics

More episodes

  1. Modularizing in Xcode with Abbey Jackson

53 min

Subscribe

Copied to clipboard

Share

ShareCopied to clipboard

EmbedCopied to clipboard

Start at

Empower AppsTrailerBonusEpisode 23Season 1

Modularizing in Xcode with Abbey Jackson

September 29, 2019Leo Dion, Principal CEO and Swift Developer at BrightDigit Full TranscriptView the website

Guest

Sponsors

BrightDigit

  • Specialize in helping businesses build apps for iPhone, iPad, Mac and Apple Watch
  • 10 years of experience developing for a variety of Apple platform
  • Helping dev shops which lack experience with Apple platforms and Swift

Contact me if you need help today.

We have an opening for sponsors

  • Do you have a product or service which can target our ever growing community of developers as well as technology and business leaders?

Contact me today if you are interested in sponsoring or go to our Patreon page.

Themes from Conferences

  • The Importance with Meeting New People
  • Learning Old Features
  • Trying to Deep Dive into SwiftUI and its Future
  • The Benefits of SwiftUI for Designers
  • Comparing HTML and SwiftUI

Breaking Down How Xcode Works

  • How Different Components in Xcode Can Help Organize Your Code
  • How an Xcode Project Works
  • How Files result in Targets
  • Differences between Targets and Build Configuration
  • Dealing with Target Dependencies
  • Testing with Targets and Xcode
  • How Workspaces Differ from Projects

Modularizing Components

  • What are the best ways to organize your product?
  • Modularizing Your Persistence Layer
  • Importance of TDD and Protocol Oriented Programming
  • Other examples of modularizing: Network, Feature-cased, Authentication, User Profile, Location
  • Following Apple's SDK Framework Example

Dealing with Source Control

  • Using Git Submodules
  • Dependency Management Tools (i.e. SPM, Cocoapods, Carthage)
  • Using SDK Targets
  • Swift Package Manager

The Benefits of Modularizing

  • Decrease Build Times
  • Share Code and Functionality
  • Optimize Your Build Pipelines

Post-September Purchasing Choices

  • Apple Watch Series 5
  • iTunes vs App Store Gift Cards
  • iMac Backpack

Social Media

Twitter - @brightdigit

Facebook - BrightDigit

LinkedIn - BrightDigit

Instagram - @brightdigit

Patreon - empowerappshow

Thanks to our monthly supporters

  • Steven Lipton

★ Support this podcast on Patreon ★

Chapters

Delegation and MVC with iOS Software Architecture

Delegation is an older pattern inherited from Objective-C and UIKit which we use in iOS user interface (UI) development for displaying information in an app. Model-View Controller (MVC) uses Delegation and is historically the most used iOS software architecture pattern for developing Apple apps. With the rise of SwiftUI though, delegation is beginning to decline in popularity. This is how it works:

  1. A user performs an action within the user interface (i.e. View).
  2. View passes it to the Controller.
  3. The Controller makes decisions about what to do with the action it's been given. If needed, it makes changes to the state of the Model, which will change its data values in response.
  4. The Controller then sees these new values and sets them for View, showing them to the user.

Delegation allows you to control how the Controller provides both the data and the way that data needs to be displayed to View in the final step. This makes it easy to break apart the functionality of the code to display information to your user the way you want.

Why Code Modularity Matters in iOS Software Architecture

Another key component of great architecture is modularity.

Modularity is the idea that different parts of your app should be able to work independently of each other. This makes it easier to both test and reuse pieces of code in different parts of your app. It also makes it easy to use the same piece of code for different platforms, so your iOS code can work on any Apple platform.

There are three ways I recommend for creating modularity in iOS app development:

Framework Targets

In Xcode (the development environment for macOS), Framework Targets are a way to easily move your app’s code from the testing environment where it was built to the production environment your users can see. Ordinarily, you have to swap out all the URLs and APIs from the testing version of your app to the production one. With Framework Targets, this is done automatically.

Projects and Workspaces

You have a specific piece of code that doesn’t fit into an existing framework but might be used in many apps. The way to deal with this is to have more than one project and workspace. This allows you to organize pieces of code and show how they are related to different development projects.

Swift Packages

The newest and simplest way to achieve modularity. Apple is encouraging a shift toward using only Swift for new apps. This means Packages is essentially the default for creating modularity for iOS apps. If you’re interested in learning how to use Continuous Integration with your Swift Packages, check out our developer article here.

If you’re interested in learning more, check out my more in-depth article on micro apps and code modularity.

Test-Driven Development with Joshua Greene and Michael Katz - Audio player

Empower AppsTrailerBonusEpisode 15Season 1

Test-Driven Development with Joshua Greene and Michael Katz

Test-Driven Development with Joshua Greene and Michael KatzTest-Driven Development with Joshua Greene and Michael Katz

101X30

00:0047:04

Visit Transistor.fm - Podcast Hosting and Analytics

More episodes

  1. Test-Driven Development with Joshua Greene and Michael Katz

48 min

Subscribe

Copied to clipboard

Share

ShareCopied to clipboard

EmbedCopied to clipboard

Start at

Empower AppsTrailerBonusEpisode 15Season 1

Test-Driven Development with Joshua Greene and Michael Katz

June 16, 2019Leo Dion, Principal CEO and Swift Developer at BrightDigit Full TranscriptView the website

Guests

Book - iOS Test Driven Development

Links

Previous Episodes

Show Notes

The Components of Test-Driven Development

  • Keep Your Iterations Small
  • Test First
  • Circular Progress of Testing and Developing Functionality
  • Avoid Testing other APIs (i.e. Integration Testing)
  • Use Mock Data for Outside Dependencies
  • Behavioral Driven Development vs XCTest

How to Encourage TDD in Your Team and Company

  • Make sure Maintainability and Specs are Met
  • Prevent Regressions with New Features
  • Regular Code Reviews
  • Tests Should Be Required Before Deployment
  • Encourage a Culture of Testing
  • Slow Add Tests to Projects Missing Them

Common Mistakes When Doing Test Driven Development

  • Following the Golden Path and not testing edge cases and errors
  • Following Test Coverage too strictly or not enough
  • Use Multiple Test Targets
  • Write Tests First

For Experimenting with New APIs

  • Use Spike Solutions to Experiment
  • Write Temporary Tests
  • Use Playground to Test Code

Continuous Integration Tools

  • Jenkins
  • Travis-CI
  • CircleCI
  • Xcode Server
  • Fastlane

WWDC and TDD

  • New Performance Tests
  • Test Plan for Xcode
  • SwiftUI, Live Previews, and Modeling

WWDC 2019 - Testing in Xcode

Social Media

Twitter - @brightdigit Facebook - BrightDigit

Brand New Instagram! - @brightdigit

Full Transcription

Leo Dion (Host): So hey guys, how's it going?

[00:00:01] Michael Katz (Guest): Great. How are you?

[00:00:02] Leo Dion (Host): Good good, just been trying to catch up with WWDC. What's your general thoughts so far.

[00:00:07] Michael Katz (Guest): It seems like this is about the biggest one we've had since they introduced Swift. There's just so much stuff.

[00:00:12] Leo Dion (Host): Yeah, that's exactly what I was thinking especially with the UI changes. So have you started investing money to buy a $1000 stand?

[00:00:20] Michael Katz (Guest): Yeah, I wish. Fortunately at my company, we actually do video editing. We have editing bays already have racks of Mac Pros. So I assume that those will get upgraded with the new machines at the fancy monitor so I can go downstairs and drool over them when I'm not actually. It's working on my MacBook.

[00:00:36] Leo Dion (Host): Yeah, I mean that's the thing about these devices. They're not for developers like there for video editing like massive 3d rendering that kind of stuff and big production companies

[00:00:45] Joshua Greene (Guest): Maybe if you're doing like 3D games or something as a developer. I could see it being really worthwhile but for business or Enterprise type apps it may be a little bit of an overkill which is definitely pretty awesome. But day to day maybe not so much.

[00:00:59] Leo Dion (Host): Yeah, exactly. So if people want to tweet at us or we're also at brightdigit on Twitter at brightdigit on Instagram and Facebook. Let us know your thoughts on WWDC and any thoughts you might have about all the new stuff that's coming  out.

[00:01:15] Guys, so apparently you have a book coming out pretty soon. Is that correct? So go ahead and introduce yourselves to let me know a little bit about this book.

[00:01:24] Joshua Greene (Guest): So my name is Joshua Greene. I am a longtime author for RayWenderlich.com

[00:01:30] I've done everything from creating tutorials to books to videos. This is a new project that we're putting together to teach test-driven development it's called iOS Test-Driven Development by Tutorials

[00:01:45] Michael Katz (Guest): And I'm Michael Katz and similar story. I've been with Ray Wenderlich for a number of years and also done books tutorials.

[00:01:53] Spoke at the RW Devcon. Haven't done any screen cast yet, but maybe someday and they are passionate about test-driven development and we both came I think independently to the idea of writing a testing book and editor-in-chief put us together. And here we are most of the way through it.

[00:02:11] Just getting ready to finally finish it up.

[00:02:13] Leo Dion (Host): So test-driven development, I remember once it was like almost more than half decade ago, probably almost 10 years ago, I went to a conference in Chicago and I think it was Bob Martin who gave a talk on test-driven development the idea being like first you write your test and then you write your code.

[00:02:33] Is that kind of the gist of it or what are the components of test-driven development? What exactly does that mean?

[00:02:39] Joshua Greene (Guest): Yeah, definitely writing tests first is definitely a big part of it. Keeping iterations small. I think test-driven development is all about, you know, writing one small thing you write a small test to implement something that you need to get implemented.

[00:02:54] You show the test actually doesn't pass you implement. Whatever code is required to get it the pass and then you verify it passes. And you just repeat this process over and over so that when you finally, you know, got your app out not only have you got all the features written you've got all of the tests that you're going to need alongside it but it's not like you just write all the tests in advance. It's literally a small step by a small step is kind of what makes it different and special.

[00:03:20] Michael Katz (Guest): It's a circle you just go over and over again at a little test and yet add some code to fix that test and you test the next piece and you add the code for that and so on so you're always in lockstep.

[00:03:31] Leo Dion (Host): So the problem I have had with test-driven development and iOS is some of the stuff that is pertaining to like the UI or perhaps like test-driven development, sometimes you have different screen sizes, obviously, you might have to deal with something like core data or networking. How do you overcome those challenges when you're trying to do test-driven development?

[00:03:57] Michael Katz (Guest): I think we think about using TDD. Is that it really forces you to think about what your code is doing? And so if you want to make sure that your code is testable and you're starting out with no code. You're going to write your code in a way that is so if you have a dependency on something external to the system like a database or an API or screen, you'll want to write your code, you know, where you have a model. For instance any test the models all the business logic and the data logic and so on and then you can add the UI on top of that and then use a different type of testing like UI tests to handle making sure that the UI is correct, but that way you're certain that your business logic and state is consistent and complete before you even get there.

[00:04:36] Joshua Greene (Guest): With TDD, even if you're following TDD from the get-go there. It Is not to say that you have to test everything per say. For example, if you're going to be caught by another their way like at the compiler is going to throw an error if you actually hit an error while you're doing TDD that counts as a failed test

[00:04:54] with the UI portion, I typically look at it as if it's something I can configure in interface Builder, I don't, you know, not necessarily going to test that too heavy in terms of TDD because it's something I can see on screen and might mention there's other tests that I can use if I really want to put test in place for UI testing and so.

[00:05:14] TDD is really about you know, structuring your code in such a way that it is testable putting in protocols instead of talking directly to a database for like Mike says, you know talking to models that are structured in such a way that you can actually put test where you get the biggest bang for your buck as far as testing goes.

[00:05:30] Leo Dion (Host): So it sounds to me like we're talking here about kind of this is similar exactly to what we talked about in our last episode. When we talked about architecture and the fact that you need to architect your app around models, and it sounds like you're basically talking about what specially when it comes to Swift, you know, doing protocol oriented programming and using mocks in your testing as opposed to directly connecting with things like user interface or your database or your network. Is that what I'm hearing?

[00:06:00] Michael Katz (Guest): Exactly? In the book. I have a chapter where we're building at a fitness app and instead of connecting to Core Motion we basically build a protocol around it so we can Mock and stub data and act as if these things were happening live, but they're actually just being faked by the tests.

[00:06:17] And that's the type of thing you would use for a pretty much any kind of Hardware or network or UI that you can do in your code. So we separate the logic and the pieces that are about the app that are unique from the things that are handled by the operating system.

[00:06:29] Leo Dion (Host): Yeah, that's awesome. And I think that's one of the things I really like about TDD is that not only is it a great way to make sure your code actually works in all cases but it also encourages healthy architecture in the end because you're allowing for different things to be plugged in like I need a fake core motion or health kit or core data or whatever. I can fake it in my test so that way when I test the actual application like you said those are different tests, they're not tdd necessarily.

[00:07:01] Michael Katz (Guest): It's particularly true when you're testing error condition. So if you have a logic in your code that handles detecting when a call is dropped and then when you reconnect to restart something in this kind of hard to test especially in a CI situation where you're building and testing your app on a server that's plugged into gigabit Ethernet.

[00:07:20] So by using TDD enrollment you've already separated out that networking layer. So you can just Supply errors and different combinations and ordering of conditions to test out that your app is going to handle those appropriately even if they're very difficult to test it manually.

[00:07:34] Joshua Greene (Guest): Even if you're starting from a point where it so you don't have a completely new application.

[00:07:39] It's not to say that you can you know, not introduced EDD later on, you know, a lot of these same principles of you want to talk through something else. Even if you directly coupled yourself to talking to a networking calls or to core data or whatever, you know external API is. You're talking to that directly.

[00:07:57] You can break those dependencies and you know move your architecture in the right way, even after the app is already, you know launched or had a few versions out. We actually have some chapters in the book that go into details about taking a legacy based app and moving it towards TDD. So. I'd say that tdd is a great start if you're just kicking off an app, but even if you're not you can still use and consider TDD just you know in sure you're writing those tests first and again, you know, just making sure that you've got the correct coverage and bang for the buck as far as testing goes.

[00:08:28] Michael Katz (Guest): Yeah, you can start writing test at any time in this way. So even if you have an app and even if you have tests that you've written sort of after the fact to validate your behavior when you write new code you can start doing TDD at any point.

[00:08:40] Leo Dion (Host): So what are some challenges that people typically face when it comes to developing like in Xcode for iOS that's different from say like your typical vue.js developer or PHP or python?

[00:08:57] Do you guys typically use the standard packages like the XC test stuff that comes with xcode and iOS, or do you use your own custom packages for mocking or what are some challenges that you've seen people face specifically in iOS.

[00:09:12] Michael Katz (Guest): I  think Xcode default is he test case is a little bit cumbersome is very much based on the old Xunit or Junit type testing which is gosh has to be 20 years old at this point. Yeah. I think it's out of the 90s where it was a long time ago.

[00:09:28] Leo Dion (Host): It was a long time ago.

[00:09:29] Michael Katz (Guest): So my company we actually use a form of what we call behavioral driven testing. So it's more descriptive. We use of Frameworks called Quick and Nimble. Which is a layer on top of XC test, so you still run the test and xcode and you get the same reports out that you do but it's a different API and XCtest so it makes it you know easier to read the test understand but it also because it's a layer on top is slower than using actually test, directly so it's the trade-off there.

[00:09:59] Joshua Greene (Guest): I'm gonna have to disagree with you a little bit my in that I would say - yes Quick and Nimble is fantastic as far as making things more descriptive and so forth. But to me like it's more syntactical flavoring if you will then it is a strict requirement

[00:10:14] XCTest very much so used to be you had to have something in addition to it. You had to have some way to do like asynchronous testing the very first version of XCTest didn't really even provide a way to set up any sort of expectations. I'd say today though, if you really want to and a lot of my day-to-day stuff, I typically unless there's a strong reason why I like you're saying unless I need to do it and some sort of behavior descriptive way that I want to actually set upfront i don't necessarily opt for going to something else always just from the get-go. You can very much so use XCTest right out of the box and it is testing completes - well as complete as you can get with Swift and really having true mock support, but you can basically do everything with XCTest that you can do with Quick and Nimble.

[00:10:59] It's just like you said, maybe it's a little bit more verbose or maybe there's a little bit that you might do differently versus some of these BDD type Frameworks that give you some nice syntax.

[00:11:10] Leo Dion (Host): I've worked with like mocha for like nodejs and some JavaScript stuff. I think that's behavioral driven, but it sounds to me like Quick and Nimble gives you that like syntactical sugar in a good way to like explain what each test actually does.

[00:11:25] Where as XCTest doesn't give you that but it does give you the basic logic and API for doing just logical tests. Which is more or less what TDD is really driving at. Is that correct?

[00:11:37] Joshua Greene (Guest): Yeah, I'd say the XCTest doesn't give you the naming syntaxes or so forth or you know, like the nice thing about BDD and really the main difference, you know, but on the other end of the things I'm close to the plain vanilla here than Mike it sounds like.

[00:11:49] The nice thing about the BDD Frameworks like Quick and Nimble is it will provide you the ability to say okay here's a descriptive string describing what I'm actually trying to test here. You can do the same thing using method signatures and that's actually what we show in the book there.

[00:12:03] [That] is if you named your test correctly, you know describing what you're doing describing what is actually being tested in the expected outcome. You can get a lot of the same benefits from the just a vanilla XCTest. But like Mike said it's you know more so by naming conventions that you set up less so directly supported by XCTest itself.

[00:12:23] Leo Dion (Host): So I want to jump a little bit more into TDD and talk about some of the terminology and some of the stuff that's involved. So, we talked a little bit about like mocking what exactly is mocking and what's it used for when it comes to test driven development. If there's any other terms, I'm forgetting that are components of test driven development let me know.

[00:12:45] Michael Katz (Guest): Yeah, so. When you're running tests, there's a whole Suite of objects that are commonly called test doubles where basically you have an object. That's just for testing that parallels production code [or] main app code.

[00:13:03] So a mock is an object that behaves like the code. So for instance you have like a mock network connection or like an nsurl session. And if you supply a command to that like low data, your mock is responsible for handing back some set of fake data that you supplied to the test knows ahead of time what's going to happen and it's going to succeed or not with mocks in particular it is to verify that certain methods or behaviors happen along with that. So if you call we go back to the mock data URL idea that you would verify that the data was returned correctly or if an error was made if you set it to make an error that the error callback gets called and so on. You can also verify that certain methods are only called once or twice.

[00:13:49] So if you have a tertiary object further down so that when you save an object to a database you want to make sure that you're not saving that same thing twice so there's no duplication in the code. You can verify that using a mock by adding methods to count the number of times a method is called and so on. I 'm not sure that was clear but maybe Josh can help here.

[00:14:06] Joshua Greene (Guest): I agree with what you're saying there Mike the only sort of difference in my mind as far as Mocks vs. a test double there. A test double may not provide like verification that behavior like you verify that a sort of method was called.

[00:14:22] It may just accept those methods and just fill in as a dummy, you know, the simplest way to make just like a test double in my mind would be you know subclass something out or conform to a protocol and then implement nothing. And those are basically the two options that you have in Swift is you either implement a protocol to create a mock and then you can you know, just pass that to either be an initializer or you know setting it as a property.

[00:14:46] Or you can subclass something else and again, you know pass it in but one way or another you have to be able to insert yourself in this hierarchy of getting these calls. When creating a mock there we're actually validating whatever happens happens in you know, maybe the correct order or maybe it's that it happens the correct count whatever you're trying to actually accomplish at the time there we're not just filling, you know, just a dummy requirement.

[00:15:10] But with that said, sometimes we could create a mock it may be that the initializer requires you to have some sort of other object, but you don't really care you're going to intercept calls and inbetween you might just create something. That's just an empty object. And that's what I call like a test double dummy to me.

[00:15:25] So I guess in a way my point is the mocks are a special type of test double that provides verification.

[00:15:31] Leo Dion (Host): So basically like for instance, I have a protocol or a mock of what a network called would be guy just like create a mock that pretends to do the call and then have like a Boolean property says like is called and just set it to true and then that way I can verify that that network call has been made.

[00:15:48] Is that kind of what we're talking about?

[00:15:50] Joshua Greene (Guest): Yeah, then the simplest thing would be holding onto a boolean and just saying that it was actually called. But you know, especially networking. You're likely going to need to return something. Right?

[00:16:01] Leo Dion (Host): Right exactly. So then you return some sort of like mock data based on that network call of some sort.

[00:16:07] Joshua Greene (Guest): Exactly and with the mocks or that test double is you could actually have like with a real networking API you got to go hit a server. It's going to take however long to connect to that get data parse it return it that you've got the full stack there right. Versus with the mock you can immediately like asynchronously pass something back or if you want to turn it in for you know, take it from an asynchronous to synchronous call.

[00:16:29] You can do that with the mark. So you eliminate having to talk to anything real then actually using a mock. It makes your test much much more faster and much more consistent as far as what you expect to happen. Given certain criteria, you can set up the criteria.

[00:16:44] Michael Katz (Guest): Yeah, absolutely.

[00:16:45] Leo Dion (Host): Are there any libraries or Frameworks that you would recommend to help create those mocks or do you just pretty much implement whatever protocol is going to pretend to do like networking or database or whatever it is?

[00:16:58] Joshua Greene (Guest): For me, I guess the sort of nicety that Objective-C had but Swift is actively moving away from this is the ability to actually have mocked that are true mocks and that you say all right i want to mock this object and it magically happens for you using things like OC mock was a very popular framework that allows you to do this in Objective C.

[00:17:20] This isn't possible in Swift, because the Swift team actively wants to move things from the runtime to compile time and for production code that makes a lot of sense because anything that you can move to compile time, you can catch an error at compile time you throw an error it doesn't build, you know, the developer has to fix that.

[00:17:38] If something gets all the way through runtime, you likely have a runtime crash. So they're really trying to get rid of those runtime crashes. Unfortunately, that makes it basically impossible to do what OC mock was doing with just pure Swift because there's nothing to you know, put yourself in between as far as a runtime that you can actually intercept messages there.

[00:17:57] Instead, you basically only have two choices you either conform to a protocol and implement all the methods there or you take whatever real object is and subclass that and just override whatever behavior such as you know, what you're talking about maybe you capture a boolean instead of whatever the superclass - the real object would have been doing.

[00:18:17] Now with that said you could definitely do those by hand. You have no choice as far as doing this at compile time. You have to compile something so you can write it by hand or there are a few niceties out there like Sourcery for example is a nice tool that allows you to write code. Do it if I hear you say here's a template that I want to use anytime that I see this protocol, you know, that may be conformed some auto-generating or something Sourcery can write that for you.

[00:18:42] So one way or another it has to be compiled time, but there are tools out there to help with some of you know, the harder bits of that or the annoying bits or boiler plate bits.

[00:18:50] Leo Dion (Host): I've just started playing around with Sourcery. Sourcery is amazing what you could do with it. Yeah. Usually what I end up doing is just implementing that protocol in creating my own mock in the test Library.

[00:19:00] That's essentially what I do because like you said you Don't have that ability that Dynamic runtime ability to just like create something on the fly like you can with Objective C.

[00:19:10] So what are some other tips or tricks you have when it comes to like TDD besides mocking trying to think if there's anything else that I think is a major component when it comes to TDD but mocking is a big one and if you have a healthy architecture then I think you're good with mocking.

[00:19:29] I guess we'll jump into like what are some ways you can encourage TDD in your team like what are some ways that like somebody who was higher up like a CTO or a manager can make sure that we're getting the tests that we need and that code is actually being tested and  written in a way that it is testable.

[00:19:50] Michael Katz (Guest): There are two things especially if you're talking to a CTO that they like to hear is that maintainability and scalability and making sure that you have a complete working set of tests allows the team to be more efficient and add features faster in the future.

[00:20:05] So. You know that you can add something without worrying that you're going to break existing behavior, especially as the app gets more complicated over time we want to make sure that as people come and go in the organization or just as you forget because you're doing a million different things that there's some requirement that doesn't get lost because it was never really written down in a spec somewhere but there's a test for it

[00:20:26] Joshua Greene (Guest): Yep, definitely maintainability is a win factor if you will as far as not having test versus having test. Also, prevention of regressions, you know Mike is kind of get up there to if you don't have any tests not only is it something that it may be that nobody on the team understands how it is because tests form documentation and maybe that later on you introduce bugs that you fixed in V1 yeah, that's a sad thing to actually see.

[00:20:53] The wins though are definitely those lines. As far as how to get your team to do it though. I'd say first and foremost, especially if a team of any sort of no more than just a couple developers you should be promoting code reviews and in the code reviews if I you know, see somebody on my team and they put out a code review that doesn't have any unit tests I'm immediately rejecting it and it has to have tests in order to even be considered to get into production.

[00:21:21] How do you know if it works without tests? So there is sort of a you know, a philosophy of you must do testing, but you can obviously write unit tests without following TDD. I'd say as far as if you want to get your team to do tdd and you know bring up this test first mentality and get the benefits that TDD. Provides with, you know you write tests for as you're going to get better coverage and typically things will be designed any more testable way versus trying to do that after the fact I'd say the first and foremost your team needs to know how to do it.

[00:21:52] If your team doesn't know test-driven development or know and just have any experience in that area. It's hard to say go and do test-driven development with that said, you know Mike and I you know part of the reason for writing this book was we looked at the community and said, you know iOS community knows about unit testing knows, you know about these things to some extent but we don't think there is a strong grasp for how TDD works. So that was a strong part of why we're actually putting this book together.

[00:22:20] So I'd say check out, you know things like art book check out the raywenderlich.com for you know, where you can go to get these materials to help get your team up to speed but you know, once they're up to speed keep the bar high make sure that there's something in place like code reviews to make sure that it's actually happening

[00:22:35] Michael Katz (Guest): When I've rolled it out on teams, usually what I do is I write a feature in with the team there so that we can serve like a pair programming or four-person five-person programming to see the process and go through it because it can be a little strange if you're not used to doing it a little slow in the first few days until you get the hang but once you do it, it's just like, you know the second nature because it's just this iterative step.

[00:22:59] So having someone that can can walk through and hold hands a little bit also makes it easy to make that transition. I also have a culture of testing that really wants this and is willing to allow developers the ability to take it on.

[00:23:13] Joshua Greene (Guest): I'd say as far as things that prevented him from going to this especially if the apps been around forever. If you've got an app and it's got you know several hundred or thousands or more classes in it just saying, all right, you've got to do this cycle where you build and compile every 30 seconds or are you know faster than that. It may take several minutes to compile the full app let alone run all the tests, right?

[00:23:36] You do have to do this in a way where one thing we are actually going to release a chapter on this in the book even is that you need design not only the core app in a way that it can be testable but there's nothing wrong with actually saying you can pull out a module and so you've got a feature that's implemented just in a module and all of the code for what it's doing is within that module any sort of externalities to its using this third party API or maybe even a different piece of your core application you can put a protocol in between.

[00:24:05] So breaking things up in a way that okay. Here's this small bit here. That's a modulo a different piece that you accomplished has a different goal or something else. That's a different module. So you go from this huge monolithic app to alright a set of libraries or frameworks, whatever you're often used based on your use cases that can be compiled to really quickly - you can run the test against them really quickly and you know can be changed pretty much independently without affecting the rest of the code base. That's fantastic. That's the you know, code that isn't tightly coupled anymore. It's Loosely coupled to the rest of the system. It's testable. It's something that can scale, you know as much as you need it to.

[00:24:42] Michael Katz (Guest): One of the things that was a game-changer for me and doing this with a existing large app was just accepting that it was okay to do TDD for just a new code and any file that was their existing did not go through that level of rigor and acceptance as it is and then in the book also we described how to like slowly add tests for the things that were there before so you can mix and match TDD even though what works best in doing it, you know straight up fresh you can add it into your process slowly and not have to to write, you know, three thousands tests before you can start writing that code because usually you're under some deadline to get something out there.

[00:25:22] Leo Dion (Host): Yeah. I think that's a big part about introducing anything new to a project. I'm thinking about it this week with SwiftUI like when they introduce Swift at you shouldn't go in and rewrite your whole project to be in Swift. If it's an Objective-C. You shouldn't, you know rip out every storyboard and convert everything to SwiftUI for a thousand reasons and I think just with tdd like you shouldn't just go in and start writing tests for all of your existing code.

[00:25:46] Like I think it's just easier to slowly introduce it as you write new features and naturally over time. It will develop that like, most of your code will end up being test driven in the end.

[00:25:56] Joshua Greene (Guest): Definitely, you don't need to just jump into here and go right to the deep end. You can start by just adding it like Mike said for new code only or identify hey, here's this core part of the app. We really need to make sure that this works or we need to make some changes around this. How can we make sure we're not going to break in the process? There's nothing that says you can't put in test place there. As you need them and identify them you don't have to go back and just add I actually be against this at my teens come and said we want to introduce TDD.

[00:26:26] I'm going to add tests throughout the app for I can chip it in new features. No, that's not a good thing to do. It's probably going to be something that you're going to waste time with that. So adding them slowly over time, especially for the very big apps may actually be not only the best choice, but maybe the only choice if you actually want to, you know, continue moving forward with delivering and, you know creating new features at the same time.

[00:26:48] Leo Dion (Host): So what are some other mistakes you think either with teams that are getting started with test-driven development or just teams that are doing thinking that they're doing test-driven development but actually, they're not. What are some common mistakes that teams and developers make when they're doing TDD.

[00:27:04] Michael Katz (Guest): So I think you know one of the mistakes is only covering the happy path or golden path through the code. So you want to make sure that you're testing the edge cases and different combinations of parameters. And if you find that your function has, you know, 4200, you know different combinations of input and that's kind of a code smell there. It may be an indication to break things up into smaller pieces.

[00:27:30] Leo Dion (Host): How do you create enough test data so that you know, you're testing as many cases as possible. Like let's say you have a function that takes in addition like does addition does that mean that I need to test every addition problem possible? What would be a great way to like break that down?

[00:27:45] Michael Katz (Guest): With math, you've got your basic, you know, making sure that you have you cover zeros in a negative values values at the max, you know max float, max int those type of things when you're doing it. Those are probably more academic. I think most apps are in the putting JSON into a table sort.

[00:28:03] So for their you know, your bounds or more, you know, did you get back an empty array to have text you know for a field that's 6 megabytes when you're expecting just a sentence, you know those type of things. It's probably a good thing. I get help somewhere. That's like common things to look out for for that.

[00:28:21] If you have code like an if statement or branch or you know, I do catch those are pretty good indicators that you should have a test at least covers that so you can use the test coverage as a way of least making sure that you've executing the code.

[00:28:34] Leo Dion (Host): Yeah. That's what it sounds like is like you're basically talking about test coverage which if I understand correctly is like basically making sure that every line of code. Xcode does it actually I don't know about you guys but it seems to do a decent job as far as the test coverage instrumentation. But like it'll actually tell you if you've covered every if branch and or switch case in every line of code and it gives you a percentage that's seems pretty reasonable.

[00:28:59] Michael Katz (Guest): Yeah, and that's a good start. It won't cover the out-of-bounds issues or overflows underflows the errors with formatting and things like that because you're still running that code so you can. End of what the function is trying to do as well, but it just covers a good way to start.

[00:29:14] The tricky thing we've run into with test coverage those we have multiple test targets and [with] Xcode I haven't found a good way to sort of sum up the coverage across multiple test targets and maybe the new test plans handles that.

[00:29:27] Leo Dion (Host): What do you mean by test targets just briefly?

[00:29:30] Michael Katz (Guest): So just like you can have multiple targets you can build Frameworks within a project, multiple apps. You can build multiple test targets so you can group your tests based upon you can have test that just cover networking or databases or test the cover each framework and a test suite and in your scheme, you can specify that when you run the test action which test targets get run and so we've broken up our app into many different libraries and each library has its own test target so we can either run all the suites or if we're just modifying code and one of the Frameworks we just run the tests when you're doing a local development.

[00:30:07] Joshua Greene (Guest): That's a good reason to you know, as far as why coverage isn't the end-all be-all story. So it may not be you know, especially in Mike's case there because he has the multiple targets. It isn't actually a true story in that they could be that you've got two targets and they've each got 50%/50% do you have a hundred percent coverage?

[00:30:25] Is there any overlap between the two of them? It's difficult to say right? So I'd say another sort of common errors, especially as far as management goes is you know giving too much emphasis to test coverage. Test coverage should be something you look at, you know, if you have zero percent versus 80% Obviously I'm going to say oh 80% is probably covering more than you know, the closer you get to the zero, but it's not the most important metric if you said as a manager I'm going to say a hundred percent of you know, the code must be covered by tests. I don't think that's a good goal.

[00:30:58] You know, it doesn't tell you actually, you know very much for what that is. All it indicates is a particular line of code was executed. You know, was it executed with the right inputs?

[00:31:07] Was it executed with all the edge cases? Like Mike is talking about. I don't know. So my point is use it as a starting point. But that's not the only thing you should consider you got to look at, you know are the cases that are the edge cases are the normal flows are all you know, all of the entire picture is what you should actually be considering

[00:31:26] The nice thing about doing tdd, by the way instead of instead of writing these after the fact and adding the unit test on after you've got all the if else has or switches or whatever your code is. Tdd says in order to add new functionality after I did the test first. So, TDD for the most part is going to be more likely to get you in a case where you've covered all of these edge cases. Now in certain times, especially with things like the out of bounds, you might miss something right and you might miss you know, here's this one weird edge case we didn't think about and you know, we accidentally wrote code that either car forms correctly that's a win or you know misses this thing without actually having to test in place. That's okay even after you do TDD or you know, you have test if you identify you're missing a test add a test. Nothing that says you can always go back and you know add more where you need. But you know knowing up front you got most of everything. That's what tdd, you know provides you a stronger guarantee of than just adding test willy-nilly.

[00:32:24] Marker

[00:32:24] Leo Dion (Host): One question I have when I am right starting to write like an app is sometimes I need to like explore a particular API and just to make sure I have the functionality of that API down before I've even gotten to a point to understand what to test .

[00:32:42] So for instance you're talking like Core Motion or  something like HealthKit. I need to understand how HealthKit expects me to get the data back. So I end up actually writing the code before I've even written the test. How do you explore tdd when you're like working with a brand new API that you've never even worked with?

[00:33:03] Joshua Greene (Guest): For me, there's nothing wrong with doing a spike solution. So I've never used an API before how good is my code actually going to be the first go around that, you know, I'm actually touching or using this thing. Maybe it's okay, but probably not great. Right I can go and explore this in a test app and compiling just a few classes is going to be way quicker than compiling my entire code base and just play with it.

[00:33:27] You know, maybe n after I'm done I can look back and say well this isn't actually too bad and then I might actually rewrite whatever I did in a TDD fashion and you know improve it from there or I might say, oh this code is I mean, at least I learned what I was trying to learn but is actually pretty off o it's not going in my case.

[00:33:45] I can entirely throw away a spike that takes me just an hour a couple hours to do and go back and then you know implement it in a correct TDD fashion. That's you know, one way the other way is if you do have some notion of what it does and how it's supposed to work. You can write tests in advance that has the, you know, just the behavior of how the thing works that you're trying to interact with things like Core Motion might be harder because it's actually doing asyncronous things or requiring you to move around in the real world for those sorts of bits. They are, you know, it may be that you can't do a lot of the testing upfront but other sorts of APIs like maybe making REST-ful calls. You can wait on a REST-ful call and you know, accept that I'm just going to write these tests as a temporary thing to see what it returns.

[00:34:31] There's nothing wrong with doing that and you know just using as experimentation. So for me if I'm touching a new thing. Those are my go to either use a spike solution that I may or may not keep and if I do keep I'm gonna have to write tests for it in a TDD fashion or just write tests that are temporary tests that are for exploratory only and throw them away after I'm done because they're not actually useful or that might be useful for learning but they're not useful for keeping in my project forever.

[00:34:57] Leo Dion (Host): It's almost like a rewrite like you basically explore the solution right and that kind of does the behavior more or less and then go through and then rewrite it with a little bit more architecture and tests within it. Is that what I'm hearing?

[00:35:10] Joshua Greene (Guest): You never used it before right so if you've never used an API, you're not going to know how it works or what's best to do with it.

[00:35:16] What's not to do? Your first solution probably isn't going to be great. So a lot of times it's worthwhile to throw out whatever you're doing because it's more of a learning thing than it is anything that's going to truly be worthwhile to put in production

[00:35:29] Michael Katz (Guest): 100% for me. One of the things that we have in our workspace is we have a couple of playgrounds where we actually import the local frameworks for our project. So if we wanted to like test how something new interacts with the code, we've already built we have that ready to go. And so you can spend some time in the playground adding a code calling a new API seeing how that goes. Obviously it doesn't really work for Hardware dependent things but for learning Core Location or you know something with SQL some like that there's definitely work there.

[00:36:00] Leo Dion (Host): Is there anything else you wanted to talk about when it comes to test driven development before I ask more about WWDC?

[00:36:07] Michael Katz (Guest): I think it's becoming more and more industry standard especially and I'm sure it's been in the server-side world for a long time. But in terms of the app world, I know I've had conversations with my executives and they start talking about it in a meeting and it usually takes a couple of years before they learn about whatever the cool new thing is.

[00:36:27] I think going forward we're going to be living in a world where this is more natural and each year Xcode gets a little bit better in terms of supporting the test, especially in terms of test running and test performance. One thing we do really touch on is how you some kind of continuous integration going which I think is it's not essential because TDD is just a methodology but in practice if you have a server that's always running these tests it makes it easier to catch things and make sure that there are issues with merges or multiple developers working on something not everyone may run all the tests before they submit.

[00:37:01] Leo Dion (Host): Yeah, let's talk a little bit about continuous integration. What have you done as far as that's concerned? Like I've done like open source projects on GitHub and I pretty much run Travis CI for doing my you know, simple essentially running my tests and testing out on different operating systems and different devices.

[00:37:21] What are some ways that you've done continuous integration? How have you seen benefits from that.

[00:37:25] Michael Katz (Guest): We use Jenkins. So we have a local server that actually we have I don't know how many Mac Mini nodes that run our tests and we use is a product called FastLane, which I think is pretty common in the iOS world.

[00:37:39] It's kind of like the. It sits on top of xcode build and allows you to basically specify the configuration for building and testing and you can run multiple tests and upload iTunes connect and things like that as part of the service but the important thing there is we have probably about 50 Engineers that contribute to our code base and so it's essential to make sure that what we have is always in good working order.

[00:38:04] But if you're working at a small team or you're working by yourself Travis or Circle CI are good solutions. Xcode server is what Apple keeps pushing. I haven't seen anyone use that in practice, but it has all the Integrations with Xcode so if you're able to use it and you're just building an iOS or macOS app and I think it's going to work out pretty well for you because it knows all about Esco tests and code coverage and things like that.

[00:38:30] Leo Dion (Host): Yeah, I've worked with xcode server. I've actually set up a virtual machine to run whatever the feud like, I'll probably set up one in a week or so and using Catalina and then put Xcode server on it. It's pretty decent like there's a lot to it some tweaking and things that you have to consider when you set up your project. But yeah, it works pretty decent.

[00:38:48] Joshua Greene (Guest): Yeah, so I basically used all of them myself and I'd say given the choice between using nothing or picking at random even right the picking at random is gonna be better than using nothing at all. Especially, you know, the more engineers you have the bigger bang you actually get for wanting to use continuous integration and sure at some point it's just strictly required frankly.

[00:39:10] You know, like my team is pretty large, but if you have maybe one or two developers. Especially if you're following TDD, I don't know they're strictly required for for that size per se because you do want to be constantly just running all over the test. Right? But once you reach a certain point where you have to ensure, okay, the projects is just so large or you got so many engineers that you really need to have some safeguards and checks in place other than just you know, Cowboy. Everybody agrees this is the right way to do it. Continuous integration definitely is a requirement. You know and Xcode server is a good one will be you know, especially if you have a Mac Mini or something around or haven't done it with the Virtual Machine although the now I want to try so that's a good suggestion but it's an easy thing.

[00:39:52] Leo Dion (Host): Especially if you're doing anything or if you're going to be trying new stuff, you probably want to put Catalina on a VM instead of running it on your main machine that's living on the edge. If you want to do that

[00:40:02] Joshua Greene (Guest): The Mac minis are still pretty cheap so our group uses just a small fleet of Mac minis as well there, but the cheaper route is going the VM for sure. So I guess maybe parallel or something depending on how you're running it and I suppose maybe have to buy the parallelization software. I don't know.

[00:40:20] Leo Dion (Host): Yeah, great guys. Thank you so much for coming on the show before we close out. You want to talk a little bit about your book again.

[00:40:28] Michael Katz (Guest): It's an iOS test-driven development by tutorials available now at raywenderlich.com we have an early access that has the first third of the book and the whole book should be out in the fall. It covers the whole TDD from starting from nothing. We have a whole big piece networking because there's almost every app has that and It's tricky to test we have chapters on how to work with a big legacy app especially where legacy means no tests or insufficient testing.

[00:41:00] It goes through each of these things step by step. So you follow along. So unlike other books that may give a more theoretical approach emerges say here's what your code should look like. This is very step by step you follow along going through adding the tests adding the test targets, the whole shebang.

[00:41:17] Joshua Greene (Guest): I'd say we've done the hard work for you going through the Apple apis and you know have a very experienced developers that you know Mike and I've used this for several years. Mike has used this for several years here. You don't want to learn all this stuff by yourself. It'll take longer. It'll be harder to do if you want to get up to speed and get running quickly.

[00:41:36] It's the best way just get the book save yourself some time. Save yourself some sanity happened to not go through those Apple API to yourself and get running quickly and  get up to speed quickly.

[00:41:47] Leo Dion (Host): Yeah, that's fantastic. I'm really looking forward to take a look at this book and just learning some new ways to do TDD when it comes to Xcode and iOS.

[00:41:57] Before we close out, do you guys have any thoughts on some of the new stuff from WWDC and how it pertains to test driven development?

[00:42:06] Michael Katz (Guest): Unfortunately, it's about six hours from the what's new in testing in Xcode. So what I've seen so far as just been what they've covered in the what's new in Xcode and the State of the Union, but it looks like that there's some new methods for.

[00:42:21] We've had the measuring blocks before that measure the time your test takes I know it looks like you can also measure memory usage, disk usage, and a bunch of other things which is really great. They're not really like for test-driven development. But when you're building reliability tests and performance tests, and with those are going to be pretty handy and then there's this new thing called test plans which basically.

[00:42:42] Takes all the management of tests from the scheme into a separate top-level object in your project and you can rerun your tests against multiple configurations. So you can run all your tests in English and then run all the tests again in French or whatever in one click. They also have four different test ordering and different runtime checks and all that so it takes one manual step out of the loop, but I wouldn't necessarily think it's super revolutionary. What do you think Josh?

[00:43:10] Joshua Greene (Guest): I'm totally with you as far as the new features. They look pretty cool for Xcode goes. I also wanted to point out that with the SwiftUI they've really gone very much so protocol oriented development.

[00:43:22] That's great news for things like testing and test driven development here anytime you can put in a protocol in place you can insert a mock very easily into whatever set up it is so I'm very excited to see how they've really architected SwiftUI and it looks like just testing is going to be a lot easier compared to some of the previous solutions where you've got concrete class and just figuring out how you're going to mock that out, you know via subclass or whatnot may have been very difficult with pure UIKit.

[00:43:51] It looks like SwiftUI is gonna help us quite a bit in the testing realm. So I'm very excited to dive into it and learn everything about you know all the cool stuff that they've done and cool stuff to make developers lives easier with testing.

[00:44:04] Leo Dion (Host): You're talking about the difference between like UIViewController, which is this class.

[00:44:08] You have to subclass as opposed to like the SwiftUI View protocol which you can pretty much mock up any way you want to right?

[00:44:15] Joshua Greene (Guest): Exactly yeah, the whole UIViewController thing, there's so much concrete stuff in that it's difficult to truly create great mocks with it. I mean you can, you know, create a mock by subclassing uiviewcontroller, right.

[00:44:28] But had that been a protocol, I mean you can combine protocols so much more easily combined functionality using protocol oriented development. But creating mocks the same thing, you can just conform to that Mark and just Implement whatever message you actually care about and it's just much more elegant solution a much more, you know architecture friendly solution going with the protocol then something concrete.

[00:44:51] So it's a very good job on Apple's part and you know it's my take on it so. I haven't gone to see all of the defaults implementations of stuff they give you but you know, hopefully it's saying and you know, from what I have seen it looks very well done.

[00:45:04] Michael Katz (Guest): One of those things with SwiftUI is there really is from sample code encouraging people to build out separate model classes, which also makes it easier to test.

[00:45:13] Leo Dion (Host): You're talking like the previews

[00:45:15] Michael Katz (Guest): Yeah with the previews and you can have being able to put multiple previews in the assistant.

[00:45:20] I think I'll make it great for testing not really testing but just visualizing the different conditions before you even get to the point of completing your code, but the at state you can have a separate model class be bound to your view as you to put that logic of loading data and changing data and so on outside of the view of other people couple and their view controllers the setting of The View State and then the model state so it's exciting.

[00:45:45] Joshua Greene (Guest): It looks like they're kind of pushing Mike component-based development too you know, I've seen like so many developers where you need a custom UI tap controller or something, right. So you go and instead of right and something your own which may be in the right solution you go and you try to reuse Apple's and then you're trying to hack internal methods and so forth and it's just hard to do with all the Swift you I think they provided a same base and said look you need new components. You can create something. I'm excited for testing because the idea being you could split those off into their own library. Here's this component that I need or set of components that I need and just pull them in as you need and ensure that they're tested really well. So again, it just looks really well done. So the team did a really good job as far as everything I've seen so far.

[00:46:25] Leo Dion (Host): Well, thank you so much guys for coming on the program if folks want to get ahold of you. What's the best way?

[00:46:31] Joshua Greene (Guest): Sure so if you have questions about the book, we actually have a forum on raywenderlich.com. We actively monitor that as authors of the book.

[00:46:41] So if you have questions ask them there and we will actually answer you for anything that you've got. If you want to reach us personally jrgdeveloper@gmail.com by email or Twitter @grg_developer

[00:46:53] Michael Katz (Guest): and I'm @themikekatz on Twitter

[00:46:56] Leo Dion (Host): well, thank you so much for coming on and maybe we'll talk again later about Swift UI and how that's going to improve test-driven development.

Thanks to our monthly supporters

  • Steven Lipton

★ Support this podcast on Patreon ★

Chapters

Why Maintaining Code Quality Matters

If you’re serious about app architecture and structuring your app well, it pays to also think about how you maintain your code. If you have high-quality code, it makes development faster, easier and cheaper.

There are two great ways to ensure high-quality code:

Test-Driven Development

I’ve previously written about Test-Driven Development (TDD), which you can find here. Committing to good testing and setting up a good testing environment is one of the most powerful things you can do to make your code top-notch.

Ensure Good Code Coverage

Code coverage, measured as a percentage, refers to how much of your app’s code is executed during testing. A high degree of code coverage indicates a low number of possible undetected bugs in your app. This is a great measurement for determining code quality, although you shouldn't be too strict about it. While it’s obviously great if you reach 100% coverage, it might come at a cost when there are more important things you could be doing to serve your users.

Complexity

In software development, there are two kinds of complexity we want to observe and measure:

Cyclomatic Complexity – this metric looks at the number of linear paths it is possible for data to take through your app’s source code. While there are going to be times when it's necessary to have many paths, you generally want to limit this kind of complexity. The reason is that more paths mean needing more test cases to make sure they all work, and more paths mean more opportunities for bugs.

Cognitive Complexity – this metric simply refers to how easy it is for people to understand your code. Easy-to-understand code is always going to be easier to maintain. This is especially true if the person who wrote the code and the person maintaining it are different people.

Overall, keeping your complexity low by limiting file and function length means adding features and fixing bugs takes less effort.

Continuous Integration with Kyle Newsome - Audio player

Empower AppsTrailerBonusEpisode 24Season 1

Continuous Integration with Kyle Newsome

Continuous Integration with Kyle NewsomeContinuous Integration with Kyle Newsome

101X30

00:0040:52

Visit Transistor.fm - Podcast Hosting and Analytics

More episodes

  1. Continuous Integration with Kyle Newsome

41 min

Subscribe

Copied to clipboard

Share

ShareCopied to clipboard

EmbedCopied to clipboard

Start at

Empower AppsTrailerBonusEpisode 24Season 1

Continuous Integration with Kyle Newsome

October 13, 2019Leo Dion, Principal CEO and Swift Developer at BrightDigit Full TranscriptView the website

Guest

Sponsors

BrightDigit

Contact me if you need help today.

We have an opening for sponsors

  • Do you have a product or service which can target our ever growing community of developers as well as technology and business leaders?

Contact me today if you are interested in sponsoring or go to our Patreon page.

New iPhone 11 Thoughts

  • Camera Improvements
  • Max vs Not-Max Size
  • DSL vs iPhone
  • Night Mode

Continuous Integration Issues with iOS

  • Deployment Issues
  • Cache Issues
  • Continuous Integration 101

How to Get Started

  • Removing Dependencies on People and Files
  • Reproducible Anywhere
  • Using Pull Requests or Code Reviews As Triggers
  • Having Tests to Address Pain Points
  • Dealing with Certificates and Provisioning Profiles
  • HashiCorp
  • Using Tools Like Fastlane

Comparing Services

Feedback Loops and CI

  • Having Healthy Unit Tests
  • Rapid Results through Automation
  • Proofing Builds Before QA

Social Media

Twitter - @brightdigit

Facebook - BrightDigit

LinkedIn - BrightDigit

Instagram - @brightdigit

Patreon - empowerappshow

Transcription

Leo Dion (Host): Hey, Kyle, how are you doing?

[00:00:01] Kyle Newsome (Guest): I'm doing great. Thanks very much. It's unfortunately a slightly rainy day in Toronto here, but otherwise, a good mood.

[00:00:07] Leo Dion (Host): Yeah, same here. It's been a weird, cause. I don't know what Ontario's like, but Michigan. It's like one day was 80 degrees and then the next day dropped down to like 50 or 60

[00:00:18] Oh, sorry. That's Fahrenheit. But you get what I mean.

[00:00:20] Kyle Newsome (Guest): It's okay. I lived a little bit in the States, so I like can do the conversion. I know that like 70 is nice and comfortable. Eighties getting to hot sixties like not too bad.

[00:00:30] Leo Dion (Host): I think fall's finally here. Yeah, so another sign of fall is the new iPhones. Did you get anyone iPhone?

[00:00:38] Kyle Newsome (Guest): I got the new iPhone 11 pro max. Which I've been waiting to upgrade for a few years. So this is like my first experience with like the X, you know, edge to edge screen as well.

[00:00:49] Leo Dion (Host): What do you think of it?

[00:00:51] Kyle Newsome (Guest): Honestly, so far I'm pretty impressed with it and as much as people have complained about how the three lenses look, I actually think it looks pretty nice.

[00:00:58] They've done something good with the glass backing, so it looks pretty refined, so I can't really complain about that. I've played around with the camera and the night photography a little bit and it's pretty cool to see how much it can capture in low light.

[00:01:11] Leo Dion (Host): What did you have previously?

[00:01:13] Kyle Newsome (Guest): Previously I had the iPhone seven plus.

[00:01:17] Leo Dion (Host): Okay. And do you really like the max size?

[00:01:19] Kyle Newsome (Guest): You know, like I'm used to it in my hand now, so I can't complain. You know, for the longest time I didn't think that I would like it, but I believe when the seven plus was the only one that had the two cameras, and I was really interested in that functionality.

[00:01:32] So I upgraded to the largest one, and now I'm kind of used to it. But I think that both the regular size and the max size are both pretty good in terms of screen size you got. I'm just sort of used to this in my hand and I liked that when they at least made the change from the old ones to the new ones, they kept the size of the same and then just you got more screen space so it feels exactly the same as my old phone in my hand.

[00:01:56] Leo Dion (Host): Yeah, I was a plus size user and I loved that. And then I went to the 10s, not max. And I don't feel like I miss the size because the screen size is pretty much the same. But I was just curious, like if you see like a big advantage with the max.

[00:02:12] Kyle Newsome (Guest): No, I don't really think so. I guess it gets a little bit longer battery life, which is always nice, but otherwise, yeah, they both look pretty nice.

[00:02:20] I was sort of on the fence whether to go with one or the other, but I think ultimately it was kind of like hand feel that I just like, I was used to the weight and everything, so I just wanted to make a seamless transition like that.

[00:02:30] And the big selling point for me with the plus was the extra lens. And like now we don't have that.

[00:02:35] Leo Dion (Host): Like the extra selling point isn't there because he can pretty much get that with the regular pro. So like that was my big thing was I just want a really good camera. Like I don't have cameras anymore. Like I think I sold my DSLR and my other digital cameras a couple of years ago cause I wasn't really using them.

[00:02:54] And like the convenience of having an iPhone was always worthwhile to me. And like the dual camera, like I'm a. I know people don't really care for portrait mode, but I use portrait mode all the time when I'm taking pictures with my family and things like that, and I like it a lot.

[00:03:08] Kyle Newsome (Guest): It's funny that you just sold your DSLR and I just bought a mirrorless camera because I was interested actually mostly for video recording purposes, which i think is actually where there's the biggest difference between what these phone cameras can do and what the regular cameras can do, because they can do a lot of post-processing on like one image, but doing things like getting that portrait mode depth of field effect per video is not something they're really capable of today.

[00:03:33] Leo Dion (Host): Yeah. Not now.

[00:03:34] Kyle Newsome (Guest): That aside, I mean, yeah. It's just like the camera on your phone is just so much more of a utility for everyday use. So many of the pictures that I take with my phone or just to like to help me maybe remember a password that was written on a note somewhere that I wanted, or just general utility.

[00:03:51] They're not very interesting pictures, but I would never do that with a mirrorless camera. Obviously not convenient at all.

[00:03:58] Leo Dion (Host): Yeah. Really liking these cameras on these phones. So what's your opinion of like night mode.

[00:04:03] Kyle Newsome (Guest): You know, it wasn't the operating the way I thought. I thought it was just going to basically do a whole bunch of post-processing on the image and know how to like extract the right colors, but it actually does do like a long shutter effect, which surprised me a little bit.

[00:04:18] I wasn't ready to see that. But it's interesting. So I think depending on the amount of light in the room, it kind of auto suggests about how long it's going to do the shutter effect for and seems like the longest it goes for is maybe four seconds.

[00:04:31] Leo Dion (Host): Okay.

[00:04:32] Kyle Newsome (Guest): What I find interesting about it though, like I'm curious about what it's doing, because obviously if you are holding the shutter open for four seconds and you're just doing it like handheld, you're probably not holding it perfectly still.

[00:04:43] So, I wonder, you know, what other sorts of machine learning and things they're applying after the fact to make sure it still comes out like a crisp photo, but it's grabbed more information about color simultaneously. I can't say I've really looked into exactly what it's doing, but that was the experience I got from it.

[00:05:01] Anyway, I thought it was going to be just Oh snap and then it'll post-process and like bring out all this color, but it actually does try to record more light for longer.

[00:05:09] Leo Dion (Host): Okay. So that's what it's doing. So it's basically keeping the shutter open to get more light while at the same time doing some ML stuff to like figure out what's the best photo to use or what's the best picture to use. Interesting.

[00:05:21] Kyle Newsome (Guest): For sure.

[00:05:21] Leo Dion (Host): That's pretty cool. So before we deep dive into continuous integration, you want to tell people a little bit about yourself.

[00:05:28] Kyle Newsome (Guest): Sure. I'm terrible at talking about myself or building myself up. I'm an iOS developer in Toronto. I've also done a lot of full stack development over the years, and so I've done backend and JavaScript and PHP, but I did Objective-C back in the day and then got a little tired of it, did some more Javascript just because the language, I think was more pleasant to use.

[00:05:53] And then Swift came out and they open sourced it, and then it just sorta like turned all my attention back to iOS again. And then I've just been going straight with iOS since, but even some of my continuous integration experience actually came first from doing it on the web side, deploying web and backend Java script applications.

[00:06:12] And then when I came back to the iOS world, realized I was joining a lot of teams that weren't doing much with that. And so. Really started trying to learn more about continuous integration on the iOS side and championing that at the places I was working.

[00:06:25] Leo Dion (Host): And where are you working right now?

[00:06:26] Kyle Newsome (Guest): So right now I am consulting with Deloitte for Loblaw digital.

[00:06:32] Loblaws is like the Walmart of Canada, effectively. And I work with their loyalty, their PC optimum points application, which is. I believe the biggest loyalty program in Canada as well. So like when you go out and buy groceries or you go to the pharmacy, they're constantly collecting points and they're giving you bonuses and things.

[00:06:50] So yeah, that's the application I'm working with right now.

[00:06:53] Leo Dion (Host): What have you found is the biggest difference with CI or continuous integration on iOS. And I'm assuming we're just talking about iOS as opposed to web development.

[00:07:05] Kyle Newsome (Guest): I mean, I think probably the deployment factor is a huge thing, which isn't exactly like, it's the last step of the continuous integration process, like right as you deploy, but going even beyond continuous integration, there's like continuous integration, continuous deployment.

[00:07:20] And continuous deployment is really like, you're always able to continuously like push out the latest version of your application, you know, multiple times per day even, which is not really possible from an iOS perspective. We have to be a little more meticulous because we go through the Apple review process.

[00:07:36] A lot of companies are, you know, probably deploying maybe at most once a week. I don't hear of many who are deploying more than once a week. There's probably some out there, so it's a little bit slower. That's one of the big things. And I think even just some of the tasks you actually do, because continuous integration sort of starts first of all with like build, test, deploy steps, which are kind of just the core steps to getting your application built, making sure it's actually functioning properly, and then sending it out to the world.

[00:08:04] But beyond that, we tend to add a lot of additional tasks to kind of make sure that we're. As much as possible, automating our entire process. So some of those additional steps are probably quite different depending on web or iOS. Like I remember on web, I had to be constantly clearing cachees out, you know, clearing cachees out from CDNs or content delivery networks.

[00:08:27] And I don't have to do that as much on an iOS side, but there's other tasks I might do instead, like, you know, automatically generate screenshots or something like that.

[00:08:36] Leo Dion (Host): All right. So let me do my best attempt at trying to explain what CI is and then you let me know what parts I'm missing. So continuous integration is the idea of, as you make changes to the code, you are running various tests, not just like unit tests, but also like integration testing, things like that.

[00:08:58] And also making sure that the app can be easily deployed. And usually you're doing it on some central server somewhere, either locally or in the cloud. So that way you can best recreate the situations for where an app will actually be running. And I'm saying this because you have, like for server side stuff, it's pretty easy because you can just run on the actual server and recreate that situation pretty easily whereas with client applications, you need to like actually recreate the client atmosphere in the client environment in order to do that. But is that like a good description of continuous integration?

[00:09:35] Kyle Newsome (Guest): Yeah, I think that's a fairly good description of it.

[00:09:38] Leo Dion (Host): What am I missing?

[00:09:39] Kyle Newsome (Guest): It's not very often that people ask me to explain it and sort of formal terms, so I'm probably usually speaking about it from the benefits perspective.

[00:09:49] But one of the things I guess I take away from it sort of from, I guess a more philosophical perspective, is like there's many things you do to sort of make sure that your app is deployment ready and some of those things can be automated and some of them can't. The ones that you can automate, you should automate and you should be doing them every single time, every single day.

[00:10:11] Leo Dion (Host): Yeah. There we go. And I think that's it. It's like regression testing where you're like testing old features and making sure they're continually working and doing it every time in a repeated basis. And when we talk deployment, we're talking about like taking that app and putting it on an actual machine, whether that's your server for server side app or an iPhone or iOS simulator in a lot of cases, and actually testing it on that device and seeing if the app is working.

[00:10:36] Kyle Newsome (Guest): Absolutely.

[00:10:37] Leo Dion (Host): If you were going to convince somebody who like has never done continuous integration, especially in an iOS application, what would you say to that person or to convince them that like, yeah, you really need to get started on getting your iPhone app running, some sort of continuous integration whenever a new release is about to come out in the app store.

[00:10:56] Kyle Newsome (Guest): Yeah, I mean, I think certainly on some teams you just really kind of help identify the pain points they're feeling or you know, something goes wrong and then you do a retrospective on like, why did this happen and how could we prevent it in the future? And then it's really easy to say like, Oh, well see, I could fix that coming from the web, like the example I used before with cache clearing, that was a super easy.

[00:11:18] Thing to point out at one company I worked with, like we were just forgetting the clear caches, and then people weren't pulling down the latest version of the application, or they were pulling down the latest JavaScript, but not getting the latest CSS and so they weren't seeing things correctly. So that was, you know, a good pain point from a web perspective

[00:11:35] On iOS, one team I worked with, they just had one developer who could deploy the app and had all the certificates and was ready to go and he was also responsible cause one of the things when you deploy an iOS application is you always have to bump the build version, which is like the most boring change you have to make to your application is increment you know, the build number every time.

[00:11:56] Leo Dion (Host): But it's easily forgettable.

[00:11:58] Kyle Newsome (Guest): Oh, super easy to forget. Right. And that's what was happening in this case was that the developer would sometimes deploy it, he'd forget to bump the build number. So we'd go through the whole deployment process and that build process takes sometimes 20-30 minutes to get that, especially if you include the uploading process to Apple's TestFlight and the processing time before they give you feedback.

[00:12:20] That's actually, you know, that's sometimes an hour to an hour and a half. So you know, having to kind of realize that the very end of that. Oops! we forgot to increment the build number let's go back. In this case too he actually unfortunately had just been going through ACL surgery too. So he wasn't always available in the office cause he was going to a physiotherapist.

[00:12:41] So like his availability wasn't good. So there, you know, the pain points between relying on this one guy who was in the middle of, you know, dealing with ACL surgery and recovering from that and having that point of failure of the build number. Those were two big pain points and good reasons to move to CI.

[00:12:57] So, yeah, I guess in summary, find the pain points. It's probably hard for me to pick someone up off the street who doesn't have a problem already and tell them that continuous integration is going to solve things. But once people have those pains, I think it's really, really easy to change their mind or convinced them to start using it.

[00:13:16] Leo Dion (Host): It's one of those cases where it's like you don't realize the pain until your employee has to be out for a few weeks, or what was it - somebody who was like on paternity leave at some company and like they're quickly trying to hire somebody to like fill the gap until he gets back. And it's this like one of those situations where you don't run into it until you run into an issue and you're like, okay, now I need to set up some sort of system with continuous integration in order to make sure that deployments are easy and things like that.

[00:13:42] Yeah. What are would be some like first steps in order to get started? Like what would you say is like the bare minimum as far as getting continuous integration set up?

[00:13:51] MarkerKyle Newsome (Guest): Yeah, so I mean, one of the first things you probably want to be thinking about is eliminating any local dependencies you have, right. If someone can only run that from their machine there's a reason why, right? Something is local to only their machine that isn't available to others. And a lot of cases with iOS, it's mainly about the certificates and the profiles that are on that computer that the others don't have. So you're going to try to either you know, make sure that your CI system has that stuff now, or ultimately, yeah, you're just trying to make sure that this is something that you can reproduce pretty much anywhere.

[00:14:29] You know, that people haven't, you know, have too many local scripts or anything like that. Running that would prevent you from duplicating the build experience somewhere else. So that's one of the first things that you can do if you have a tool like fastlane that you're using already. Cause sometimes some teams are actually using fastlane,  to do tasks for themselves, but they haven't gotten themselves on CI yet, or you're trying to sort of slowly work your way there.

[00:14:54] I think fastlane is a good tool that can start getting you ready for that because fast lane is all about doing tasks related to iOS stuff for you automatically, and you can run fastlane commands in CI. So you could even have your build, test, deploy phases running from your local machine through fastlane.

[00:15:12] And then when you put it on CI, you're basically just telling CI to run those same commands you were locally. So that can make it very easy to make the transition. If you already have a pull request code review process going on, that's probably one of the most important places to start integrating your CI server because every time you put code up for review, then it can go through this system and some of that feedback can be automated against it.

[00:15:39] So I'd say if a team doesn't have any sort of pull requests or code review process yet, they should get that up and running first. Even if they don't do super thorough examinations of the code in those pull requests, at least get the CI starting to do that for them. I think those are some good first steps to getting ready for CI.

[00:15:59] Leo Dion (Host): So let's sit back for a little bit and talk about each of those components, like a pull request and a code review process. What does that mean exactly?

[00:16:06] Kyle Newsome (Guest): So it's very easy for me to just merge code into, say,  the main code base that maybe I'm collaborating on with others. But if I just sort of get to directly make changes to the code.

[00:16:20] No one else is, you know, reviewing that in advance for any sort of mistakes or giving me feedback on how maybe I can improve those changes to the code base. And not having a process in place to do something like that is probably prone to causing error or catching problems later. So if you use anything like GitHub, GitLab, Bitbucket, they all have the ability to do a pull request process, which basically means you work on your code in sort of a separate branch and get terms, you know, from the main master code base, and then you make a formal request to merge your branch of code into your master or into maybe your development branch where you're working on things.

[00:17:03] And before that merge actually happens, someone actually has to approve it. You know, someone has to actually go into, say if you're using GitHub, going to GitHub and hit the approve button, and then the code can be merged from there.

[00:17:17] So. You know, the pull request process is the first step to, I think, creating a code review process. Like I said, you know, even if you weren't reviewing the code changes, but you at least were going through a formal process of putting up a request to change the code and someone else was approving it, that would be the first step.

[00:17:36] And then from there you'd probably want to influence your culture to like spend more time actually looking at the code. I'm getting feedback on it. And then integrating CI as well. And I can certainly talk about things. See I can do for your code review processes as well later.

[00:17:51] Leo Dion (Host): So basically like you have unit tests, obviously that need to be run and we did a whole episode on unit tests a few months ago, which you can check out. But like a pull request, that's where you'd have like your branch or your feature, and then you want to make sure to merge it into a specific version or master branch, and then somebody will go ahead and approve that. Does that sound about right?

[00:18:12] Kyle Newsome (Guest): Yeah

[00:18:12] Leo Dion (Host): and I think like one of the biggest challenges, and you just touched upon this, was the local dependencies and the certificates and profiles and things like that. That seems like one of the biggest challenges that I've faced with getting any sort of continuous integration set up is getting those certificates on some sort of server or putting them into the repo, but also in a way that it's secure.

[00:18:36] Because obviously you don't want anybody off the street to come in and get your repo and then put your app into the app store, but like there's a specific process for setting that up, right, where you can like encrypt the certificate, but then like have the password on the CI so that way you can decrypt it while at the same time, like making it secure, but also letting the CI system be able to approve and deploy an app.

[00:19:00] Is that right?

[00:19:01] Kyle Newsome (Guest): Yeah, absolutely. You ultimately want to expose. You're a certificate to as few people as possible. Ideally, you don't really want to be distributing these widely. So yeah, the fewer number of people that have that privileged, right - the better. And I mean, depending on the size of the team, you know, in enterprise situations, like I was working with a bank earlier this year.

[00:19:24] And they don't want the certificates or the profiles available to the developers at all. In fact, they have policies at the bank that, you know, a developer can't end to end both build the application and get it deployed to the store. There's actually multiple steps between to sort of make sure no one gets that much power.

[00:19:41] Leo Dion (Host): If you can say, I guess, how do they get around that?

[00:19:44] Kyle Newsome (Guest): Well, I mean, ultimately they have a dev ops team, and so these are, you know, operations guys who are sort of full time dedicated to building the applications and getting things configured properly so they get some access to this stuff. Although those certificates and profiles are still kept in a vault.

[00:20:02] There's like HashiCorp Vault is a product, I don't know if you're familiar with it, but it's just sort of a secure key store. So their CI system access is things from this vault, but they have permissions to work with the Vault and the CI process. But yeah, we weren't even really super involved. And that, you know, I could make some requests to change some of the CI workflows, but dev ops always was approving those.

[00:20:26] I couldn't change those myself. So interesting. It was just sort of one layer away from me that had the access ultimately.

[00:20:33] Leo Dion (Host): So if someone were to get started with CI, what service would you recommend first and foremost, and how do each differentiate themselves?

[00:20:44] Kyle Newsome (Guest): Right. Well, I think. My suggestion would maybe depend on, you know, whether, like if we're talking about just getting started with your first CI ever and you haven't done this at all, and we're talking about iOS, I've certainly enjoyed using BitRise because BitRise is very iOS and Android focused.

[00:21:06] When they first came out, they were even just iOS focused. And I found that the flow of getting started with them, they would, you know, do additional analysis on your project and try to sort of get it auto configured for you every time there's new versions of Xcode, they really try to be the first to get those beta versions of Xcode out onto their systems.

[00:21:28] So I found that they just, they have a very, like iOS is first class kind of attitude, which I like. Things like Travis CI and CircleCI are both. I guess I don't have much to differentiate between those two. They might have different price points, some of these different services. Also, I know like let's say you're doing an open source project that you want to put through CI. I think Travis or Circle might be better for that because they have a better free tier.

[00:21:56] Leo Dion (Host): Yup, yep. I've used Travis CI and we'll get into it a little bit, but I still haven't figured it out with Circle CI, and I've actually talked to some of the folks there, but Travis also does Mac apps. Which we'll talk about in a little bit.

[00:22:09] I think Circle supports that, but I haven't quite figured that out. It seems like the big hurdle with a lot of these surfaces, spoiler alert, is that you actually need a Mac to like run this stuff, which is a huge cost burden to any company in the cloud because they literally, like if you look at somebody like MacStadium, like you literally have to have a rack of Mac pros or Mac minis or iMac pros or whatever to like from this stuff. It's not like even with the VM, you need to run this stuff on a Mac. So I think like that's one of the big burdens with a lot of these services is like a lot of your CI services, they're going to be fine at doing like your Ruby or your Node JS and even some of the.net stuff, but like once you actually need a piece of like Mac hardware to do it, that kind of makes it more of a challenge cost-wise to these companies

[00:23:00] Kyle Newsome (Guest): for sure. And yeah, performance of some of these things, I guess when they're like running inside of virtual machines may not be as good as if you say got a really high end Mac mini or something and ran it locally because that is another option is self hosting, which we haven't touched on yet.

[00:23:17] And I don't really recommend self hosting for some reasons I'll bring up in a second, but just exploring what that means. You know, this is buying a computer to sort of have, you know, in your office that is connected with the system and running those things locally on your own computer. It meant you could do that either through Jenkins, which is a very popular one, or Xcode server.

[00:23:40] Apple has their own X code server. Although I don't know anyone who uses Xcode server. I don't know if you have worked with many companies that use it. I haven't found it to be very good personally.

[00:23:50] Leo Dion (Host): It's okay. So here's my situation that I've run into is I have a Mac app Speculid, which is for building app icons from SVG files or image sets, whatever. Okay.

[00:24:02] So like with this app, I've run into situations, especially early on where I needed to like actually test it on different like Mac environments and one thing you learn with like Mac development, I find one of the biggest challenges is that you don't have like reset simulator on the Mac, right? So I ended up sending up like a Virtual Box VM on my iMac to run Mojave or whatever is the latest OS and putting Xcode server on it and it works and it's like a great way for me to just like do reset simulator essentially by reverting to like a snapshot on a VM and that's what I've been using whenever I need to like test. There's been all sorts of weird issues like dependencies that have been installed or like I totally forgot about how different countries do decimal points differently and like all sorts of weird issues I've run into.

[00:24:54] That has been to my benefit with the CIA stuff. So like XCode server worked. It was fine. It was a great, was it as easy to set up as like Travis, which is probably the other situation I've run into? No, I don't think so. And of course it's like not the fastest, but it works.

[00:25:11] Kyle Newsome (Guest): It gets the steps done for sure.

[00:25:13] Like it's not pretty, it just sorta does the basics versus something like, I know BitRise. I mean I really liked their interface cause I think it's nice looking and it's something, I mean I know some companies, you know, even have sort of a culture of trying to make sure that sort of the build and whether it's kind of staying green is, you know, the developers are sort of aware of that all time.

[00:25:34] So maybe you have a dashboard that's kind of giving you an update on what your CI is and is it staying green. So sometimes using a nice CI that actually makes that look kind of nice to have, but it's not really the most important thing as just being able to run the steps.

[00:25:48] Leo Dion (Host): And then integration with the Xcode is really good.  And it was just a matter of like, the issue I ran into was just, I was using Travis CI cause Travis CI is free for open source projects and like it worked fine, but there was just a lot of things that I couldn't really like get into the guts of a Mac that I could do with the VM and Xcode server. So that's why I ended up getting that set up.

[00:26:09] And Travis CI doesn't necessarily have the latest betas installed for a lot of reasons. So I was able to like set up a CI system with whatever was the latest beta at that time.

[00:26:20] Kyle Newsome (Guest): Yeah. For ultimate sort of like power and control, having things, you know, self hosting is the way to go. For sure. You can do things just different that may not be possible.

[00:26:31] Like even the kinds of like caching can be different on some of these different services as well. I know that BitRise has some caching capabilities, but there might be a limit to the size of the cache. I've heard recently, I think maybe Circle CI didn't have a cache. Okay. Someone was telling me they were using either Travis or Circle and they couldn't cache the same way that BitRise could anyway.

[00:26:52] Leo Dion (Host): And when you say cache, what exactly are you talking about?

[00:26:55] Kyle Newsome (Guest): Just like holding onto some artifacts. Like, you know, sometimes you have dependencies such a, you know, a lot of people use CocoaPods

[00:27:02] Leo Dion (Host): and you know, want to rebuild and refinish those dependencies every single time. Is that what you mean?

[00:27:07] Kyle Newsome (Guest): For sure.

[00:27:08] Leo Dion (Host): Okay.

[00:27:08] Kyle Newsome (Guest): Exactly. That can certainly add to the time that it takes to get through your whole CI process.

[00:27:13] Leo Dion (Host): Yeah, that sounds like a lot. We had Abby Jackson on last week. We talked about modularization but she said like one of the big benefits is build times. So it's not something I really think about, but like if you're doing caching like what you're talking about, but that makes total sense. That's gonna like save a ton of time on your builds

[00:27:30] Kyle Newsome (Guest): for sure. One other thing with self hosting is the benefits is you get all the control, but the downsides is nobody's going to do that for you, so you become responsible for it. So I definitely think when a company decides whether they want to use a service or want to self host. They should really think about the dev ops costs associated with that in particular.

[00:27:52] Leo Dion (Host): Exactly.

[00:27:53] Kyle Newsome (Guest): Because if there's a beta, you're going to be responsible for getting that beta up and running. And if you realize that all of a sudden your team is growing and you need more machines, then you need to go buy and provision all of those machines and then get them collaborating together on a farm yourself again.

[00:28:10] And that is one thing that's really nice about using a service is that your team grows and you just buy the next tier or pay, you know, $5 more per month or whatever it costs per developer to grow your team like that. So these third party services scale very nicely. And yeah, the dev ops costs, you should really strongly consider before self hosting, I think for sure.

[00:28:31] Leo Dion (Host): Yeah. Do you have like an opinion on using a service like MacStadium  because the only reason I see it might be important for self hosting is security reasons or like Mac development where you like actually need an actual machine to like play around essentially with the computer itself and get those settings exactly the way you want it like otherwise, I don't see much of a reason to use self hosting service right.

[00:28:56] Kyle Newsome (Guest): Yeah. Unless you just, you want to do something really different. There is one organization I was working with, I can't talk too much about this one, but they wanted to be running a lot of different types of virtual - like they wanted to kind of virtualize their whole system during the CI process.

[00:29:13] So the servers that were being communicated with were all being run from that server as well. And so they were looking at moving towards self hosting to get some of those features that they couldn't get from doing it through these third party services. Because there are some limitations to just like how far you can configure these things.

[00:29:32] Leo Dion (Host): Exactly, exactly.

[00:29:33] Kyle Newsome (Guest): It's like I sort of temporary container. They boot up and they run some things and then they tear it down for you. Right, so you only get so much in that container.

[00:29:41] Leo Dion (Host): Like I'd almost suggest maybe looking at something like MacStadium like somewhere it's almost like a compromise in between, like what is it - it's like a layer of abstraction from running your own server locally, but not quite as abstract as like Travis CI or Circle or a BitRise because then like you don't have to do the IT work, but you still have to set up though less. So like that might be a decent compromise in some situations.

[00:30:07] Kyle Newsome (Guest): So I don't know MacStadium super well if I understand, it's sort of letting you actually get full access to a Mac machine.

[00:30:13] Leo Dion (Host): Exactly.

[00:30:14] Kyle Newsome (Guest): Remotely. Yeah.

[00:30:15] Leo Dion (Host): Yeah. They just have like. Mac minis that they run in their separate locations that you have access to. And I've done, like I've done the virtual box setup with getting a Mac server set up in virtual box. That way I can like tear it down and bring it back up, but that's only for like small apps that I've done.

[00:30:32] And then I'll post a link to my YouTube video about how I got Speculid set up on Travis CI, which is a Mac app and how I got that to work as well.

[00:30:41] So I wanted to jump in and talk a little bit more about Fastlane, which we got into and some of the tooling there, but you said you wanted to mention something about feedback loop and how feedback loops can be some issues you can run into with continuous integration.

[00:30:55] Do you want to explain that a little bit?

[00:30:57] Kyle Newsome (Guest): Sure. Continuous integration is something that I see as fitting as one of your feedback loops or sort of touch points, but to explain first a little bit about what the feedback loop is. You know, developer's going to get a piece of work in and then they're going to need to iterate on that several times before it goes out the door.

[00:31:14] And that iteration cycle, I would call your feedback loop and how long it takes for you to get feedback on something, whether it's working for you or not. You want to try to make that the smallest amount of time possible. Right?

[00:31:27] So there's lots of different points of feedback that we have. We're getting feedback as we're continuously like developing on something, running it, checking if it's working.

[00:31:36] We're getting feedback when we run unit tests, when we run UI tests, we're getting feedback when we pass things to the QA team and when we're say, getting approval from our designers and our product owners, but each one of these points of feedback takes a certain amount of time to like send it out and then get feedback and know whether to iterate on it further or whether you've sort of met the requirements.

[00:31:58] So I think we want to try to think about how well A - you know, some of the touch points with people, we want to make sure that we have like fast access to them and can turn around feedback quickly, but we also want to try to organize things in a way where the tightest feedback loops are sort of available to us first.

[00:32:14] We get those working and then we slowly work our way outward into the things that take longer and longer to get feedback from. So the first things are the development you're doing as you're iterating on it. Unit tests, I think, are a great way to get fast feedback on something as well. UI tests, those tend to get a little bit slower.

[00:32:34] Now, sometimes some UI tests suites, you know, may even take hours to run. So those are not necessarily the greatest way to get feedback. Those are something that might fit well in say, your continuous integration. Right. And I think this, again, so this is coming back to earlier, just like why continuous integration is important and sort of making sure that steps, like say running your UI tests don't get missed before you say go to QA or maybe get your final approvals.

[00:33:02] Because those types of feedback to take even longer sometimes than running some of those tests earlier, right. So I think that's where continuous integration fits in ultimately, is that you kind of want to make sure there's some steps that's making sure that's doing that proofing and giving you feedback as soon as possible.

[00:33:17] Because sometimes you ship something to QA and QA can't look at it until tomorrow, and then, you know, four hours later, then they give you the feedback and then you iterate on it. So really you want to be sending things to QA as perfect as possible. So yeah, again, just thinking about that feedback loop, what kinds of things can I get the feedback on the fastest to help me with my iterations before I go to the slowest things. CI, I think kind of fits somewhere nicely in the middle, like after I've done my work, but before I start sharing it out with the greater team, I want to have my continuous integration feedback loop in place.

[00:33:53] Leo Dion (Host): So you're saying like when it comes to the pipeline between the developer and QA, continuous integration kind of fits in there to kind of facilitate and help QA give you feedback, but on a much quicker timeline. Does that sound right?

[00:34:08] Kyle Newsome (Guest): Yeah, absolutely, and I mean continuous integration can even help with the pull requests or code review process itself.

[00:34:15] Like I'm really big on automating as much analysis as possible really so that even when it comes to requesting that your peers review code. They're not, you know, nitpicking on - Oh, you left it to do comment in here and Oh your spacing isn't quite right here. Cause those aren't really exciting things. And I don't think they contribute super positively to the culture to be nitpicking at code where you really want to automate those things.

[00:34:39] To help just kind of make sure everyone's code is in line and then let the team work on some of the higher level analysis of like, Oh, this is an interesting implementation, but if you use this trick, you might save, you know, five lines of code or something like that. Like that's the kind of feedback I want from peers.

[00:34:54] So CI, yeah. Can help do some QA before you get to your QA, and it can also help you do some code review before it even gets to your peers.

[00:35:01] Leo Dion (Host): Really interesting. I like that a lot. And then I guess let's just touch on it, but like the elephant in the room to a lot of this setup with continuous integration is fastlane.

[00:35:11] And I don't know if there's any other apps you'd recommend, but like I met Felix, I want to say like about a year and a half ago, and he was super nice. He's super into security now. I don't know if you've watched or gone to any of his talks, but he's really into. Man in the middle of tax where you can like have software that kind of listens into your traffic or all that kind of stuff, which I think is super important.

[00:35:34] We don't really talk much about, but like Fastlane has been around. I don't know since when, but it's definitely automated. A lot of like the app store API stuff and a few of the other things. What other benefits does Fastlane have, and especially when it comes to continuous integration, what does it bring to the table?

[00:35:53] Kyle Newsome (Guest): Yeah, so I mean, Fastlane has like a ton of different types of tasks you can run with it.

[00:35:59] Leo Dion (Host): And it's available for both iPhone apps and Android apps, correct?

[00:36:03] Kyle Newsome (Guest): Yes, it was iOS support first, but I believe it does all sorts of Android stuff now as well, too. But I don't feel like it's just added so many different tasks and all sorts of ways to communicate also with the Apple or like App Store Connect in order to help like get team members set up so it can do things even sort of outside your system of helping you just get your team set up. I recently worked on a team that had a good fast lane setup for helping people get. The configurations they needed, like pull down the development profiles that they needed just to run things on the simulator, sort of all automatically.

[00:36:38] That was something I actually hadn't seen Fastlane used before. So even beyond CIA, it just has tasks that are really useful to automate for an iOS team that maybe don't need to run more than every time you add a new developer to the team. But beyond that also, yeah, just full of lots of different tasks you can do to build, test the application on pure version number, take screenshots.

[00:36:59] And one other. I think very important thing to think about. Sometimes when you set up what's going to be happening in your continuous integration process, you can sort of choose - Oh, am I going to write the tasks that it's going to do? Am I going to configure those in the continuous integration system itself, or am I going to try to push as much of that configuration into my code repository, like commands for Fastlane to run.

[00:37:26] And the benefit of keeping it in your repository is that the developers have more control over it. Like I mentioned that example earlier where when I was working with a bank, the dev ops team was in charge of the CI, so really we wanted to put as much into Fastlane as possible because that's where we had more control over changing what targets were being built, et cetera, versus if we had put that into the CI system, we would have had to go through a much slower process in order to make changes to our build configurations.

[00:37:56] So yeah, putting things in Fastlane, I think helps developers keeping control of it. And you can also think about vendor lock-in.

[00:38:03] If you were saying, moving between. Maybe you're using a third party service and then you decided - Hey, I want to actually move to self hosting, or vice versa. Or say you're using Travis and then you decide, no, I'd prefer BitRise. If you have most of your commands in Fastlane, it's going to be easier to move between these services because you've used far less of the vendor oriented configurations.

[00:38:28] Leo Dion (Host): Yeah. You talked to a lot of people in server-side development, and I'll tell you, like vendor lock in has become a big deal on their end. So it's only a microcosm of that issue when it comes to like continuous integration services when it comes to iOS development so I can totally understand that.

[00:38:43] Kyle Newsome (Guest): Yeah vendor lock in for like server side is way, way more of a problem then what I'm talking about. But I mean, it's not even so much vendor lock in. It's just like, Oh - it's going to take me a little bit of time to get from this service to this service. But like the server side, people are dealing with like serious, like costs associated with moving their services over like nothing we see on our side.

[00:39:02] Leo Dion (Host): Right, exactly. Well, thank you so much for coming on. The show is really, really great to talk about this topic. I think it's super important and I'm glad we covered it. Going back server-side people have been doing this for awhile, but like when it comes to iOS stuff, I think, and watch and Mac and TV there, I always forget that one.

[00:39:21] I think this is a topic along with a test driven development that people should really engage with and integrate into their team. And where can people find you?

[00:39:29] Kyle Newsome (Guest): On Twitter? I guess @kylnew - it's just like the first three letters of my first name, first three letters of my last name. Other than that.

[00:39:36] Also, I have a website, pyrus.io that I do consulting through. I blog on there occasionally. I haven't blogged recently. Otherwise I'm just in the community in Toronto trying to run meetups and ran the SwiftTO conference just this past summer, which you spoke at about Vapor. Yeah.

[00:39:57] You can find me around Toronto, go to a Toronto Swift meetup and you'll probably see me there.

[00:40:01] Leo Dion (Host): Yes. And if you miss a meetup, you're doing the video work on those, aren't you?

[00:40:06] Kyle Newsome (Guest): Yeah. As much as possible. And trying to film all the meetups going on in Toronto, just because we did a survey from the conference and got feedback from people and definitely saw from even the conference feedback that like people find it hard sometimes to come into the city. Unless I'd say I like a full day of content. So trying to find ways to distribute more video content so that it's available to those who can't make it downtown for our meetups.

[00:40:31] Leo Dion (Host): I'd love to check those out. And Swift Toronto was a great conference. so we'll see if you guys do it again. So

[00:40:39] Kyle Newsome (Guest): hopefully I'll try to polish up the details.

[00:40:41] Leo Dion (Host): Yeah, yeah. Fantastic. Thanks again for joining us on this episode and we look forward to talking to you in a couple of weeks. Thanks again.

[00:40:51] Kyle Newsome (Guest): Take care. Thank you.

Thanks to our monthly supporters

  • Steven Lipton

★ Support this podcast on Patreon ★

Chapters

Code Reviews

A code review is when someone other than the code’s creator reads the code, looking for errors or anything unclear. While simple to do, this often gets missed because it takes time to sit down and review code someone else has written —time you might feel you don't have. Having someone review what you’ve written is a great way of spotting mistakes and ensuring better-quality code.

Continuous Integration

This is something I’ve written about previously, explaining what Continuous Integration (CI) is and why it’s important. If you can deploy code frequently, it means you can deliver features more rapidly.If there are problems or bugs, you discover them earlier and faster. CI is also a great way to shorten the time it takes to get feedback from your users.

The Components of Good iOS Software Architecture

By putting in the time to think through the architecture for your app using effective patterns and modularity, as well as following good code quality practices, you will find:

  • bug fixes become easier;
  • adding new features becomes straightforward;
  • your app becomes easier to test and maintain; and,
  • your developers will have an easier time understanding the code.

I believe these are things we should all try to observe. You’ll find it not only improves the morale of your developers but also saves you loads of time and money in the long run.