Angelo Stavrow [dot] Blog

Missives and musings on a variety of topics.

In moving this blog to a static site generator, one concern was whether I'd still be able to work on and/or publish a post from my phone. I tend to do a fair bit of mobile drafting while I'm in the subway or waiting in line, and will sometimes publish content when I'm away from my computer. YOLO.

Requirements

It's a given—since that's how the site has been setup—that you need a GitLab.com account, and Hugo set up with GitLab CI to build the site and deploy it to GitLab Pages.

On my iPhone, I have Working Copy, which I use for git operations on the repository. It's an excellent app, and when you pair it with Editorial's powerful workflow and text editing capabilities, you've got a great toolkit for repository management as well as writing.

I like using issues as jumping off points for new posts (including this one, so I also use Git Trident to manage this in GitLab from my phone. Matt's working hard on making this the best app for handling GitHub and GitLab issues on your iOS device, and I'm especially looking forward to offline access.

Workflow

This post was a test for how to add content to the site from my phone, and here's how I'm going to do it from now on:

  1. Usually (but not always), an issue tagged post idea is the basis for a new post. When I'm ready to write, I assign the issue to myself and set a due date for it.
  2. I then create a new branch as n_post_post-subject_yyyy-mm-dd in Working Copy, where n is the issue number and yyyy-mm-dd is the post date. If no issue exists, I drop the n_ prefix in the branch name. I try to avoid setting a title, as this can change over the course of the post. “Post subject” is already pretty well defined, since I know what I want to write about.
  3. Next, I create a new text file in Working Copy under /content/post, and open it in Editorial via the share sheet to start writing. I have a TextExpander snippet to add the TOML front matter; it's also set as a draft, to ensure it doesn't get published accidentally.
  4. Then comes the hard part: write the post. Commit as necessary with Working Copy's workflow for Editorial. I commit and push for a “cloud save”, or if I think I might want to continue elsewhere (i.e., on my desktop, or in a web editor1.
  5. When it's all said and done, I set 'draft = false in the front matter, commit and push with message Closes #n, where n is the issue number.
  6. When I'm ready to publish, I launch Safari and go to GitLab.com to open a new merge request. Merging the draft branch into master will trigger GitLab CI; once the build passes, the post will be published. I also delete the original branch.
  7. That's it! The post is published. Enjoy a tasty, refreshing beverage!

I wrote the majority of this post on my iPhone, although I'll admit that it does feel a bit silly to tap away on a 4.7” screen when I've got a 24” monitor and full-size keyboard to work with. Still, for drafting and editing, it's great, and in a pinch (or, say, on an iPad with an external keyboard), you can keep your blog running from your iOS device without issue.

  1. Web editor, you say? Why yes! You can edit a file in GitLab, then commit the changes. Neat, huh?

Discuss...

As I mentioned last week, today is July 1st, which marks a convenient half-way point for the year. On New Year's Day, I posted a short list of goals that I was hoping to make progress towards. Here's how it all breaks down.

1. Post something here every Friday.

So far, so good. I haven't missed a single week, which I'm pretty pleased with. I'll grant that it hasn't always (ever?) been a particularly interesting read, but I've been trying hard to keep showing up. Discipline isn't easy, but it helps if you try to avoid breaking the streak.

2. Post to a journal at least once every day.

I was doing pretty well with this through to the end of March, and gave up by April 22nd. It started well, but frankly, I wasn't comfortable in writing my deepest thoughts into a service that can't guarantee its privacy—not that I think the fine folks at Bloom would ever consider it, but if key employees have access to the decrypted data, that means necessarily that there's some risk of a data breach.

And I could feel it when I was writing, too—I was self-censoring just in case. And if you can't just write whatever you want in your journal, of all places, then it's not really a journal.

So, I've deleted whatever I'd posted there, and I'm re-thinking this goal. There's value to writing regularly, sure, and there's value to getting your thoughts down, but between this blog, the Break Before Make tumblr blog, and Twitter, I think I've got more than enough opportunity to write.

3. Make real progress towards my Mac app.

Myeah.

Well, I settled on a name and registered a domain. I keep starting new projects and I've got even more in my Someday/Maybe list. I really need to focus more on this.

4. Contribute to open-source projects.

I feel like I haven't done too much with this yet. I've written for open-source projects, but beyond that, this also feels like something that's maybe taking focus away from the Mac app.

5. Get in better shape.

After taking care of some knee issues with my physiotherapist, she gave me the green light to start getting active again. So, as of the end of March, I've started by jogging. My goal is to get in three 15-minute runs per week—I'm not trying to run a marathon, just improve my cardiovascular health.

It's been, well, shaky.

I've lapsed into no-run periods a few times, either because of an injury, or because I've been too lazy to get out and do it. But generally, there's a very strong downward trend in my pace (from a 7:41 to a 6:17), so I'm happy. Moreover, it's just been getting easier to run for extended periods of time.

It's high time I add some kind of strength training into the mix, though!

Other salient projects

As linked above, other projects have come up that I started work on.

For one, you may notice the new look of this site. As of today, it's being built by Hugo and is running on GitLab Pages. That's been a fun little project, with the side benefit of saving me a few bucks a month, too. I'm considering cross-posting over to Medium, but we'll see. There's some theme work to be done, but otherwise, hello Hugo!

I've also open-sourced my first iOS app, in the hopes that having it in public will embarrass me into updating it. But again, I really don't want this to distract me from the Mac app I want to write.

What's next

Honestly?

I don't know.

But the intention is, for the next six months, to:

  • keep up with writing here, on (at least) a weekly basis;
  • keep up with improving my general fitness and health; and
  • really get cracking on this Mac app I keep hinting at.

Will I get sidetracked? Undoubtedly. Will I venture into new little projects that may or may not be abandoned? Yeah, it's possible. We live in flux, after all, and it's way more fun to explore the forest than it is to walk the path.

Definitely more tk.

Discuss...

Reminder: as of next week, the RSS feed for this site is moving! If you subscribe, please be sure to point your favourite reader to:

http://makebeforebreak.com/index.xml

Next week is July the first. It's Canada Day here, which means it's a national holiday, but in Montreal, it's also an unofficial moving day.

So it's a propos that this site will be moving over to its new digs on that same day.

But July first also marks the halfway point of the year, a year which I started with some set of goals. So it's also a good time to take stock of progress made against those goals, and make any necessary course-corrections.

I don't intend on revisiting that here today, but I can tell you that I know that I haven't made the kind of progress I was hoping for. In fact, the only thing I've “succeeded” at, strictly speaking, is posting something here every Friday. It hasn't always been easy, but so far the streak has remained unbroken.

So, technically, I'm looking at an 80% failure rate. That doesn't sound encouraging at all.

I could feel bad about this.

But I don't.

Ash Furrow gave a great talk called Loosely Held Strong Convictions last year. It reminded me that, despite our belief to the contrary, we exist in a state of flux.

It's strange how we unconsciously fight this. I mean, we know that things—including ourselves—are constantly changing. And yet, we often try to plot rigid courses through life, despite the fact that today's road may well be tomorrow's wall.

It's fine to change your mind. In fact, it's encouraged. It means you're adaptable. You're able to go beyond living your life as a to-do list.

The hard part in all of this, what I fight with the most, is whether or not I'm changing my mind because a path has become irrelevant, or just unpleasant. I may not be doing super well at getting to the gym (like, at all), but I am trying to run for 15 minutes or so, three times a week.

Except if it's raining.

Or if I really need to get into the office soon.

Or maybe if I woke up with a bit of a gurgle in my tummy.

Discipline is hard. Which means it's way more valuable than motivation. It's easy to do the pleasant thing when you're motivated; it's useful to do the unpleasant thing because you're disciplined.

So, yeah. By all means, make changes to your opinions and your plans. But do it because it's a good idea, not because it makes your life easier.

Discuss...

This week, I took a hiatus from the refactoring fun I've undertaken to (finally) move the blog over to a static site generator.

I've written before about my plans to move to Hugo, and that's now complete. Since the beginning of the year, all posts have been written as Markdown files that I can easily grab and format with the necessary front matter. Before then, I hadn't written very much, and in fact I've dropped a couple of old posts that I felt didn't add to the site in any way.

The site-generation files exist in a GitLab repo. I treat this site as I would any other software project; issues are opened to add or modify things (including posts), a branch is created to address these issues, and when the work is done, the changes are merged into master.

Whenever something happens on master, GitLab's CI kicks in and a shared runner picks up the job, builds the site, and uploads the public/ folder to GitLab Pages. This is one of the easiest ways to set up continuous deployment for the site, but when I started trying it out there was an open issue to resolve for performance—it could take hours before the changes went live. That's gotten much better since GitLab 8.9RC3 was deployed, and I only make one post per week so it's not that big a deal—but if you need to keep things up-to-the-minute fresh it's not a bad idea to set up a project-specific runner instead to build and deploy your site.

The official deploy date of the site is—as you can see from the 1.0 milestone—Friday, July 1st.

One more thing: the RSS feed for this site will be changing. If you subscribe to the feed, please update your link to

http://makebeforebreak.com/index.xml

More tk!

Discuss...

I'm in the process of (finally) finalizing the move of this site to Hugo.

No, for real.

Most content is already in place. A few older posts need to be added, and some info pages are to be added. This is normal-priority.

I'm using a slightly-modified built-in template to render the site. There a few more modifications to make, but this is low-priority.

A commenting platform will be added. This is also normal-priority.

I want to explore adding SSL to the site, but this is low-priority.

Finally, a deploy strategy is to be set up—this is high-priority. The plan right now is to have the following workflow:

  1. Merge in some changes (i.e. New post, updating old content, &cet.);
  2. Merge commit triggers CI to build the site;
  3. When CI succeeds, deploy the built site to the web host.

This will give me the opportunity to post from either my computer or my phone without issue. Then it's just a question of reconfiguring DNS to serve up the new site.

If all goes well, next week's post should be on the new platform!

Discuss...

The Great HoneyJar Refactoring is a series of posts in which I take the first iOS app I ever wrote, HoneyJar, and refactor it out of its original burning-dumpster-fire state and into a modern app. And I'm doing it in public.

Earlier this week, I tweeted about my adventures in trying to add a test suite to HoneyJar.

The idea is this: I want to be sure that I'm not breaking anything in the app, as it exists right now, when I start refactoring. Without an existing test suite, I have no way of knowing if I'm creating any regressions.

The TDD approach is to

  1. Write a test that checks a particular public method against a particular condition;
  2. Write the code that makes the test pass; and
  3. Repeat steps 1 and 2 until you're done writing the method / class / app.

The tests come first, and the code “fills in the blanks”.

When you've got a legacy codebase1, however, does it still make sense to write failing tests first? Probably not.

Furthermore, what if it's just not possible to test certain methods or classes, because of the way the code is structured? If you haven't written the code with testing in mind, then it might be too coupled or complex to test after the fact.

Stop writing legacy code. Do not write new features without unit testing. You are just making the code base worse and getting further away from introducing tests into your system. Get your testing infrastructure set up and a few tests running successfully and it will be much easier to think about introducing tests for the rest of the code.

— Dan Lee, TDD when up to your neck in legacy code

Right now, what's making me a little bit crazy is that I'll open a class to start adding some unit tests, see all kinds of ways to improve the code before adding the tests, and have to remind myself that I've made a promise not to touch the code until the test suite is in place.

SO. FRUSTRATING.

It's especially frustrating when you realize that you'd written something that you can't really test, but you're not allowing yourself to fix it.

But we have a great way of getting around that. Comments.

So, here's what I'm doing:

  1. Open the class to which I want to add tests;
  2. Add a new test case class for said tests;
  3. Scan through the class under test and grind my teeth at obvious problems;
  4. Take three deep breaths;
  5. Start adding whatever tests that I can add without changing the code; and
  6. Add thorough //TODO comments on “next steps” for refactoring this class—obvious problems, how to improve testability, &cet.

I'm going to go through doing this for the entire codebase first. I could add some tests for a class, then refactor it, then move on to the next one, but then I have no way of knowing if I'm making a change that will somehow propagate through the app and trigger a failure elsewhere. So, while I'm not especially happy with the coverage I'm getting right now, it's better this way.

Once the issue is closed, I'll start tackling the actual refactoring—and I'll feel more like the project is ready for others to work on, too. For me, at least, I t's really hard to make changes to a codebase I'm unfamiliar with if I don't have the safety net of a test suite.

As always, more tk.

  1. By "legacy codebase", here, we mean untested code, i.e., a codebase with no pre-existing test suite.

#tghr

Discuss...

The Great HoneyJar Refactoring is a series of posts in which I take the first iOS app I ever wrote, HoneyJar, and refactor it out of its original burning-dumpster-fire state and into a modern app. And I'm doing it in public.

Last week I introduced an idea I had: to open-source my first-ever iOS app, embarrassing as it might be, and refactor it out in the open.

Over the last week, I handled the open-sourcing of the app. This took a bit more time than I expected, and normally this should be done before releasing the project to the wild, but I figured it might be interesting to see just what the process was, what I learned, and some resources I found along the way.

The starting point

HoneyJar, in its closed-source state, was very clearly an “I'm learning as I go and am super excited to ship” kind of project. It had a README, kinda, which really just re-iterated some tagline-style description of the project, and that's it. Unit tests were few and far between, comments were… not awesome, and there was no real structure in place to make it useful for other contributors.

So the first step was to do exactly that. I opened the first issue and set up a task list:

  • Add a CONTRIBUTING document
  • Add a LICENSE document
  • Add a CHANGELOG document
  • Update the README to provide more information on the project
  • Set up GitLab continuous integration

Okay. I know. That sounds like a pretty straightforward list. Quick and easy to add. Turns out, you should put a little effort into these things.

Readez-moi

The first thing most people will see in a project is the README file. This should provide some information on how to install/use the project, where to find further info on licensing and contributing, &cet. But how much info? What exactly do I need to add?

I found an excellent template by Billie Thompson that fits the bill nicely. While I've commented out a bunch of stuff that isn't necessarily relevant (or maybe not relevant yet), I think it provides a pretty good overview of the what, who, why, and hows of the project. I'm relatively happy with the way the README turned out.

With every change, log, log, log

Next up: everyone's favourite, the CHANGELOG.

No, seriously. This either gets totally overlooked, or totally becomes a series of punchlines about episodes of Friends or whatever. In trying to figure out what needs to go into a change log, I discovered Keep A CHANGLELOG. Great resource.

As you go through merging in changes, part of the merge should including updating the change log with whatever you've, well, changed. As the project maintainers indicate, typical sections are:

  • Added for new features.
  • Changed for changes in existing functionality.
  • Deprecated for once-stable features removed in upcoming releases.
  • Removed for deprecated features removed in this release.
  • Fixed for any bug fixes.
  • Security to invite users to upgrade in case of vulnerabilities.

Additionally—I love this— every subtitle of the document should be a link to a git compare of the previous and current tags (or HEAD, if you're working on an unreleased version).

Excellent idea.

License to thrive

Jeff Atwood said it in 5 words. Pick a license. This is important, or you're pretty much putting your work out there without letting anyone know if they can use it. Picking a license helps you both cut the overhead of having to reply to emails (“can I use this code?”) while putting down some ground rules on how your work can be used.

I went with a simple 3-clause BSD license. Essentially, this is a use-as-is-without-warranty license, requiring attribution by others who redistribute your work, and written permission if they want to use my name (or my organization's name) in any endorsement or promotion of their derived products.

Just add contributors

The hardest to set up was the CONTRIBUTING document. Here, there are two main things I wanted to address:

  1. Expectations of all involved (i.e., a code of conduct), and
  2. Just how to contribute.

The how-to-contribute part is pretty straightforward. Everything should start with an issue, and once labels and owners are assigned, work can begin. There's some basic info on how to report a bug vs. how to add a feature request, and I added some requirements for merge requests too. Such requirements can get pretty complex and involved, but it's important to step back and examine the scope of the project too. We're not building CocoaPods here; a tiny not-super-important project like HoneyJar probably won't attract much in the way of contributions, so there's no need for overly complex requirements for making changes.

That said, I believe that any project, regardless of size, has the potential for community. And a community is only as good as the expectations for interaction. In my work, as in my life, I really try to come from a position of trust, mindfulness, and open-ness, so putting together a code of conduct that embraces these values is important to me.

Luckily, I'm not the only one that feels this way. The Contributor Covenant is a good place to start, and other open-source communities (1, 2, 3, as examples) have done a great job of adapting it. I've followed in their footsteps, and I think the code of conduct section nicely explains the let's-be-wonderful-to-each-other feels that I want in my community.

All the great fails

The last thing I absolutely wanted up and running for this first issue was to get continuous integration up and running.

“But Angelo, you don't have a test suite set up for your project.”

Yeah, I know. But the next big step before I start working on the actual refactoring is exactly that: add a test suite for existing code. It would be downright silly to try refactoring something without making sure that you're not breaking anything as you go through.

So, I followed the steps in the article I wrote and created a new runner and a .gitlab-ci.yml file, along with some sample test, to make sure everything's working.

And builds kept getting stuck with the error:

Failed to authorize rights (0x1) with status: -60007.

Turns out, I needed to update the runner on my build machine to address some changes in Xcode 7.3—once that was done, things started building as expected. One of the great things about GitLab being an open-source project is that if you're running into trouble, there's likely an issue available to help you figure out what's happening and how to fix it (and if there isn't, open one!).

I've left the build history as-is, along with the commit history, as breadcrumbs to how I managed to get things working, along with the stupid mistakes like overlooked typos in your runner tags. I don't think there's any value in trying to hide these goofs, because they could be invaluable the next time you're yelling at your system for not just working come on you stupid thing everything was fine a minute ago what do you mean this tag doesn't exist.

Onwards and upwards

So, the project is now, IMO, officially open-sourced. The next big step is to add the test suite, and then I can move on to the fun stuff: refactoring.

More tk.

#tghr

Discuss...

Over the next few weeks, I've decided to write a series of posts about taking my first iOS app, HoneyJar, and refactoring it from its current (terrible) state into something, well, less-terrible.

And I plan on doing it in public, too.

I'm calling this project The Great HoneyJar Refactoring.

HoneyJar is a future-value calculator. As explained on the product page, you set a payment amount, a rate of return, and a period of time, and HoneyJar will give you a scenario showing how your money will grow if the amount entered amount was

  • a one-time lump-sum payment
  • a series of equal weekly payments
  • a series of equal monthly payments

I haven't really touched it after I released 1.0 save for a few minor updates. It could certainly use some love, as there's a whole lot of technical debt going on in that codebase. Just off the top of my head, without having poked around the repository for months, I can list the following required fixes:

  1. Refactor the main UIViewController into several lighter classes. The thing is a mess.
  2. Along a similar line, convert the project to use Storyboards and Autolayout.
  3. Add a test suite.
  4. Add localization (I'll start with English and French, since I speak those languages pretty fluently).
  5. Ensure accessibility.
  6. Port the thing to Swift, or at least write new code in Swift.
  7. General UI/UX improvements (e.g., make the result presentation clearer).
  8. Drop support for devices running iOS 8 and before.

I'm going to call this version 2.0 and I've opened a milestone in GitLab to track my progress. The associated issues will be added over the next day or two, so you can see how what I'm working on at any given time. I'll also be setting up CI and other (non-code) project settings.

So, I'm open-sourcing the (embarrassing) version as it exists right now—please be nice—and I plan on tackling one issue every couple of weeks or so, until the milestone is closed and 2.0 is released. Each time I close an issue, I'll write up a post on the whys and wherefores of the changes.

I haven't yet decided if I'll accept any merge requests during this project, but I certainly look forward to feedback on my work. To make it easier for people, to follow along, I will be mirroring the repository on GitHub, too—GitLab makes it easy to push changes to a remote repo. GitLab is my origin of choice, though, thanks to the built-in continuous integration.

Update (2016-05-25): I've moved the GitHub mirror from my personal account to the organization account, since it's Dropped Bits that's handling the App Store stuff.

More tk!

#tghr

Discuss...

I mentioned that keeping comments up-to-date with modifications in source code helps me with task-switching in a busy workplace.

Of course, that doesn't make a difference if you're not commenting your code well.

Therein lies the rub. I spent weeks on learning various sorting algorithms in my data structures and algorithms class, but I never really learned anything on the whys and wherefores of commenting.

I've been taught that

// This is an inline comment.

and that

/* This is a block comment, which makes
 * longer comments a little bit more
 * readable.
 */

and also how to use comments to temporarily disable portions of your source code to try something out.

And that's fine.

But what should you put in your comments?

Visual Studio has a neat feature where if you type three slashes in a row (///) before a method definition, it'll expand a comment snippet that includes, as appropriate, sections for a summary, what method argument parameters are, and what the method returns. Whatever you enter there shows up in a tool tip when you hover over the method call later.

Similarly, three slashes (///) in Xcode will allow you to enter comments that show up when you hover over method calls.1

Handy, for sure.

But, really, when I'm heads down and trying to push code out before, say, I leave for the day, I've noticed that all I write in these comments is a re-iteration of the method signature—and given that I try to use very descriptive method and variable names in the first place, these extra lines of typing are pretty redundant. I'm just giving myself work for zero added benefit.

Samantha's tweet inspired me to think a bit more about how I comment my code. Intent is key, I agree. If the source code is the documentation2, then the comments should probably play the role of both the chapter summaries, and the sidebars that warn of the gotchas, the perils, and the pitfalls. The bigger-picture stuff. Why is this structured this way? What might I have to look out for when testing this particular method?

All the best practices we learn—design patterns, unit testing, &cet.—are meant to make our code more maintainable. Comments should be an integral part of that, not just as a repetition of what's obvious from the source, but as a reflection of the intent of the thing.

  1. You definitely should pick up Erica Sadun's Swift Documentation Markup to really make the most of this feature, by the way.

  2. I'm not 100% convinced of this particular mantra. Of course, code is the canonical source of ground truth, and that's the intent, but as far as it being documentation—well, that's a post for another day.

Discuss...

I've discussed the transition over to a static-site generator before.

Yes, I'm still planning on doing this.

Yes, it's been a long time coming.

So I'm setting a deadline for myself: the next post on this blog will be with the new setup. It probably won't have all the pieces in place re: design and other related-site plans, but I've got to start somewhere.

More tk.

Discuss...

Enter your email to subscribe to updates.