WordCounter v1.6 Brings Analytics to Your Productivity!

My stats for October 2019. Didn’t notice I wrote that many words in emacs.

The WordCounter update to v1.6 is online! It brings the long-awaited statistics module so you can get an overview of your productivity over any period of time. It also comes with a CSV export of the visible data.

Download the free update!

Export and the aggregate numbers will be expanded in future updates. The stats currently supplement the daily calendar history, but the history will be obsoleted as I move the daily details into the analytics part itself.

Here’s what my last 365 days looked like:

My stats for the last year.

When did I write that many words in TextMate?! It’s almost on par with Xcode. I bet it’s mostly for the book update from September …

Focusing on TextMate only for the same period. See the 7000 spring at the end of August?

Turns out that, apart from the time when I churned out the update in TextMate, Xcode was pretty much present every day. It’s a very steady companion, boringly so, even when I look at 2 years of data:

Xcode programming output for the past 2 years.

In early 2018, I was working on The Archive furiously. It’s a greenfield app, so everything I typed was new and paved the way for future structural changes. Nowadays, I have to adhere to the same structure in my code and either replace things carefully, or add to existing code. It’s less a first draft-like writing frenzy and more like a careful surgical operation. Still I’m bummed one can see the change in programming mode before and after v1.0 public release so clearly!

Alright, enough playing around with the numbers. I hope you enjoy this free update and find it as useful as I!

Get the new version of the WordCounter

X-Oriented Programming, Using Functions or Classes?

Working on a greenfield project is nice, but it also brings up all the uncertainties of the start: which components, modules, objects, interfaces do you need?

With Swift, you even have to decide if you want to design the system in an object-oriented or a functional way. As far as the core functionality is concerned, you do have this choice. (When it comes to UIKit/AppKit, you don’t.)

Thinking in objects, my tool of choice is OOP. But then I end up with classes that have 1 initializer with 2 dependencies injected, and 1 method that calls the dependencies to carry out some functionality. The very same method could be a free function.

class Foo {
    let bar: Bar
    let baz: Baz

    init(bar: Bar, baz: Baz) {
        self.bar = bar
        self.baz = baz
    }

    func perform() {
        baz.compute(bar.currentFizz())
    }
}

// or 

func perform(bar: Bar, baz: Baz) {
    baz.compute(bar.currentFizz())
}

If there are side-effects, both the class and the function will need a handler, e.g. a closure like completion: (SideEffect) -> Void. Again, this works for both cases.

With the class-based approach, the dependencies are injected upon object initialization. If Foo is a long-lived service object, that can be very early in the app’s lifetime. Afterwards, you only need to call the perform method. If the completion handler is injected on call time, you get a nice separation of the parts that change and the parts that stay the same.

With functions, in a naive approach, you have to inject everything at the same time: at call time. So the knowledge trickles down from app launch to the actual call site.

But this isn’t really true. You can prepare partial function applications in much the same way as you would with constuctor dependency injection:

typealias SideEffectHandler = (SideEffect) -> Void
func perform(bar: Bar, baz: Baz, completion: SideEffectHandler) {
    let result = baz.compute(bar.currentFizz())
    completion(result)
}

let bar: Bar = ...
let baz: Baz = ...
let preparedPerform: (SideEffectHandler) -> Void = { completion in
    perform(bar: bar, baz: baz, completion: completion)
}

preparedPerform() { /* side effect processing */ }

That’s also what you can use currying for, for example.

Which path do you choose?

I tend to stick to classes and protocols because of testing. I use mocks in my unit tests as replacements for dependencies and result handlers. It works because I can test every object in about the same way.

With a purely functional approach, you can test the functional units just as fine, but the function compositions not so much. They turn into integration tests of sorts, where you validate a couple of important paths, but not all possible combinations of the underlying parts, because that would duplicate the unit tests and be a combinatorial pain. Since integration tests are a scam when used to verify the system, it’s pointless to even try to get all their combinations right; you get far more value by testing units at their seams.

I prefer similar-looking object boundaries and similar-looking tests in most parts of my application instead of attempting to implement VIPER with pure functions.

This is not a recommendation. It stems from my cluelessness, really. How could I make this different, and better? I don’t know, yet, but I sense that this is a problem that I can eventually solve.

See also:

Win32 API Programming With Swift

With some luck, all my Windows programming wet dream might actually come true one day. There’s progress on making Swift available on Windows, and there’s progress on providing a Win32 API wrapper for Swift so you can share model code across platforms and write UI for Windows and Mac separately.

Check out the GitHub repo: https://github.com/compnerd/swift-win32

It’s experimental, but apparently way less experimental than it was a year ago!

ExactScan Leaves the Mac App Store

Berlin-based company ExactCODE, makers of ExactScan and OCRKit, experiences trouble with Catalina and a rather short time to submit bug fixes for their app before the public release of Catalina earlier this month. They decided to leave the Mac App Store behind:

  • each manual update review by Apple causes delay and drama
  • AppStore does not support paid upgrades, only new App, in-App purchase or subscriptions
  • Apple takes 30% and that is not sustainable to run a company and pay salleries
  • it is not provide to provide free updates forever
  • if you purchased our application this year we provide a direct license, if you had it significantly longer, we think a paid upgrade is fair for continuously developing, improvements, and support

[…]

There is mostly only one benefit [of using the MAS] for users: one central place for purchasee and updates. However, there are many negatives, such as: […]

I don’t know if they could’ve done more to prepare for the macOS upgrade. Recently, folks on Slack shared screenshots, and it turns out that as a serious Mac developer you apparently have external hard drives full of previous and future macOS versions, plus a stack of different Xcode versions (that are no longer available for download by Apple!) – that’s required by virtually everyone in order to support multiple OS versions and fix bugs. The Catalina beta also was very flaky.

After releasing the Catalina Golden Master build to developers on October the 3rd, we immediately finished fixing any new crash or issue we could find over the weekend. In our opinion, leaving developer just four (4!) days over a weekend with a public release on October the 7th is not very helpful nor professional.

They have a point here. But could they have fixed the same bugs earlier in preparation of the Golden Master release?

The call for App Store submissions went live on October 3rd, too, at the day of the Golden Master release. So even if they fixed all the bugs early, Apple would have had only 4 days to review all App Store submissions, which sounds like a bad idea nevertheless.

See also:

Shameless plug: I also wrote a book on selling outside the Mac App Store in case you want to leave the App Store, too, or make your company more resilient through availability in multiple stores.

Reducing the Blog Post Email Digest To Once a Week

After a couple weeks of experimentation, I find that twice weekly email delivery of my recent blog posts is one too many. I wrote a lot in the past months, so each issue contained quite a few links. But who wants more email with less links in it? I don’t, so I changed the interval to weekly, delivered every Thursday, covering a summary of the whole past week.

If you missed updates and haven’t subscribed to the blog via RSS, I strongly suggest you take a look at the blog post digest newsletter delivery service.

Model-View-Presenter, Form Validation, and a Unidirectional State Machine

As an exercise, I wrote a simple iOS scene transition from a login form (root view controller) to a success scene. I was experimenting with the Model-View-Presenter approach where view and presenter know each other, but communicate through protocols, so you program to an interface, not the implementation. I ended up using a simple state machine to represent the view’s state, and employed form validation that is represented in the types. I like how the result reads, so here’s a rundown of the exercise:

  • Recap of MVP on iOS
  • State machines
  • Uni-directional flow of event, state updates, and view changes

Model-View-Presenter Revisited

The suggested approach was awkward at first, but not that bad once I got the hang of it. The view is dumb, so the view’s protocol exposes methods like show(title:), display(loginError:), and change(borderColor:ofFormElement:) that allow the presenter to control what’s displayed on screen in fine detail.

Here’s an example from Fabrizio’s original post:

class ProductsPresenter {
    // ...
    func onStart() {
        productsView.show(title: "Products")
        productsView.showLoadingStatus()
        productsRepository.get { [unowned self] retrievedProducts in
            self.tryToShow(retrievedProducts: retrievedProducts)
            self.productsView.hideLoadingStatus()
        }
    }
    // ...
}

The presenter here controls the view’s contents in fine detail, and also gets data from a repository that holds model data. With the VIPER architecture pattern, you’d be splitting up the Presenter and Interactor at this point at least.

I found that my own presenters usually just pass a view model to the view and let the view handle its own configuration. While that keeps the presenter slim, it moves some of the display logic to the UIViewController. Having that logic removed from the view controller was a nice change, even though I now want to refactor the presenter some more to minimize its impact. Shifting the logic might be a good idea for future refactorings.

LoginCredentials Model

With regard to the login form, I started with the Swift form validation code I wrote about last year.

I started with LoginCredentials:

struct LoginCredentials {
    let email: String
    let password: String
}

Then I used the validation code from last year to wrap this as a Partial<LoginCredentials>. Through Swift key-value-mutations, I could start with an empty Partial() and reflect the user input from the email and passwort UITextFields through partial.update(\.email, to: newValue).

I’ll show you details in a second, but let me add another requirement first.

Login Form State Transitions

The login form should show email and password fields, and a “Login” button that’s deactivated at first. When the user enters valid data into both fields, the button is enabled. Upon tapping, an activity indicator is shown. While the request is active, the button changes to “Cancel”. On success, the other scene is displayed; otherwise, an error is displayed, the activity indicator is hidden again, and the button offers a “Try Again”.

So these are the real elements of the scene:

  1. Email text field
  2. Password text field
  3. Button
  4. Activity indicator
  5. Multiline error label

You will also have noticed that the HTTP login request affects what the button does. At first, it triggers a login request; during the request, it offers a cancellation; after a failed request, it offers to retry. Upon success, this scene is reset and replaced.

So the whole scene can have multiple states. This is how I’d enumerate the states:

  1. Initial
    • Email text field is blank
    • Password text field is blank
    • Button shows “Login” and is disabled
    • Activity indicator and error are hidden
  2. Invalid form input
    • Email text field is blank or not a valid email
    • Password text field is blank
    • Button shows “Login” and is disabled
    • Activity indicator and error are hidden
  3. Valid form input
    • Email text field contains a valid email
    • Password text field contains something
    • Button shows “Login” and is enabled
    • Activity indicator and error are hidden
  4. Pending request
    • Email text field is uneditable
    • Password text field is uneditable
    • Button shows “Cancel” and is enabled
    • Activity indicator is visible
    • Error label is hidden
  5. Failed request
    • Email text field contains a valid email
    • Password text field contains something
    • Button shows “Try Again” and is enabled
    • Activity indicator is hidden
    • Error shows failure reason
  6. Successful request
    • Email and password are cleared
    • Button is reset and disabled again
    • Activity indicator and error are hidden
    • Transition to a new scene is triggered

Okay then, so the login scene can be represented by a state machine! The state, which I was adventurously naming “view model”, can look like this:

enum LoginViewModel {
    case initial
    case unvalidatedLogin(unvalidatedCredentials: Partial<LoginCredentials>)
    case validatedLogin(loginCredentials: LoginCredentials)
    case requestPending(request: LoginRequest)
    case requestFailed(request: LoginRequest, message: String)
    case requestSucceeded
}

The rules to determine if a Partial<LoginCredentials> contains valid user input boil down to non-empty input plus validating an email for its email-ness. Here’s a very simple test for the “@” sign, which I don’t suggest you use, but should give you an idea:

let loginCredentialValidation = Partial<LoginCredentials>.Validation(
    .required(\LoginCredentials.email),
    .required(\LoginCredentials.password),
    .valueValidation(keyPath: \LoginCredentials.email, { $0.contains("@") }))

With these rules, we can now transition from .unvalidatedLogin(unvalidatedCredentials:) to .validatedLogin(loginCredentials:). The result of the validation itself is a LoginCredentials object. Here’s a snippet from the state machine effect:

switch self.loginViewModel {
// ...
case .unvalidatedLogin(unvalidatedCredentials: let unvalidatedCredentials):
    // Ensure the view is in the proper state
    view.hideError()
    view.hideActivityIndiator()

    // Validate input ...
    switch loginCredentialValidation.validate(unvalidatedCredentials) {
    case .valid(let credentials):
        // ... and transition to a new state
        self.loginViewModel = .validatedLogin(loginCredentials: credentials)

    case .invalid(let reasons):
        // ... or display validation errors, e.g. by coloring text fields
        self.displayValidationErrors(reasons: reasons)
    }
// ...
}

Improving the State Machine to Separate State Transitions from Side Effects

I still refer to Andy Matuschak’s “A composable pattern for pure state machines with effects” because it teaches so many interesting things at once.

For example, a state machine there has a method called mutating func handle(event: Event) -> Command?. It is mutating because the event processing affects the state the machine is in. (Thanks to it being an enum value type, this does not affect existing references.) It also produces an optional Command, which is a side effect that is supposed to be consumed by another object.

Look at the transition from unvalidated to validated credentials above. In terms of a mutating state machine with clean separation of side effects, I want to show you a sketch of the transition in Andy’s much better approach.

Here’s the changed state machine: it still sports the same cases, but now also has Event and Command types. The example I will discuss pertains user input for the email text field to keep the example small enough to be grasp-able:

enum LoginViewModel {
    // ...
    case unvalidatedLogin(unvalidatedCredentials: Partial<LoginCredentials>)
    case validatedLogin(loginCredentials: LoginCredentials)
    // ... more cases here ...

    enum Event {
        case emailChanged(String)
        case passwordChanged(String)
        // ... more events for the other cases ...
    }

    enum Command {
        case showInvalidInput(onEmail: Bool, onPassword: Bool)
        case showValidInput
    }
}

The event handler then takes the current state into account, plus the event, and implements state transitions plus optional side effects.

For example, when the input is invalid, and the user types into the email text field, the new text field’s text should be reflected in the state. Also, since this is supposed to update live, the updated state should trigger a validation pass to make it possible to transition from invalid to valid state. The validation needs to happen both when the input is known to be valid and invalid, because input can invalidate everything again, of course. In this example, typing an “@” will validate the email field, and removing it should invalidate it again, resulting in a proper state transition.

So I extract the validation into a helper method further down in the following example code:

extension LoginViewModel {
    mutating func handle(event: Event) -> Command? {
        switch (self, event) {

        // Validate credentials live when typing
        case (.unvalidatedLogin(var partial), .emailChanged(let email)):
            // Reflect the changes
            partial.update(\.email, to: email)
            return self.validate(partial: partial)

        // Invalidate credentials again when changed
        case let (.validatedLogin(credentials), .emailChanged(email)):
            var partial = Partial(from: credentials)
            partial.update(\.email, to: email)
            return self.validate(partial: partial)
        // ...
    }

    // Same rules as above
    static let validation = Partial<LoginCredentials>.Validation(
        .required(\LoginCredentials.email),
        .required(\LoginCredentials.password),
        .valueValidation(keyPath: \LoginCredentials.email, { $0.contains("@") }))

    /// Extracted validation code that is used multiple times in
    /// `handle(event:)` for live input validation.
    mutating private func validate(partial: Partial<LoginCredentials>) -> Command? {
        switch LoginViewModel.validation.validate(partial) {
        case .valid(let credentials):
            self = .validatedLogin(loginCredentials: credentials)
            return .showValidInput

        case .invalid(let reasons):
            self = .unvalidatedLogin(unvalidatedCredentials: partial)

            let emailIsInvalid: Bool    = // filer when keyPath == \.email in reasons
            let passwordIsInvalid: Bool = // filer when keyPath == \.password in reasons
            return .showInvalidInput(onEmail: emailIsInvalid, 
                                     onPassword: passwordIsInvalid)
        }
    }
}

With the side effect separated from the state change, a consuming service object can carry these out and update the view.

Implement the Presenter to Update the View and Carry Out Side Effects

Given a view that satisfies the following protocol to change the UI:

protocol LoginView {
    func hideError()
    func display(error: String)

    func change(buttonIsEnabled: Bool)

    func change(activityIndicatorIsVisible: Bool)
    func indicateInvalidInput(onEmail: Bool, onPassword: Bool)
    func indicateValidInput()
}

Then a presenter that owns the state and processes state transitions on email input can look as follows:

class LoginPresenter {
    var viewModel: LoginViewModel
    var view: LoginView

    // Called by the view controller
    func emailChanged(value: String) {
        self.updateState(event: .emailChanged(email: value))
    }

    fileprivate updateState(event: LoginViewModel.Event) {
        let oldState = viewModel
        let command = viewModel.handle(event: event)
        self.updateViewTransition(from: oldState, to: viewModel)
        self.process(command: command)
    }

    fileprivate func updateView(from oldState: LoginViewModel, to newState: LoginViewModel) {
        switch (oldState, newState) {
        // Example: Button toggling when input turns valid/invalid
        case (.unvalidatedLogin(_), .unvalidatedLogin(_)),
             (.validatedLogin(_), .validatedLogin(_)):
             break // Keep as-is
        case (.unvalidatedLogin(_), .validatedLogin(_)):
            self.view.change(buttonIsEnabled: true)
        case (.validatedLogin(_), .unvalidatedLogin(_)):
            self.view.change(buttonIsEnabled: false)

        // Example: Activity indicator
        case (_, .requestPending(_)):
            self.view.change(activityIndicatorIsVisible: true)
        case (.requestPending(_), _):
            self.view.change(activityIndicatorIsVisible: false)

        // Example: Error display
        case (_, .requestFailed(_, message: let message)):
            self.view.display(error: message)
        case (.requestFailed(_), _):
            self.view.hideError()
        }
    }

    fileprivate func process(command: LoginViewModel.Command?) {
        guard let command = command else { return }

        switch command {
        case let .showInvalidInput(onEmail: emailIsInvalid, 
                                   onPassword: passwordIsInvalid):
            // E.g. turn text field borders red, 
            // show "X" for invalid input, ...
            self.view.change(buttonIsEnabled: false)
            self.view.indicateInvalidInput(
                onEmail: emailIsInvalid, 
                onPassword: passwordIsInvalid)

        case .showValidInput:
            self.view.change(buttonIsEnabled: true)
            self.view.indicateValidInput()
        }
    }
}

Of course email input is not all there is, so I extracted updateState(event:) as a reusable private event handler. You can call it from a method like passwordChanged(value:), too, and also pass in events when the button is tapped.

Refactoring the Presenter

With a setup like this, the LoginPresenter can be further refactored into multiple components. The view updates upon changed from previous to next state can become the presenter, while another object can carry out side-effect execution. Since the side-effects here affect the UI, it doesn’t make much sense in my book to split the presenter into multiple objects at that seam.

It does make sense to me to split LoginPresenter and LoginEventHandler in two, though, with one reacting to UI callbacks like emailChanged, sending events to the state machine, and the other handling the view updates and side-effects as a pure projection of the state.

If you take this further, you end up with a uni-directional flow approach that is very similar to Flux/Redux and ReSwift: an event handler forwards events to an object that owns the state, called “Store”, and the store informs subscribers about the state updates. Here, we only have 1 subscriber, and the state changes are local. But the approach is very similar in principle once you begin to untangle the objects and clean up the control and information flow.

  • A LoginViewModelStore is a service object that holds on to the state. Someone has to, and this concept is as good as any. Could also remain in the presenter, if you want.
  • The LoginEventHandler produces objects of type LoginViewModel.Event and forwards these to the store.
  • The LoginPresenter is informed by the store about state changes and commands.

A sketch in code:

enum LoginViewModel {
    /// ... as above ...
}

class LoginViewModelStore {
    let presenter: LoginPresenter
    var state: LoginViewModel

    func process(event: LoginViewModel.Event) {
        let oldState = state
        let command = state.handle(event: event)
        self.presenter.updateViewTransition(from: oldState, to: viewModel)
        self.presenter.process(command: command)
    }
}

class LoginPresenter {
    let view: LoginView

    // Expose the change handlers directly that were private before

    func updateViewTransition(from oldState: LoginViewModel, to newState: LoginViewModel) {
        // ... as above ...
    }

    func process(command: LoginViewModel.Command?) {
        // ... as above ...
    }
}

class LoginEventHandler {
    let store: LoginViewModelStore

    func emailChanged(value: String) {
        store.process(event: .emailChanged(email: value)
    }

    // ... other event handlers ...
}

Do you have any suggestions to improve the setup further? Do you actually like this less than earlier stages, or putting everything into view controllers? I’m curious to hear what y’all come up with in this situation.

Xcode Bug Turns Out To Be the Hardened Runtime Setting

What I called an Xcode bug last week turned out to be a broken project configuration that was absolutely my fault. Back when Hardened Runtime was introduced, I switched it on at the Xcode project level, not just for the app target. When you set “Enable Hardened Runtime” on the project level, all targets inherit this setting: the app, the unit tests, and the UI tests. With Xcode 11, it now turns out that hardening the runtime for the test runner broke an internal library lookup in perfect accordance with the utility of the Hardened Runtime settings.

Disabling Hardened Runtime for the UI tests “fixed” them and I can now continue to work on The Archive, right after I finished the feature update to the WordCounter that I’ve started work on in the past weeks.

Happy news, but also stupid me.

Fix Missing Font Fallbacks for NSTextView

Rich Siegel recently wondered on Slack why NSTextView would suddenly display empty placeholders for some glyphs when the font does not support them, instead of falling back to a safe font like it usually does. Chinese characters never got displayed. Michel Fortin remembered a similar problem, and the potential fix was quite simple:

In summary, if you have to change the font after the text storage was edited, do it in willProcessEditing and it’ll do the right thing. Don’t do it in didProcessEditing.

That turned out to be what tripped up Mr Siegel’s text view, which now happily displays CJK/CJKV again. For more details and some background about how you can detect this problem in your apps, read Michel’s post.

Building a Rich Domain In Iterations

I’m currently revising code from 3 years ago. The result is a replica of the old stuff – updating isn’t worth the effort, it’s written in Swift 3 and the code base is small, so I rewrite it and copy useful parts over. The public interface already differs from what I wrote 3 years ago.

In the first step, I translated the old code but took what was there. For example, back then I had a DateRange type. Swift Ranges were less powerful back then, so I added a couple of convenient methods that I can now replace with the standard library protocols instead. So I demoted the type to typealias DateRange = Range<Date>. I also had a Date type (this was before NSDate dropped the ”NS”) that I renamed to NormalizedDate. In the domain I work on, a date isn’t a date-time-combination, but just the year, month, and day. Confusingly, this type was a mere wrapper for NSDate that dropped the time information for quick comparisons.

Later, as I worked on the protocols that this module would expose, I figured that the notion of a “range of days” is missing. Sure, Range<NormalizedDate> did the job, but a DayRange type was better. It’s became a RawRepresentable, backed by Range<NormalizedDate>.

After this change, though, I found the name “normalized date” too general. Sure, I am normalizing the date-time to drop the time information completely. But I really want to work with a Day-date type. So I introduced Day, which is backed by a NormalizedDate and specifies its own normalization rules. This is oddly satisfying. The Day type knows the normalization rules to create a NormalizedDate from a regular old NSDate.

As I write about all this, I notice that I should’ve made an additional step and replaced Day with a struct that has year, month, and day only and constructs NSDates where needed, instead of relying on that type to represent its values. Excuse me for a bit while I change the domain to accommodate this insights.

Prevent Emacs Compilation Window From Displaying Other Content

By accident I found a setting for emacs windows that prevents a window from displaying any other content than what it currently is showing. It is not locking the textual contents but the buffer. That means you cannot show the contents of another file, or change the currently visible help page, or whatever.

And, just what I needed: you can prevent the small compilation results window from changing contents. Sometimes I have the compilation window focused and want to look at a code listing; now the code listing would open inside the tiny compilation window!

To prevent this, you can lock a window to its current buffer by making it “dedicated”. Call the non-interactive function (set-window-dedicated-p WINDOW t) to enable this, and (set-window-dedicated-p WINDOW nil) to disable this again.

I added it to the code where I create the compilation window to limit its height to 10 lines of text, and enable the flag after the window’s buffer is configured:

(setq compilation-window-height 10)

(defun ct/create-proper-compilation-window ()
  "Setup the *compilation* window with custom settings."
  (when (not (get-buffer-window "*compilation*"))
    (save-selected-window
      (save-excursion
        (let* ((w (split-window-vertically))
               (h (window-height w)))
          (select-window w)
          (switch-to-buffer "*compilation*")

          ;; Reduce window height
          (shrink-window (- h compilation-window-height))

          ;; Prevent other buffers from displaying inside
          (set-window-dedicated-p w t) 
  )))))
(add-hook 'compilation-mode-hook 'ct/create-proper-compilation-window)

That does the job. Now the tiny compilation window contents are locked and the madness of displaying anything anywhere is over!


→ Blog Archive