Getting Stuck

Where’s the first place you go to when you get stuck on a programming problem? Stack Overflow most likely, but what if there’s nothing there to help you? Do you go to Medium in hopes someone wrote a blog post about that very obscure thing you’re working on? Well, this happened to me recently when I was finishing the last part of refactoring We Read Too’s suggestion view.


Working full time as a developer is very different than working on a solo project. At work you have your team to bounce ideas off of and if you get stuck you often have several other people to help you figure out your issue. When you want to merge new code into the app, you’ll do a code review with one of your teammates which hopefully teaches you how to improve your approach. Being on a team of other programmers helps you grow as a programmer. Side projects on the other hand are sometimes done solo. How can you make sure you’re still growing while working alone?

You have to ask for help. It may sound simple, but asking for help can be daunting. Working alone does give you the flexibility to make whatever decisions you please but if you get stuck it can be very frustrating which is why a lot of side projects never get finished. Many folks in the development community who are passionate about their work on are willing to answer your questions if you just reach out, whether it’s by email or Twitter DM. If that doesn’t work there’s always Stack Overflow or publicly asking a question on Twitter or in a forum.


So here’s where I got stuck. I needed to create an Observable<String> that my view controller would subscribe to in order to display an alert that shows the user whether or not sending the suggestion form worked. I decided to use RxFirebase to write the form to my database, but RxFirebase returns an observable of a database reference.

As shown above, I created a class, FirebaseService, where I’m going to add all the methods that interact directly with my Firebase database. My point of confusion was related to the Observable<DatabaseReference>, I know that if the write transaction succeeds then the observable will trigger an onNext event and if it fails the onError event will trigger. The issue is, I don’t want my view controller to subscribe to the Observable<DatabaseReference>, I want that to be abstracted and only have my view model return the success or error string to the view controller.

Now I could get these events by subscribing to that observable in my view model, but my view model does not have a dispose bag (nor do I want it to, since I want my view model to just provide observables to a consumer, the view controller, which does the subscriptions). So how do I get my view model to consume the onNext and onError events without subscribing? I didn’t know. So I decided to ask Shai Mishali, a well-known iOS developer in the RxSwift community. He was incredibly helpful and provided me with suggestions on how I can use PublishSubjectflatMap, materialize and RxSwiftExt to solve my problem.

From his suggestions here’s what I came up with for my view model’s intializer:

Let’s break it down. Before the view model had an empty initializer but now we initialize it with my FirebaseService class as a parameter. The formData combines all inputs into one Observable<(String, String, String)> which will come from text fields and a picker view. Title, author and category are all PublishSubjects. A PublishSubject emits items to a subscriber only after they’ve subscribed. I was using BehaviorRelay subjects before, but because my text fields have no initial value, I can use PublishSubject.

We make the request by using sendButtonTapped which is a PublishSubject<Void>. The withLatestFrom operator gets the latest item emitted by a given Observable.  To ensure that we don’t make multiple request for the same data, I am using the distinctUntilChanged operator which suppresses duplicates. Then we use the flatMapLatest. Here’s a diagram from bacon.js that shows the difference between flatMap and flatMapLatest:

 

 

flatMap takes each emitted item and turns it into a new stream whereas flatMapLatest overwrites the previous stream so there is only one stream to subscribe to.

The data I’m passing into the processForm method is a simple Encodable struct I created so it can be turned into JSON and sent to the database. After the Observable<DatabaseReference> is returned from processForm I use the materialize operator which takes the emits items and turn them into events (onNext, onError, onCompleted). The last operator I use is share, which allows you to have multiple subscriptions to one observable.

This is where RxSwiftExt comes in handy. RxSwiftExt is a library that provides convenience operators separate RxSwift in order to avoid bloating the RxSwift library. The two operators we’re using are elements and errors. Defining my outputs, successMessage and errorMessage, you can see why the operators come in handy, now I am able to send the right message to my view controller according to the events emitted from the Observable the RxFirebase method returns.

What’s Next

That wraps up the suggestion view (for now!). Next up I have to pull the book data from Firebase and insert it into a collection view. I also want to connect these different views using a Tab Controller so you can tab from Books, Search and Suggestion.

 

Refactoring to MVVM with RxSwift

kyle_blog_pic.png
Source: Manu Cornet

Every developer has that moment of realization when you look at your code and barely understand what it’s suppose to do or how it got to be so many lines long. This doesn’t mean you have to completely start from scratch, but it’s important to be open to refactoring parts of your code. The point of refactoring is to make your code more understandable, testable and/or modern.

This is the first post of many where I’m going to share the refactoring process for my app, We Read Too, along with the patterns, libraries & tools I learn along the way.


When I first started learning iOS development four years ago, the design pattern I learned was MVC which stands for Model View Controller. The following diagram shows the user interaction an MVC pattern:

1200px-MVC-Process.svg
Source: Wikipedia

If you’re learning iOS and rely on Apple’s documentation you’ll notice that they follow the MVC pattern. Over time as your app grows it’s easy to write all the logic for your app into the view controller which leads to extremely large classes that are hard to test and hard to understand (commonly known as the Massive View Controller).

A different design pattern that has grown in popularity recently is MVVM which stands for Model-View-ViewModel. The view model allows the business logic to be decoupled from the view controller. That way our view controllers stay small and focused on the UI. The view model usually doesn’t import UIKit and has no knowledge of the view or view controller. This allows the view model to be unit testable. The model is usually a struct or simple class that represents the data.

1*iwgAHz3uZGqyk3OhOOjgyg
Source: icetime17

Following the MVVM pattern doesn’t mean your code will be perfect. Just as you can have massive view controllers, you can also have massive view models. You don’t have to use one design pattern throughout your whole app, it depends on what’s works best for the functionality you’re trying to implement.

Reactive programming

In the MVVM diagram above you there are terms like “data and user action binding”, “updates”, and “notifies”. How do you actually implement those relationships in MVVM?

Many developers model those relationships through reactive programming. Reactive programming is a paradigm that has existed in software development for decades that allows developers to write  declarative code focused on asynchronous data streams. Check out this great documentation written by Andre Staltz that goes into more explanation. Reactive extensions (Rx) are how reactive programming became popularized especially in mobile development.

Why am I learning Rx? Users expect modern apps to be responsive. Thinking of everything as streams with inputs and outputs makes sure there is always a reaction to any change that comes in whether it’s a user action or network request. Reactive programming uses an Observer design pattern where a subscriber “listens” to a stream (the observable). For more on reactive programming and RxSwift specifically, watch this great talk by Shai Mishali or read the documentation.

Red, green, refactor method for testing

I wrote earlier about how testable view models are, but how will we test them?

I’ve decided to use the Red green refactor method created by John Shore. This ensures I’m following a TDD mindset when writing my code. The tests are written before the logic is completed and you write the logic to conform to the tests. Once the tests are passing you find ways to improve your code without breaking the tests. Kickstarter follows this method in their codebase and you can watch this video to see how it works. They use ReactiveSwift and have written their own test helpers. I’m using RxSwift and found a Cocoapods library that has been very useful called RxExpect.

Implementing the refactor

Now that we’ve laid the ground work for understanding the basics of what MVVM and reactive programming are, let’s get into beginning implementation of refactoring my app We Read Too which is written all in Swift.

We Read Too is a book directory app with the following features:

  • a collection view that displays the books filtered by age category
  • search by author, title or description
  • a detail view that shows the specifics of a book with data pulled from Goodreads and allows the user to share the book or view it on Safari/Goodreads
  • a suggestion view that allows the user to send a suggestion of a title that should be added to the directory.

The database (recently moved to Firebase) contains all the books and can be updated at anytime with new data or changes on existing data.

For the refactor I started with the suggestion view because it is the least complex and will help me build my comfort level with writing code in MVVM reactively. In later posts I’m going to cover how I refactor the other parts of the app and how I improve the code over time.

View model inputs / outputs

I decided to adopt the functional input-output approach to view models inspired by Kickstarter. The inputs and outputs are protocols which make easier to test and very readable.

The SuggestionViewModel adopts all three of these protocols and is a final class so that it cannot be inherited. For each of the inputs there is an associated BehaviorRelay subject (formerly known as Variable) which is used to transform the observed inputs into outputs.

Tests

Before we implement the logic for the outputs, we write our tests.

The first three tests above are all testing the functionality of the submit button which is only enabled when there is text present in the title and author text fields in our view. The last test is for the alert message after the submit button is pressed.

Logic for the view model

Now that we’ve got our tests, we have to write the logic to get them passing. We do this in the init method of the view model.

First, we combine the streams from the title text field and the author text field using the combineLatest operator which makes a tuple of the emitted values. We use the sample operator which will emit the most recent events from a given Observable. In this case we need the alert message when the submit button is pressed. Using a helper method isPresent which checks the length of the given text, we filter so that we give the alert message only when the text is present. For more on Rx operators check out this post.

Lastly we need the observable for knowing when to enable the submit button. When the view loads the submit button should not be enabled and then we want to monitor the form data and if isPresent returns true then the button will be enabled. With these two values merged we’re listening for both values and you can see that in how our tests are implemented above. Now when we run our tests, they pass!

View controller binding

Now that we’ve got our logic passing our tests, it’s time to actually connect it to a view. We create our view controller with two UITextFields, a UIButton, and a reference to a view model. Then in viewDidLoad we add targets that are initialized with the following selectors:

This makes sure all the logic is abstracted from our view controller. We pass any user interaction in as inputs to our view model. Next we need to use the observables from our view model’s outputs.

For the alert message observable we create an alert controller for every value that’s emitted and display it. For the submit button we bind our view model output to Rx control property for UIButton, isEnabled.

Lastly, we trigger our view model input for viewDidLoad.

What’s next

This is only the start! We’re not finished with refactoring the suggestion view. The only functionality we have set up is ensuring that the user has inputted text into the the title and author fields so we can enable the button that would trigger sending their suggestion.

We need to add another field to the form. The user has to pick a category their book suggestion matches to; picture book, chapter book, middle grade or young adult. We’ll do this with an Swift enum and UIPickerView that’s connected using RxSwift.

You also may notice that the send button logic is not actually finished. We’re not actually sending anything! And where’s our model? Next we need to create the model object from the form data and send it off to Firebase.