My family recently had some holiday photos taken.
The photographer was using Zenfolio to host their photos.
I loved the photos and wanted to archive the originals on my laptop (and NAS, and Amazon Photos, and Time Machine, and Carbon Copy Cloner clone, and…).
But every time I tried to download an original – of one photo, of all the
photos, makes no difference – the server always sent me an empty zipfile!
I emailed the photographer to let them know, but I wasn’t going to wait.
Rather than work around this manually by visiting each page and right-clicking
to Save As each photo – and I’m not sure that would show me the full-size image
, anyway! – I figured Zenfolio would have an API.
Sure enough, there’s a well-enough documented Zenfolio API. I was in business!
I was able to lash together some shell commands to grab my full photoset. To save you some fumbling, here’s how I did it.
The Swift standard library introduces some unfamiliar concepts if you’re coming
from Obj-C and Cocoa. map is one thing, but for some, flatMap seems
a bridge too far. It’s a question of taste, and of background, if something
comes across as a well-chosen, expressive phrase or if it just seems like
status signaling, high-falutin' bullshit.
Well, I’m not going to sort that all out, but I did find myself rewriting an
expression using a mix of if let/else into a flatMap chain recently, so
I thought I’d share how I rewrote it and why.
If you’re mystified by Optional.flatMap, read on, and you should have a good
feel for what that does in a couple minutes.
I think my big ??? is that I don’t get how to test a functional pipeline.
It seems to not having any of the seams you’d usually rely on.
Testing FP Code
Separate out pure code from impure.
Use PBT for the pure code.
Use typeclasses or protocols or similar dynamic binding methods to swizzle
I guess, use acceptance testing to check that you got the wiring to impure
stuff correct? That issue seems mostly ignored in favor of the much happier
“pure functions are easy to test” story.
In practice, I think I’m now foundering on the mess that is object-functional
blending. You’d hope that the Scala folks might have something good to stay on
that, but that’ll have to be a later round of The Internet Speaks.
Unit-testing needs seams, seams is where we prevent the execution of normal
code path and is how we achieve isolation of the class under test. seams work
through polymorphism, we override/implement class/interface and than wire
the class under test differently in order to take control of the execution
flow. With static methods there is nothing to override.
Recommends converting static methods to instance methods:
If your application has no global state than all of the input for your static
method must come from its arguments. Chances are very good that you can move
the method as an instance method to one of the method’s arguments. (As in
method(a,b) becomes a.method(b).) Once you move it you realized that that is
where the method should have been to begin with.
Says not to even consider leaf methods as OK as static, because they tend
not to remain leaves for long.
The problem manifests when we want to do the equivalent of injecting stubs
and mocks in higher-level functions: there are no seams where we can
substitute collaborator functions with stubbed ones, useful for testing. If
my function calls printf(), I cannot stub that out specifying a different
implementation (unless maybe I recompile everytime and play a lot with the
Outlines, in theory, what they would do, but have not done, for FP code:
Pass in functions to parameterize behavior:
So instead of injecting collaborators in the constructor we could provide
them as arguments, earning the ability to pass in fake functions in tests.
The upper layers can thus be insulated without problems (with this sort of
dependency injection) and there are no side effects that we have to take care
of in the tear down phase
Omits stack and logic paradigms. No surprise there.
Sums up a conversation that happens across several blogs. Weirdly omits any
links to primary sources. Yuck.
OO is rife with seams that are easy to exploit, so Feathers likes it.
Where you need a seam is a design issue:
Another blogger, Andrew, highlights that if “code isn’t factored into methods
that align with the needs of your tests”, the implementation will need to be
changed to accommodate the test. Hence, he argues as well that “thoughts
about “seams” are really just getting at the underlying issue of design for
testability”, i.e. the proper placement of seams.
But not all systems are always so designed (putting it nicely), so
“recoverability” matters: being able to make something testable in spite of
According to Feathers, even though there are alternative modules to link
against in functional languages, “it’s clunky”, with exception of Haskel
where “most of the code that you’d ever want to avoid in a test can be
sequestered in a monad”
Then there’s an argument that pushing the impurity to the edges makes
things testable. No-one addresses validating correct composition of
verified components, though. :(
has been pretty successful at providing a framework for APIs that lets
you focus on roughly the entity–relationship diagram of your data.
But I find it frustrating at some turns (too flexible!) and peculiar at others
(why is it bound to just one content-type?).
My frustrations with JSON API are ultimately because it doesn’t solve the
problems I have as an API consumer,
and its aim of preserving flexibility results in API consumers paying the
price of that in needing to deal with the foibles of a specific implementation
and in manually tuning their API queries.
I find the approach taken by GraphQL more directly and usefully
addresses my needs as a client developer while also necessarily, by design,
minimizing requests made and data transmitted.
JSON API makes it possible to accomplish that, but it leaves the responsibility for doing so up to the client developer; GraphQL makes it possible to accomplish that, but it takes the perftuning responsibility upon itself,
which makes my life as a client dev easier.
This Sunday marks my second Father’s Day as a father. If you’re not yourself a parent, that won’t mean much to you. It certainly didn’t to me. If you’re en route to fatherhood, read on to learn what “fatherhood” actually means.