Recent Posts | Archive


Simple Reactive: Notifier

After trying out simple KVO, I wanted to try assigning a single property to each observableclass that would emit events when something changed. I liked this idea because it would, in theory, require very few changes to the actual observable class, and could thus live separately from it, such as in an extension or in a subclass even. To keep it simple, I opted to not worry about sending the current (or previous) value, as KVO does, and instead just let observers know that something changed, and make them investigate.

The event emitter, which I’ve called Notifier, might look like this:

class Notifier<T> {
    typealias NotificationCallback = (T) -> Void
    var notificationCallbacks = [NotificationCallback]()

    func observe(_ callback: @escaping NotificationCallback) {
        notificationCallbacks.append(callback)
    }

    func send(_ value: T) {
        for callback in notificationCallbacks {
            callback(value)
        }
    }
}

Consider our previous example of having a Person class with observable first and last names, and a ViewModel that puts the pieces together for its view.

To our really simple Person class, we’d add a single, public Notifier instance, where the generic T is a Swift enum containing the field name that changed.

enum PersonProperty {
    case firstName, lastName
}

class Person {
    var notifier = Notifier<PersonProperty>()
    var firstName: String { didSet { notifier.send(.firstName) } }
    var lastName: String { didSet { notifier.send(.lastName) } }
}

Then, our View Model would just register a handler with likely a switch statement to decide what to do:

class PersonViewModel {
    var personNameText: String

    //...

    func bindPerson() {
        person.notifier.observe({[unowned self](property) in
            switch property {
            case .firstName:
                self.firstNameChanged()
            case .lastName:
                self.lastNameChanged()
            }
        })
    }
}

Benefits

As noted above, this method hardly changes the observed class at all. The only changes necessary are adding a Notifier instance, adding a swift didSet hook to each observable property, and defining which properties can be observed in an enum. There is zero dependence on Foundation, NSObjects, or Objective-C.

Costs

Unfortunately, there are some very real costs.

Reference Counters

To be able to stop observing, you’d need to probably create a class containing a callback and some way to identify it. Then, like with KVO, you’d need to keep a reference to it (or its identifier), and when you no longer want to observe, you’d have to tell the Notifier to remove it. I wound up doing this for subsequent patterns, meaning this problem isn’t unique to this pattern.

Initial Values

Remember in my KVO post how I noticed that getting an initial value was pretty nice? Without some modification, this pattern won’t do that. I wound up getting around this fairly easily, but it wasn’t pretty.

class Notifier<T> {
    func observe(_ callback: @escaping NotificationCallback, withInitialValue initialValue: T? = nil) {
        //...
        if let initialValue = initialValue {
            callback(initialValue)
        }
    }
}

enum PersonProperty {
    case .initial, ...
}

class PersonViewModel {
    func bindPerson() {
        person.notifier.observe({[unowned self](property) in
            //...
        }, withInitialValue: .initial)
    }
}

Rating: C+

The simplicity of this approach goes a really long way. In many cases, where there’s really only one observer, you could make the notifier instance optional, and set it to nil to effectively stop observing, the initialize a new one when you need to. But it just requires too much funny business to make it practical, like passing in that initial value when observing.

Still, I think we may be onto something with this pattern, and I’m excited to explore some more options before we can take the best of all of them!

#permalink

Simple Reactive: KVO

My initial thought when considering how to build a reactive model without any dependencies was to use iOS Foundation’s KVO, or Key Value Observing. Baked into anything inheriting from NSObject is a mechanism to observe changes at key paths of a specific object.

For example, let’s suppose we have a Person model that has a first and last name. If we want to observe changes to either attribute, we need only mark them as dynamic, make them available in objective-c, and tell the instance that we want to be told when the value changes.

class Person: NSObject {
    @objc dynamic var firstName: String
    @objc dynamic var lastName: String

    //...
}

And then in the ViewModel, where we want to build a string for our View to observe:

class PersonViewModel: NSObject {
    private var firstNameObserver: NSKeyValueObservation?
    private var lastNameObserver: NSKeyValueObservation?

    //...

    private func observePersonAttributes() {
        firstNameObserver = person.observe(\Person.firstName, options: [.initial, .new], changeHandler: {[unowned self] object, change in
            self.firstNameChanged(change.newValue as? String)
        })
        lastNameObserver = person.observe(\Person.lastName, options: [.initial, .new], changeHandler: {[unowned self] object, change in
            self.lastNameChanged(change.newValue as? String)
        })
    }
}

Benefits

KVO is (probably) already there! It will manage your observers, it will send events on change.

You can also specify if you want your callback executed with the initial value or only new ones. This may seem like not a big deal, but as we explore other patterns for reactive programming, it’s a pretty big plus.

Costs

Doing this has quite a few requirements, so let’s walk through them.

Objective C

KVO depends entirely on meta-programming, because it observes changes to objects at key paths. Swift doesn’t like meta-programming, so this all needs to happen in the Objective-C under the hood. This requires a simple dynamic declaration for each observable property, as well as an @objc export.

In practice, this doesn’t matter too much. You can still write your app in Swift, and leverage the compiler to make sure you’re observing real keypaths. But it does mean some extra casting.

Note: Swift makes this a bit safer than it used to, telling the compiler to verify that the key path used actually exists (previously it was a string, which of course guarantees a mistake at least once).

Type Constraints

…but the real bummer about requiring objective-c is that your observable types need to be representable in objc. So, if, for example, you want to observe changes to a Swift enum, you’ll need to instead use monitor its raw value.

NSObject

KVO’s observe method lives in NSObject. So your models need to extend NSObject. That’s a drag.

Other Notes

  • Observing will continue until your NSKeyValueObservation instance is deallocated. This is important! If you do not retain a reference to it, it will stop observing; if you retain a reference to it, your callback better be able to run
  • If you don’t know the difference between unowned and weak (or - gasp! - either), then take the time now to read up on the difference. Because if you refer to self in your callback, you probably want it to be weak or unowned, else you’ll have circular references
  • Have I mentioned the importance of retaining or destroying references?
  • This one was too obvious to list as a cost, but this does require Foundation. That doesn’t matter for iOS/macOS projects, but if you’re running a swift app elsewhere, that may not be desirable.

Rating: B-

The fact that all of this comes right out of the box is pretty hard to beat. But I really don’t want to introduce dependencies if I don’t need them. And the fact that NSObject#observe, the method used above, was introduced within the last year, makes me very wary that there may be other interface changes. Furthermore, for many of my projects, the inability to use Swift types not available in Objective-C is a deal breaker.

#permalink

Simple Reactive Programming

Two years ago I wrote an iOS app that leaned heavily on ReactiveCocoa. Going from MVC to MVVM with a framework like ReactiveCocoa was to me a life-changing experience, so much that I was willing to relax my strong feelings against third party dependencies to be able to do it.

The app has several hundred daily active users across a handful of countries, but juggling a toddler, full time job, and a side project meant the time I could afford to maintain the app generally went to improving the reliability of the backend serving it real time data.

My daughter is now almost two, and can entertain herself, so recently I’ve been working on bringing my side projects back into the foreground. I sat down a few weeks ago to add a watch complication for this app, and lo and behold, it wouldn’t even build. The version of ReactiveCocoa the app is locked to was, at the time, their first release to support Swift 3 syntax, which uses now-deprecated iOS APIs, making it impossible to build. But updating requires a significant rebuild of my app, given how dependent it is on the framework.

I complained to a friend and long time iOS developer, who said he’d never built anything reactive in iOS that didn’t depend on either RxSwift or ReactiveCocoa/ReactiveSwift. I took that as a challenge, and quickly drafted a few Swift Playgrounds using different patterns that would allow for easy reactive programming, with zero dependencies, and simple enough that they were unlikely to break with subsequent iOS or Swift updates.

Stay tuned for a few different patterns I tried, what I like about them, what I don’t, and my ultimate conclusion about whether I’ll stick with my own code, or if I’m just reinventing the wheel.

Continue reading!

  1. Key-Value Observing
  2. Notifier
  3. Observable Properties: Post coming soon, but here’s a teaser
#permalink

LXC Containers

My Adventure With LXC Containers

Over the last week or so, I’ve been playing around with LXC containers, low level virtualization containers in Linux. (Specifically, I’ve been using LXC version 2.0.9 with Ubuntu 16.04, on a cheap Digital Ocean box I setup for my experiment.)

Basic LXC Usage

Installation

First, in case you want to play along, installing LXC is incredibly easy:

$ sudo apt-get update && sudo apt-get install lxc

Handling Containers

Create containers from a given template. For most of my playing around, I used a base ubuntu template, but you can find far more with apt-get install lxc-templates.

# lxc-create -n container_name -t template
$ lxc-create -n webserver -t ubuntu

Each container lives in /var/lib/lxc/$CONTAINER_NAME. Exploring this directory shows how simple a container really is:

$ ls /var/lib/lxc/webserver
config
rootfs/

The config is created automatically, as is the root filesystem. By default, containers don’t start automatically, but you can change this easily by adding the following to your config:

lxc.start.auto = 1

Henceforth, you can start your container either by specifying which container to start, or by autostarting all of your containers based on their autostart settings:

$ lxc-start -n webserver
$ lxc-stop -n webserver
$ lxc-autostart

Connecting to your container is easy as pie. Either enter a console session from the host, or setup ssh as you would with any other Linux machine, except that your container is living in virtual private network, and thus only accessible from the host or with some port forwarding.

# lxc-console -n $CONTAINER_NAME
$ lxc-console -n webserver

If you’re going to connect to your container remotely often, you may want to setup ssh forwarding. On your local machine, add the following to ~/.ssh/config:

Host my_webserver_host
  User myuser
  ProxyCommand ssh -q host_container  nc -q0 private_local_ip 22

Here’s what my ssh config looked like:

Host host_container
  HostName 123.123.123.123
  User root

Host appname
  User deploy
  ProxyCommand ssh -q host_container  nc -q0 10.0.3.96 22

Then I could ssh using ssh appname or ssh deploy@appname, which would first connect to my host container as a proxy, which would forward traffic to my app container. (Note: I added keys to both machines to avoid dealing with passwords.)

Notes

  • Containers don’t autostart by default. Which is good! But easy to forget.
  • Containers use DHCP on a virtual private network. You can make it a bit easier to connect by adding a line in /etc/hosts, but either way, you’ll probably want to set the container’s IP to be static if you plan on connecting to it in any way other than lxc-console (see update below to connect by hostname)
  • Containers use DHCP by default, so if you plan to do this often, you’ll want to set your container’s IP to be static (in /etc/network/interface).
  • Containers, by default, use the same filesystem as the host. But you can also set them up to use different filesystems, such as btrfs. The benefits are pretty mindblowing.

What I Learned

LXC Containers are pretty incredible.

As a result of my little experiment, I’m running three rack applications on a single host, using a container for each application (which contains only the code base, rbenv, and unicorn, running on the only open port other than 22 for ssh), a container for nginx, which forwards requests to the appropriate container by hostname (bonus: I only need to setup pesky ssl stuff once!), and one container running postgres.

I can easily constrain resources on any container to ensure something going haywire doesn’t affect the others. I know each is secure and walled off, so there’s no risk that a process on one could, say, overwrite part of another’s filesystem, or kill off any processes.

At any given time, I can clone one of the application containers and add it to my nginx upstream and I’ve got built in redundancy, or, if I’d rather move it to a different machine, I can do so easily by exporting the container to a new machine and merely changing my nginx config to look at that IP.

What I Really Learned

But realistically, this isn’t any different than running each of these five services on their own servers. What I really learned was that containerizing web applications has some really tremendous benefits.

Historically I’ve tended to put all my applications on their own server: each had source code, database, webserver (plus passenger/puma/unicorn for rack apps), a user for sudo stuff, a user for deploys and sometimes running the webserver. For really small websites, I’d setup several as virtual hosts on the same machine. This approach was easy and familiar, and pretty cost effective.

But over the years I’ve built so many small side projects. In fact, my exploration into LXC containers was because I built emoj.es (a stupid website that takes emoji and makes them into a big image, so when you share links in chat apps, they’d get a huge image as a “preview”, making your emoji nearly full screen), and couldn’t justify spending $7/mo for Heroku, or $5/mo for a new Digital Ocean droplet, and it was so stupid a site I didn’t want to risk affecting any of my other side projects.

Docker

Docker is all the rage right now. Probably even moreso than the latest javascript framework that … wait for it … just ceased development. Docker takes this containerization idea and automates lots of it. In fact, it sounds like if you know what you’re doing, it’s pretty incredible. And, unlike LXC containers, you can run them on Mac OS X, so your development environment matches your production environment more closely. (It does this by running vagrant and VirtualBox behind the scenes. If you do this yourself, you can run LXC containers locally too.)

I played with Docker for a few hours and learned a couple things, which ultimately resulted in my choosing LXC containers instead:

  • Most of the base images everyone uses are marked as vulnerable. That doesn’t give me a warm and fuzzy feeling.
  • Most of the base images are created and maintained by people who have little incentive to keep them around, which makes me very worried. Worse, they change all the time, so unless you – and they – are extremely careful about versioning, you risk small changes in your environment any time you run your deploy. (This is true for just about any package management (side note: a third party library we use at work removed and recreated a tag on github, so the same locked version had different behavior), but particularly scary when you’re talking about environments.)
  • It took me forever to do basic things. Specifically, I wanted to start with a base Ubuntu image rather than the vulnerable ruby one, and it took me nearly three hours to get a new version of ruby installed. With apt-get on ubuntu, the same task took me 15 minutes.
  • Docker is really bad about permissions and security. If you’re using docker, I highly recommend you check whatever images you’re using that you didn’t write, and see how much is running as root.

But there’s one thing Docker does that my now-beloved LXC containers don’t: it automates provisioning and configuration. I tend to do that either as a set-it-and-forget-it because I’m lazy, which doesn’t do well over time, or with bash scripts that get grosser and grosser over time. This is better with containerized applications, though, because the steps to configurate a server are fewer and fewer. But it’s still a problem I wouldn’t consider solved (for me).

Conclusion

If you like Docker, awesome. If you like LXC Containers, that’s awesome(r). If you’re like I was, installing the full stack on a single box for your app, then, well, you’re livin’ in the past, man. I’ll never go back.

Moving the components of my application into different containers (whether servers, LXC containers, whatever) made me think more about how they talk to each other, what they need to run effectively, and how to isolate possibly vulnerabilities. For my more significant applications, like the API for Station to Station, I can have one machine with different containers, which I can easily scale, clone, whatever, as my needs change. Or for my smaller side projects, I can share resources by having a single webserver forwarding traffic to each application, a single database that I can backup or add slaves to, and I can keep costs way down by doing so on fewer machines.

Either way, if you host web applications, this is something worth looking into.

Also, I really love Linux.

Update

Turns out you can connect to LXC containers by hostname pretty easily.

  1. Install dnsmaq with sudo apt-get install dnsmasq
  2. On Ubuntu 16.04, update /etc/default/lxc-net to set the top level domain. The default is lxc, which you can set by uncommenting the line LXC_DOMAIN="lxc".
  3. Restart the LXC net service sudo service lxc-net restart
  4. Add forwarding by editing /etc/dnsmasq.d/lxc and adding server=/lxc/10.0.3.1 (this is /etc/NetworkManager/dnsmasq.d/lxc.conf for Ubuntu 14.04)

Then you can connect using ssh user@container-name.lxc, or verify using dig container-name.lxc

#permalink

It’s now 2017, almost 15 years since I met (and have since exceeded) my thousand mile goal. A very dear friend of mine recently has had the same urge for going. Like me, he grew up in Chicago, but he never drew a circle with a big radius around it. Instead, he’s had his sights on New York (Chicago’s older, grumpier brother). We’ve known each other for a few years, and I’ve always known about this dream of his, and, with my memory as bad as it is, I must’ve told him this story a dozen times.

He finally made the jump, and is leaving next week. We had a ceremonious last supper, when this story, again, came up. And the next day, he decided to look up the quote. (I have no idea why this never occurred to me. I could say it was too magical and important to me to ruin, but mostly it just never dawned on me that it was more than some World Market doodad the Hyatt installed in all their hotels.)

So, I love that quote you frequently recite: “Man travels the world in search of what he needs and returns home to find it.” So much so, that I looked up the guy who wrote it. And I couldn’t help but notice something…

My friend, last week

I panicked when I received his message, worried it was Bruce Springstein. (Really.)

Time Traveling Novelist (Not Bruce)

Fortunately, it wasn’t a Bruce quote!

It was from a dude named George Moore, a novelist from the late 19th century, who, according to my friend, looks a bit like me. Then he asked if I was a time traveling novelist. With great enthusiasm, I decided to research the answer to this question, knowing full well that I don’t currently have the ability to travel through time.

I managed to find an old photo of me from around when this quote so changed my course in life. Here’s that photo, as well as George Moore’s portrait on Wikipedia:

Me and the other me, aka George Moore. Note that the photo of me, on the left, was actually taken around the time I read that quote.

I did a quick informal poll of people who know me pretty well, and on a scale of 1-10, the average response was a high 7 for visual similarlities.

Time Lord? (Still not Bruce)

It then dawned on me that for the last five or so years, I’ve been dressing up for Halloween as Matt Smith’s Doctor Who, a Time Lord. (Rarely known fact: I have worn and loved bowties ever since I borrowed one for that first Halloween.)

Let’s take a look at those alongside each other as well:

Me and the other me, aka Matt Smith as Doctor Who. Taken on Halloween, 2016.

Greetings!

In conclusion, greetings from the future! I cannot tell you how I did it, but somehow the future-me was able to return to 1879 and 2011!

Further, I used what I learned in 2011 to say something famous in the late 19th century, that managed to influence me in 2011 to go back and say it before!

Even more, I probably knew that what I said in the 19th century would influence my friend in 2017 to tell me about my other selves so I would know to go back to 2011 and read that placard! Amazing.


Now I just need to find where I left the TARDIS

#permalink

View Archive