Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Road To Damascus, or FRP and Me

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Abizer Nasir Abizer Nasir
September 14, 2017

The Road To Damascus, or FRP and Me

Presentation I gave at NSSpain 2017 about my thoughts on Functional Reactive Program and whether I should use it.

Avatar for Abizer Nasir

Abizer Nasir

September 14, 2017
Tweet

More Decks by Abizer Nasir

Other Decks in Technology

Transcript

  1. I like to keep things simple • MVC • Dependency

    Injection, protocols, value types • Storyboards • Core Data
  2. Functional Reactive Programming • Reactive: Treats data as a flow

    over time rather than individual events. A sequence. • Functional: map and filter and reduce can be applied to these sequences - the things we like about Swift
  3. Not a good starting point “The RepositoryListViewController is also a

    delegate and a data source for the table view. It handles the navigation, formats model data to display and performs network requests. Wow, a lot of responsibilities for just one View Controller!”
  4. Events only have three states public enum Event<Element> { case

    next(Element) case error(Swift.Error) case completed }
  5. Events are emitted when an Observable is subscribed to Think

    of subscribing as repeatedly calling next() an an Iterator.
  6. “Flattens Asynchronous Code” By that I mean they are treated

    as the same thing. • A single value injected into a View Controller • The text in a Text View • The response from a network request.
  7. Validate UserName & Password, Classic final class ViewController: UIViewController {

    @IBOutlet private var name: UITextField! { didSet { name.addTarget(self, action: #selector(validate(_:)), for: .editingChanged) } } @IBOutlet private var password: UITextField!{ didSet { password.addTarget(self, action: #selector(validate(_:)), for: .editingChanged)} } @IBOutlet private var confirm: UIButton! @objc private func validate(_ sender: UITextField) { let name = self.name.text ?? "" let password = self.password.text ?? "" confirm.isEnabled = !name.isEmpty && !password.isEmpty } }
  8. Validate UserName & Password, RxSwift class LoginViewController: UIViewController { @IBOutlet

    private var name: UITextField! @IBOutlet private var password: UITextField! @IBOutlet private var confirm: UIButton! let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() let username = name.rx.text.orEmpty.asObservable() let password = password.rx.text.orEmpty.asObservable() confirmButtonValid(username: username, password: password) .bind(to: confirmButton.rx.isEnabled) .disposed(by: disposeBag) } func confirmButtonValid(username: Observable<String>, password: Observable<String>) -> Observable<Bool> { return Observable.combineLatest(username, password { (username, password) in return !username.isEmpty && !password.isEmpty } } }
  9. Observable<Bool> can be - .next(Bool) - .error(Error) - .completed Looks

    a lot like Result<Bool, Error> - .success(Bool) - .failure(Error)
  10. Composition searchBar.rx.text .orEmpty .filter { $0.characters.count > 3 } .debounce

    { 0.5, scheduler: MainScheduler.instance } .map { query in let url = URLBuilder.urlFor(query) return URLRequest(url: url) .flatMapLatest{ request in return URLSession.shared.rx.json(request: request) .catchErrorJustReturn([]) } .map { json -> [Model] in guard let items = json as? [[String: Any]] else { return [] } return items.flatMap { Model.init } } .bindTo(tableView.rx.items) { tableView, row, model in let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") cell.configureWith(model) return cell } .disposed(by: disposeBag) h/t Marin Todorov @icanzilb
  11. The code is in one place. It is readable, the

    order is determined and easy to reason about.
  12. It’s a Big DSL • RxSwift for FRP • RxBindings

    for working with UI elements • RxTest
  13. It’s a Large Dependency • Active project with many contributors

    and users. • Easily installed with CocoaPods or Carthage, but these are the days of Xcode transitions. • You don’t have to use it everywhere, but if you’ve added it...