inessential by Brent Simmons

September 2018

NetNewsWire Diary #2: Switching to OPML

Since the earliest days of NetNewsWire, before 1.0 even shipped, I wanted to make the subscriptions list on disk an OPML file.

It seemed like using the standard format for listing RSS subscriptions would be a good idea. But I was never able to make that happen — until now, with NetNewsWire 5.0d7.

Why It’s a Good Idea

Given that OPML import and export is a must-have feature — which NetNewsWire already has — then storing the subscriptions on disk as OPML means less code, because there’s just one format to support, instead of supporting both OPML and a custom format for just the app.

It means that the OPML reading and writing code will run for every user on every session, which means any bugs in OPML support won’t be able to hide.

It means a user can get their subscriptions list and move it to another system without first having to launch the app and do an export — the OPML file is already there on disk already.

It also means a user could replace their subscriptions list on disk by swapping in a different OPML file, without having to figure out how to do it through the app.

Why I Never Did This Before

The problem, though, is that the standard OPML format for listing RSS feeds doesn’t have slots for additional metadata. I want to store things like Conditional GET information, the hash of the contents from the last fetch, the edited name as well as the feed’s declared name, and so on.

So for all these years I thought, “Well, that’s too bad. I wish I could use OPML, but I can’t.”

Why I Could Do It Now

It occurred to me I could use a “side table” — that is, a separate place to store feed metadata. This would allow me to store whatever additional data I wanted to store in a separate location.

The go-to for this would normally be SQLite, with some kind of table for feed metadata.

But this has another problem: SQLite is structured storage. There’s a schema. But this doesn’t quite suit feed metadata — especially not when you add in syncing. I wanted the ability to store attributes for each feed without knowing, in advance, what all those attributes might be.

Enter Rainier, the inspired-by-UserLand-Frontier app I’m working on. It includes an object database — that is, it includes a hierarchical, schema-less, key-value database. It’s like a dictionary that can contain nested dictionaries.

Which is perfect for what I wanted to do: I could make each feed a table in an ODB database, and then each feed can store arbitrary key-value pairs. (Think of a “table” in an ODB database as really a dictionary.)

So I built this ODB storage — perhaps ironically, it’s built on top of SQLite, but why not? SQLite is amazing — and its first use is in NetNewsWire.

Rainier-the-app isn’t far enough along to actually do anything at all yet. But a key component of it is now part of NetNewsWire. I expect this pattern to get repeated for a few more things, too — including the (not-nearly-finished) scripting language.

Unofficial Seattle Xcoders tonight — at 6:30 pm at the Cyclops in Belltown. I’ll be there!

There might be some other Omni folks there too unofficially celebrating recent releases. :)

All are welcome! You don’t have to be a coder. Find us in back, on the restaurant side.

The latest episode of The Omni Show is ostensibly about launch day — but mostly it’s a discussion of the new design in OmniFocus 3 for Mac. How it started, how it evolved, how it ended up.

It’s of obvious interest to OmniFocus users, but I think the discussion is also interesting to anybody who cares about app design.

(I think it’s one of the best episodes, by far.)

My friend Geoffrey — the one with the big beard in the pictures in the linked-to page — is opening Fair Isle Brewing in Seattle, in Ballard (my neighborhood), next year. They’re doing farmhouse and wild beer.

You can invest as little as $100 if this interests you. More about farmhouse beer:

Farmhouse beer is one of the most exciting and fastest growing segments in the beer industry. These special beers are fermented with a mixed culture that includes local, wild yeasts and bacteria; instead of the laboratory-isolated and tightly controlled commercial yeasts that are more typically used today. Farmhouse brewing techniques embrace the local environment. Like fine wines, Fair Isle’s beers are all about a specific place and a specific time.

I think it’s going to be a success — but that’s because I know Geoffrey. We’re talking about investing money here, so please make up your own mind!

Gus in 2009:

Learn to be your best critic, and you’ll learn to ship software that’s worth paying for.

Tech Diversity

When Blogger came out, we all got on Blogger. When Flickr came out, we all got on Flickr. Later there was Twitter and Facebook, and we all got on.

(Okay. Not every single person, but you get my drift.)

In those days, for a thing to be important, for it to be a success, it had to get the attention of much of the internet.

It was a lot like TV used to be. There were just a few networks, and for a show to be a hit it had to have some significant percentage of viewers watching it.

Times have changed, and the internet is more mature and diverse. As my friend Kelly Guimont says, the internet is “sort of like TV” these days, and “you can have a successful show and not have half of America watching.”

Like Game of Thrones. It doesn’t have half of America watching it, but it’s still a success.

I argue that the same is true of apps and app categories: we’ve (finally!) entered a period of tech diversity, and Mastodon and Micro.blog and RSS readers and blogging systems and so on do not have to capture the attention of the entire internet to be successful and important.

In fact, those days are gone. TV changed, and so did the internet.

Oh God Not This Again

Every now and again there’s a thing about the tragedy of RSS. Ugh.

I want to make a few points.

One is that, as Greg Reinacker once said, RSS is plumbing.

Another is that millions of mainstream users rely on it — for podcasting, especially, but also because it powers other things that they use. They don’t know that there’s RSS under the hood, and that’s totally fine.

Another is that it’s not necessary for RSS readers to become mass-market, mainstream apps. I’m sure I never said they would be, and I don’t remember anyone else from the early days of RSS saying they would be, either.

It’s totally fine if RSS readers are just used by journalists, bloggers, researchers, and people who like to read. Yes! It’s a-okay.

But note that everyone who uses Twitter and whatever else, and who follows those people, are benefiting indirectly from RSS. RSS is, often, where the links come from in the first place before they show up on social networks.

(Sometimes it’s even automated. For instance, posts to my @NetNewsWire account on Twitter come from the blog’s feed. In other words: Twitter itself is an RSS reader.)

In a nutshell: judging RSS itself because RSS readers are not mainstream is to miss everything that RSS does. And judging RSS readers for not being mainstream is to judge them against expectations set by some hype artists more than a decade ago — but not by me or anybody else actually doing the work.

I don’t expect to see RSS readers running on every Mac and iOS device. This does not make it a failure.

It’s 2018, and I think by now we’re allowed to have things that some people like, but that not everybody uses.

* * *

From 2011: What we talk about when we talk about RSS

From 2013: Why I love RSS and You Do Too

From 2018: Some Hope

Dana Blankenhorn, No More Mr. Nice Liberal:

It only ends when anyone associated with Trump or Trumpism, down to city councilmen, can be disqualified by the simple fact of having been Trumpists. Trumpism, and that brand of conservativism, must become as anathema as Nazism became for Germans after World War II.

Why NetNewsWire 5 Doesn’t Support Nested Folders

I was asked on the NetNewsWire Slack group about supporting nested folders — folders inside other folders — and I realized the answer deserves a blog post, because it brings up some larger issues.

But first, some technical stuff.

RSS readers have moved over the years toward tagging as opposed to folders.

A structure where feeds can have multiple tags is the same thing as a structure where you have multiple folders but not nested folders, and a feed can appear in more than one folder.

So that’s what NetNewsWire does, because this looks like a de facto standard to me.

That’s part of the reason, but there’s more…

Simplicity

In earlier versions of NetNewsWire there were too many features that added to the fiddliness of the app.

Those features were invitations to the user to comb and revise their system. They could customize colors and fonts, create deep folder structures, archive articles on disk, and so on.

Over the years I’ve learned that these kinds of things often detract from an app. Every decision is a moment of anxiety for the user. The user wonders: is this the right call? Did I consider all the issues? Can I change it later?

And the user may be motivated to come back and re-do those decisions.

I don’t want my software to do that to you.

Furthermore: simplicity is itself appealing. Delight comes in getting the most power from the smallest effort.

Adding features may make the app more appealing to people who want those specific features — but it chips away at simplicity as a feature, and some people will go look for something less complicated.

To be clear, though, this approach isn’t right for every app. It depends on what you want the app to be. I like Acorn for its relative simplicity over Photoshop, for instance — but Photoshop absolutely needs to be what it is for people like Brad Ellis to get their work done.

I have the luxury of not needing to make money from this, and I also have the luxury of knowing there are other really good RSS readers. I’m not required to make this particular app the RSS reader for every single person.

Bugs

Our industry has not only been poor ethically, it’s also been substandard at just plain old quality. Sure, the economics of it are partly to blame. It motivates people to sell out their users and to ship broken software.

“Move fast and break things” is a motto that seems to apply to the industry at large. I think it’s wrong, because there’s a human cost to this.

Again — because I have the luxury, because I don’t have deadlines or commercial concerns — I can do something different: I can ship software with no bugs. Zero.

I’ll be more precise: if a bug is any ticket in the issue tracker, then of course there are always bugs. I’m talking about known, reproducible defects.

My plan is to never release a shipping version that has any such defects. I believe that’s a feature in itself.

But that’s much more easily done with a simpler app. Every added feature adds to the combinatorial complexity of the app, and the app becomes harder to test and harder to get right.

My commitment to zero defects outweighs my commitment to adding features.

Time

And I do want to add features. There are some features I haven’t seen in other RSS readers — even earlier versions of NetNewsWire — that I want to do.

I think (I hope) they’ll be fun and useful and that you’ll like them. (We’ll see, of course!)

But when I spend time adding some features from an older version of NetNewsWire, I’m not doing the new features that this new world NetNewsWire wants.

My Pitch

You might end up disappointed, when NetNewsWire 5.0 ships, that some feature you used in an earlier version of NetNewsWire isn’t there. I totally understand that.

But my pitch is this — or will be (it’s not shipping yet): try an app with zero known defects, where performance is critical, where careful, considered design and simplicity are valued, where there is room for future innovation, where development happens in the open, and see if you like it despite the missing things you wish it had.

You might find you do! And you might not, which is okay — as I mentioned earlier, there are other really good RSS readers, which is a great thing.

PS You can join the Slack group too — just send me email.

PPS I could change my mind in the future about nested folders. Very few decisions are set in stone. But the above is all the things on my mind as I make decisions about things like this.

NetNewsWire History

On the NetNewsWire blog I’ve been publishing bits of NetNewsWire history. It’s a look at the history of our industry through the eyes of one single 16-year-old app.

Though I have my own blogging software, for the NetNewsWire blog I decided to go with Micro.blog and my own domain (nnw.ranchero.com). It’s easier to use than my own software — especially when it comes to adding pictures, and I definitely want to use a lot of screenshots on this blog.

I set it up to automatically cross-post to @NetNewsWire on Twitter. I don’t love Twitter, obviously, but I feel it’s important, when you have a product, even a free one, to be accessible wherever the users are.

Daniel Jalkut, Saying Goodbye to NetNewsWire 3:

Since I’m not the only stalwart NetNewsWire 3 user, one of the things Brent was curious about was whether he could give that version “one last hurrah,” so to speak. Fix a few of the most glaring bugs, build against a modern SDK, and not only create an artifact for history to more accurately judge the app’s virtues, but to give long-standing users something to tide them over while development continues on NetNewsWire 5.

Decision: Not Publishing NetNewsWire 3.x

The last build of the full version of NetNewsWire, before the sale to Black Pixel, was 3.3.2. I’ve learned that lots of people still use it!

I was considering publishing the source on GitHub and/or making a 3.4 build that strips out the Esellerate and Google Reader syncing parts.

So I sent the code to Daniel Jalkut, who quickly hacked at it and got it running and sent it back to me.

And then I ran it too — and quickly realized a few things:

  1. It has lots of bugs. Bugs that would be difficult to fix without rearchitecting critical parts.
  2. It uses WebView a ton, which is deprecated, and replacing use of WebView with the new WKWebView would not get us the results we want. (The Combined View wouldn’t survive, for one thing.)
  3. It would be an attractive nuisance — some people would focus on this while I’d rather the focus be on NetNewsWire 5. I care about history, but not at the expense of the future.

I might still make a build of NetNewsWire Lite 4.0 available. That code base is not just newer than 3.3.2, it’s just plain way better.

(It was the start of my never-completed NetNewsWire 4 rewrite. NetNewsWire Lite 4, when it shipped, had zero known bugs, and just one known bug within a couple weeks. It was a good app. With modern tools I bet I could find more bugs pretty easily, though.)

But it’s still not nearly as good as the code I’m working on now. (Which should be no surprise — it’s years later, and I’m a better developer.)

NetNewsWire Diary #1: Automatic Hashing and Performance

I like Swift’s recent addition of automatic hashing support — in many cases you can declare conformance to Hashable and let the compiler do the rest.

This let me delete a bunch of code, and I love deleting code.

* * *

I noticed a regression the other day: for some reason, fetching articles from the database and populating the timeline view got noticeably slower when the results are fairly large.

I worried that this is because my articles database is over a year old, and as it grows the fetch times get longer.

So I used the Time Profiler instrument to see what was going on during a fetch — and I found that most of the time was being spent in hash(into:) in two of my structs: Article and DatabaseArticle.

And of course fetching articles means creating a whole bunch of these structs. Hundreds or thousands, even, depending.

Those were two cases where I had adopted automatic hashing. The hash(into:) method was generated by the compiler.

So I thought about what to do. I wanted a hash that’s unique, or close enough, and I want it to be fast.

The solution, in both of these cases, was obvious — each has an articleID property that is unique per database, which is close enough. That means just hashing one property rather than (presumably) all of them.

So I made hashValue a computed property in each of those structs, as in:

var hashValue: Int {
    return articleID.hashValue
}

I built and ran the app — and the performance issue was fixed.

I put some (temporary) timing code around the code that fetches all unread articles, and it went from 0.37 with automatic hashing to 0.07 with my computed hashValue.

That’s huge!

I realize I could have written a hash(into:) function instead. Maybe I should? I’m not sure that it matters one way or the other. Possibly by the time you read this I will have switched the implementation.

The point still stands, though, that automatic hashing in the case of objects with lots of properties might be a performance hit. As always — use the profiler.

PS Hashing is important in NetNewsWire because I use sets frequently. In general I make arrays at the UI level, when populating a timeline (for instance), and use sets when fetching from the database, etc.

How To Add Your Micro.blog Feed to NetNewsWire

In NetNewsWire 5, you can add your Micro.blog feed of people you follow, so you can read their posts in NetNewsWire.

Here’s how:

Figure out the URL. It’s something like this, where my username is replaced with your username: https://micro.blog/feeds/brentsimmons.json

In NetNewsWire, hit cmd-N. (Or click the + button in the toolbar.) Put that URL in the URL field in the sheet that appears. Give it a name if you want, and choose a folder if you want. Then click the Add button.

That’s it!

Posting to Micro.blog

If you have the Micro.blog app on your Mac, you can select an article in NetNewsWire, then pull down the share menu in the toolbar, and choose Micro.blog.

It will send that article to the Micro.blog app, where you can edit and comment before posting.

The same thing works for MarsEdit, so you can post to any blog.

New World NetNewsWire

So much has changed since I last worked on NetNewsWire, and my thinking about it has changed too.

The big things remain the same — NetNewsWire is at the intersection of my passions: reading and writing, the open web, and Mac apps. I want to make NetNewsWire a great app with lots of users. No change there.

But so much else has changed.

In 2002, when I started NetNewsWire, there was no Facebook and no Twitter, no iPhones, and most people hadn’t heard of RSS. People got their news by visiting a few sites a few times a day. People subscribed to email newsletters. That was about it.

Since those days a whole bunch of RSS readers — most notably Google Reader — have come and gone. But, interestingly, there are probably more web-based readers these days than ever before.

But most people, it seems, get much of their news from Twitter and Facebook these days, and I believe this is unhealthy for society and for individuals. None of that existed in the early days of NetNewsWire.

Another change: the energy in app-making has moved from Mac to iOS. But I still love Mac apps, and I still believe in them as works of art that people use to get their work done.

Another change is a personal change: I don’t need to make money from NetNewsWire. While I always wanted to make NetNewsWire the best app it could be, I used to have to consider money as I made decisions. I no longer have to.

* * *

My goal used to be to make NetNewsWire a great Mac app with lots of paying users. Secondary goals were to promote reading and writing on the web, the blogosphere, and RSS and open web standards.

My goal now is to make NetNewsWire a great Mac app with lots of users. Other, no-less-important, goals are to:

  • Promote healthier news-reading via the open web and RSS
  • Promote native Mac app development by providing a good example and by making the code open source

(Yes, I’m strongly considering an iOS version, but I’m concentrating on the Mac app first.)

* * *

Let’s go back to how people get their news these days.

NetNewsWire will never be the sole news-gatherer for anybody. People use social networks. They still visit sites manually and subscribe to email newsletters. They use apps like Apple’s News app. They get news from Slack and other group and personal chat apps.

And they use other RSS readers too.

This means that NetNewsWire does not have to be designed as if it’s anybody’s only source of news. And it doesn’t have to be designed to please the maximum number of people.

My thinking, instead, is to make it fit into an ecosystem: it’s just one of a number of sources, and not even the only RSS reader.

This allows me to design more carefully. NetNewsWire used to be quite over-featured, and now I have the luxury of being able to make a leaner NetNewsWire.

I can say no to things that I would have said yes to — I can make it the app I want it to be, an app that hopefully lots of people love using, but that isn’t trying overly hard to be everybody’s friend.

It’s okay, in other words, to remember that there are other RSS readers, and it’s totally a-okay when somebody likes another one more.

In other words, NetNewsWire of the future will be more me than any previous versions were.

PS Here’s a secret: my favorite version of NetNewsWire was always NetNewsWire Lite, which was the pared-down, free version. I keep thinking that I’m designing in the spirit of NetNewsWire Lite.

NetNewsWire 5.0d1

If you’d like to run it, go to the NetNewsWire site and download the latest build.

Things to know:

  • A whole bunch of important features haven’t even been started yet
  • There are features not finished yet
  • There are bugs
  • It’s not even beta. Not even alpha!
  • It still has the Evergreen app icon

If you’re upgrading from Evergreen, you can either:

  • Start fresh, or
  • Rename the folder ~/Library/Application Support/Evergreen to ~/Library/Application Support/NetNewsWire, or
  • If you already have a NetNewsWire folder there, copy the contents of the above-mentioned Evergreen folder into that NetNewsWire folder.

Note: I’ve started a Slack group, but I don’t have a public signup form for it yet. You can email me to ask for an invitation. Just let me know if I should use an email address other than the one you used to email me. (You can find my email address at the bottom of the NetNewsWire site.)

You don’t have to be on the Slack to help. You can always contact me by whatever means, and you can post to the Issues tracker on GitHub.