Categories
Uncategorized

New habits I haven’t dropped in 2018

I just came back from a casual 4.5 mile run in the rain and I feel terrific.

Before blogging on this website, I wrote all my personal blog content on the Day One app. It’s my safe haven for notes, thoughts and feelings I live that I prefer to keep private.

One promise I made to start 2018 off was to start the new year being more physically active in ways I haven’t tried before. I’ve been playing basketball my whole life, and most of it was ultra-competitive practicing and chaos.

So I started 2018 by attending a boxing class. The cover image above is an image of Overthrow, a boxing studio down in down at Soho, NY.

I’ll admit, a big reason that made achieving this resolution way easier was the emergerce of fitness class marketplaces like ClassPass. I think I would have been way more relunctant to indulge in a cycling class had it required a dedicated studio membership.

So I cycled more often. I also ran more too, but more on that later. I dabbled a little with rock climbing. (To be fair, I lived directly under a Brooklyn Boulder gym in Long Island City so it’d be sad if I didn’t).

If you’ve tried ClassPass before in the New York City area, you’ll begin to realize strength training, cycling/treadmill and yoga classes account for most options on the platform. I wish there were more options for team sport activities like volleyball or soccer, but I think that’s a genal issue with NYC constrained space than it is ClassPass.

I was actually going to jump right into running and talk about why it’s been growing as a casual passion, but thinking more about cycling and bouldering, I actually have more love so spread.

Rock Climbing/ Bouldering

With all these activities, keep in mind I’ve only scratched the surface of each of them, so these feelings are based just on early experience.

In indoor bouldering, there are rocks and groves of many, many colors splattered across many, many walls. The goal of the game is to simply put two hands on a flagged rock, usually at a high point of a wall. The challenge is, your hands and feet can only touch certain rocks, usually based on the flagged rock’s color.

This sport is unlike any physical activity I have ever encountered. Its pace is akin to the structure and flow of chess if you were thrown into the middle of a match.

While I’m sure you need to think fast in competion due of time constaints, my takeaway as a novice (with limited grip strengh) was that a lot of consideration needs to go into the first moves you make. When I didn’t, I ended up stuck, unsure, and energy inefficient since my grip strengh was depleted by the seconds. And fall.

Boundering gave me an appreciation for positional techniques to best leverage my body while hanging onto a very little surface area.

I didn’t even mention the element of fear. I really do want to try the outdoors one day, but as a novice… even jumping onto a soft mat 12-15 feet off the ground can be a bit nerve-wrecking. I don’t know the science, but there’s a direct correlation with the amount of time you stay calm to the stamina of your wrists and grip. If you panic, you just feel Spiderman with his powers taken away all of a sudden.

Photo by Mike Kotsch / Unsplash

Cycling

I have a hard time with cycling/treadmill/fitness classes because I zone out really fast if the music is not rap, trap or hip hop. I never understood how other people in the class holler in excitement after a tough stretch— you were focused the whole time? One time I walked out of a fitness class 15 minutes in, because I couldn’t stop thinking about a code problem at work. (I walked out and across the street back to the office to relieve the distraction.)

Anyways, despite the lack of focus I put into classes like Peloton Studio, cycling at Peloton is my default class for ClassPass. I appreciate the personal intensity you can set your bike to, as well as a well-lit instructor in the middle of the room. I must admit, I think the real reason why Peloton is my workout of choice is the customer service and amenities. Something as simple as a free branded water bottle to go alongside your workout stands out to me.

peloton chelsea

2019

This year, I’m hoping to learn a thing or two about Soccer. Again I wish ClassPass offered more sports based classes in the NYC area, but in the meantime I’ll just have to learn on my own!

Categories
Uncategorized

Making network requests more reactive with RxMoya.

The Rx ecosystem is strong. Before RxSwift, I used a brittle wrapper of an “Observable” type in my codebases, just so I could “subscribe” to values. It was really helpful to start, as I personally saw the benefits of being able to bind value changes to your UI, or any side effect really.

It worked to begin with, but then I realized:

  1. My wrapper had 0 tests
  2. My “Observable” lacked access control features. anything could observe and push values to an observable stream.
  3. RxSwift is way more popular and does what I want… times 1000

So if you’re like me and you’ve added reactive paradigms like RxSwift to your codebase to slowly introduce yourself to Observables, you’re probably still confused. Because the learning curve is STEEP.

RxSwift artwork from RayWenderlich.com

Fortunately, I spend without thinking on educational resources like raywenderlich.com and Egghead.io, where there’s plenty on content about Rx in iOS, Android and JavaScript.

I’ve written briefly about Moya, networking library that sits on top of Alamofire, and how to get started with the library way back. (It’s actually my most viewed blog post, yet the tutorial is so outdated, sorry.)

It’s a great library, and aside from some desolate areas in SuperFit iOS where URLSession is used here and there, Moya does a really great job with extending a codebase’s networking requirements from various endpoints, or “providers” in Moya speak.

One big mistake I’ve been making with having both Moya and RxSwift in my codebase is that I’m manually wrapping Moya requests and operations inside an Observable.

In the code block below, I am making a network request to a remote resource that returns “Sections”; With the sections data, I want to persist the models, as well as append any client-side sections, such as a tool-tip, to my list before ultimately handing it off to a ViewController to render.

self.listSections = fetchCatalogSectionsProperty.asObservable()  .flatMap { (_) -> RxSwift.Observable<[ListDiffable]> in
    return RxSwift.Observable<[ListDiffable]>.create({ observer -> RxSwift.Disposable in
      programCatalogManager.fetchAndCacheCatalogSections(liveOnly: !AppEnvironment.current.authorizationManager.isAdmin, { (result) in
        switch result {
        case .success(let sections):
          var sectionsToShow = [ListDiffable]()
          // add catalog sections
          let orderedCatalogSections = Array(sections).sorted(by: {$0.title < $1.title})
          sectionsToShow.append(contentsOf: orderedCatalogSections)
          observer.onNext(sectionsToShow)
          return
        case .failure(let error):
          throw error
        }
      })
      return Disposables.create()
    })
}

I used to have a sensitive instinct to drying up code or refactoring code smells, but more recently, I accepted that I cannot spend too much time figuring out the better way to do something on lines of code that really don’t matter in the grand scheme of a business.

However, regarding this code block, and the 10 others places in my code where I manually encapsulate network requests in observables, it was finally time to consider a smarter approach and figure out how I could make the networking layer more “reactive”.

And. yeah, the answer is literally in Moya’s repo. They have Rx extensions you can use, aliased as “RxMoya”. Instead of pod Moya in your Podfile, simply change that to pod 'Moya/RxSwift'.

This is what my code block looks like now using observable network requests with RxMoya.

func fetchAndCacheCatalogSections(liveOnly: Bool)-> Single<[CatalogSection]> {
  let endpoint: CatalogSectionService = liveOnly ? .getLiveOnlyCatalogSections : .getAllCatalogSections
  return catalogSectionService.rx.request(endpoint)
    .map { response -> [CatalogSection] in
      do {
        // Core Data Stuff here
        return sections
      } catch let error {
        AppEnvironment.current.logger.print(error.localizedDescription)
        throw CatalogManagerError.errorDecoding(CatalogSectionRemote.self)
      }
  }
}

And what the caller of fetchAndCacheCatalogSections looks like:

self.listSections = fetchCatalogSectionsProperty
  .flatMap({ (_) -> Observable<[CatalogSection]> in
    return programCatalogManager.fetchAndCacheCatalogSections(liveOnly: !AppEnvironment.current.authorizationManager.isAdmin).asObservable()
  })
  .map({ (sections) -> [ListDiffable] in
    var sectionsToShow = [ListDiffable]()
    // add catalog sections
    let orderedCatalogSections = Array(sections).sorted(by: {$0.title < $1.title})
    sectionsToShow.append(contentsOf: orderedCatalogSections)
    return sectionsToShow
  })
  .asDriver(onErrorRecover: { (error) in
    print(error.localizedDescription)
    let request = AppEnvironment.current.coreDataStack.fetch(request: CatalogSection.defaultFetchRequest())
    guard let cachedSections = request.result else {
      return Driver.just([])
    }
    let sortedSections = Array(cachedSections).sorted(by: {$0.title < $1.title})
    return Driver.just(sortedSections)
  })

Instead of fetchAndCacheCatalogSections calling back with the actual response, I now begin with a request Observable from RxMoya,  and I perform response data parsing and transformations in a map against the observable. Finally, CatalogSectionListViewModel, the struct that invokes fetchAndCacheCatalogSections maps the observable once more to attach any additional UI sections beyond the data from the network, then returns a `Driver` (an observable with specific traits), which my view controllers can then consume.

Using RxMoya freed me up from having to ever create an Observable type myself. (Of course, creating the observable needs to happen somewhere; in this case; RxMoya is doing that in its extensions, but I don’t see it, which is all that matters~).

I’m clearly able to fetch my data, map my data, and centralize error handling with observables and some Rx goodies like Driver and Single.

In the end, all my view controller needs to do is subscribe and bind to its viewmodel’s list observable and render a collection view.

catalogSectionListViewModel.outputs.listSections.drive(onNext: { [weak self] sections in
      self?.uiSections = sections
      self?.adapter.performUpdates(animated: true)
      self?.feedRefresh.endRefreshing(updates: nil, completion: nil)
    }).disposed(by: bag)

For all the IGListKit fans out there, you may be thinking… there’s are Rx extensions for IGListKit as well. Until then, progress is better than nothing— I’ll get there when I get there!

Categories
Uncategorized

About Me

Hi, I’m Leo and I enjoy sharing stories, thoughts, and photos as I navigate through life.

Quick facts about me

I went to college for Exercise Science and started out as a strength coach for sports teams at New York University. I took a leap of faith three years later and taught myself how to code and build software for mobile apps.

What I’m doing now

Now I’ve taken another leap and am working full time on SuperFit, a workout app for people who really want to become better at their sport.

Starting a business has a ton of highs, but five times more lows. That’s something one of my closest friends, Brian, knows too well when he started his own gym a year ago in Long Island, NY. He’s the founder of T3 Performance gym, and it’s no coincidence that we synced up six years to help each other grow our businesses.

I’m helping Brian make T3 one of the most welcoming sports gyms in NY, while he’s providing me the platform to iterate and build SuperFit with my target audience in house.

Fun Fact: As “gym roommates” in college, Brian and I may have spent more time working out and playing basketball together than focusing on classroom lectures.

SuperFit is in the app store now and I’d love feedback if you have any. check out the free app here.

Categories
personal work

What I learned building a fitness app as a personal trainer-turned computer programmer.

The fitness industry does not need innovation.

I’m Leo and three years ago, I pivoted from pursuing a three-year post grad degree in Physical Therapy at New York University to learning how to code. Prior to that, I worked at NYU as a part-time strength and conditioning coach for its Division III athletes, and as my first job out of college, it was a dream come true.

nyu_leo_kwan

Graduating from SUNY Buffalo with a degree in Exercise Science, I always wanted to train athletes and work in the athletic world. I interned around the country as a student, and I was a disciple to industry leading coaches and organizations in sports performance.
I was never tech savvy growing up, but I considered myself a nerd to anything I put my interests in. You know, that person who learned through the textbooks and came off a bit awkward to others because that person thought he knew everything. That was me (might still be, I hope not).

I was a student of the game.

I graduated college in 2013, and immediately, I went straight down to Pensacola, Florida for a summer internship with Athletes Performance, now named EXOS. Athletes’ Performance (AP) was regarded as the cream of the crop of sports performance gyms in the US. They trained the best collegiate and pro athletes in all major sporting organizations, particularly American Football.

athletes_performance

I learned a whole lot interning at AP. I won’t get into detail but it was a top notch facility with world class coaching. Side note: growing up in NY and living in Pensacola for 3 month— big culture change.

Coming out of college and internships like EXOS, I thought— why isn’t smarter coaching content available for other sportsy people out there? There are a ton of people like myself who wished they had trained more effectively at a younger age. Can technology solve the problem?

I had an idea

Two years into working as a strength coach at NYU, I realized there should be an app for this. I didn’t know how to code, but in my spare time I learned how to make a website and create mockups like the banner image above.
The idea was called Atrium, and it was a fitness app that would bring teammates together to train as a team, thus the “atrium” name. Awful name, but a lot of motivation.

But what about my career? In the meantime, I was wrestling with my future career trajectory and quickly trying to figure out how I would generate a steady income. Physical Therapy seemed like the clear direction for me. I loved fitness and sports performance, but juggling NYU and personal training at Equinox was hard.

Physical Therapy seemed like the clear direction for me.

Back at EXOS, I was inspired by the sports medicine staff, particularly the athletic trainers and physical therapists. Their work on athletes looked so novel and, for lack of a better phrase, intellectually challenging. It seemed fitting for me, so I looked into Physical Therapy as my next endeavor after strength conditioning.
But what about my idea?
I spent a year completing remaining prerequisite classes (bio 1 & 2), punching in volunteering hours at the hospital and perfecting admissions essays for NYU and Duke’s Doctorate of Physical Therapy program. I was ready to put my idea to rest and move on with a new chapter in my life.
Then… I got rejected by Duke’s early decision process. I was distraught and pretty disappointed. During that time, I remember simply thinking about two things.
I had to focus on getting into NYU. It was the only other PT program I applied to besides Duke, and if I didn’t get in, I’d need to wait an entire year to reapply.
I stumbled upon a free online class about technology entrepreneurship by Stanford.

This class changed my life.

There was nothing ground breaking taught, but for someone like myself who had never took a computer science course, it spun my mental model harder than any other class I took in my life. I eventually got the acceptance letter into NYU, but I had already made my mind. I was going to opt out of Physical Therapy to learn how to code, and ultimately, build my app.

“Atrium” was the initial name of my business. Before I even knew how to code, I sketched out exactly how I wanted my fitness app to look. For future entrepreneurs, don’t do this. Move and adjust quickly.


Fast forward to today

This is personal and hopefully anyone who traveled a similar path can understand its difficulties.
I left strength conditioning, NYU and the fitness world to pursue a field I wasn’t entirely sure about. I learned how to code, got a tech job, and continued building my app in my spare time. I said I would never want to get too involved in tech, just enough so I could build my product and move on. But the truth is when you want to be great at anything, you cannot help but pour every ounce of effort to stand out. I did that with fitness, and I’m trying to do that with software development and technology.
Even though I never hoped to stray far from my passion for sports, programming has opened so many doors for me. I’ve made incredible friends and colleagues in tech that I can’t imagine not meeting. I’ve also developed a new set of skills, particularly computer programming and deep problem solving, that I really lacked before I wrote my first line of code in 2015.


The toughest lesson I had to learn

Up until now, I thought technology would save the day. People use mobile apps and I know how to build them. Innovation in website development has moved really fast, and some web applications just blow me away every time I use them. Big tech buzzwords like AI, AR, machine learning, and deep learning have sprung up in the last three years, and companies like Google, Apple and Facebook are racing to be at the front of these domains.
As a programmer who writes code 40 hours a week, I’ve also adopted the mindset that better software equals better business, and that if I want my apps succeeding in the fitness industry, I, too, need to build smarter technology and take the lead in this innovation race.

Wrong.
Coaches and trainers just need to be better coaches and trainers. Athletes need to be attentive, trust their coaches and put the requisite hours in the gym and in their sport. I’ve spent so much time focusing on the wrong things, because I often forget the core needs of coaches and athletes.

Coaches and trainers have to problem sharing their content on a google excel sheet. Even less complicated than that, I’ve seen coaches share static word documents outlining their premium workout program. This is a really tough lesson I’m learning to swallow: do not add innovation where it is really not needed.


If you’re interested in what I’m building, follow me @imleokwan and check out SuperFit for free on the app store.