What is a JSON feed? Learn more

JSON Feed Viewer

Browse through the showcased feeds, or enter a feed URL below.

Now supporting RSS and Atom feeds thanks to Andrew Chilton's feed2json.org service

CURRENT FEED

inessential

Brent Simmons’s weblog.

A feed by Brent Simmons

JSON


Fair Isle Brewery Opens Today

Permalink - Posted on 2020-01-23 23:13

The Fair Isle Brewing company’s tasting room opens today! (One of the partners is a friend: the one in the photo with the big gray beard.)

I had a preview a couple weeks ago. The beers are really, really good. 🎩🐥

The beers were…

…created with ingredients farmed and foraged in the Pacific Northwest and fermented with our house blend of wild and feral yeasts and bacterias.

The name “Fair Isle” sounds like “feral.”

PS Here’s their website.


Jeff McLeman

Permalink - Posted on 2020-01-23 18:34

It is my sad duty to report that Jeff McLeman — whose work you’ve used, even if you don’t know it — suffered injuries from a very bad fall, and soon after passed away as a result of those injuries.

Jeff was a long-time Seattle Xcoder, before recently moving away, and he was a beloved friend to me and many people.

He was also a walking computer history museum — he was a little older than me, and he’d worked on a number of projects during that heroic age when people wrote new operating systems because they were needed. I learned from every single conversation with him.

There’s a NetNewsWire connection, too. He worked at Black Pixel for a while, and — among many other things — he played a significant role in their shipping NetNewsWire. And when it came back to me, he was super-happy for me, and he encouraged me frequently and cheered on our work.

He was exactly the kind of person you wanted in your corner — and it seemed like he was in everybody’s corner.

We’re all shocked and saddened, and we miss him. I miss him. Our thoughts go to his wife and family.

You’ve probably heard his voice before: he was on Debug #35: Jeff McLeman on porting kernels. I’m re-listening to it right now.


Uniform Type Identifier Bug on iOS — and How It Affects NetNewsWire

Permalink - Posted on 2020-01-21 01:15

In NetNewsWire you can import your subscriptions from an OPML file. This is the standard way RSS readers work: you can export your subscriptions as an OPML file, and then import them into a different RSS reader.

This way you can move from reader to reader without having to redo your subscriptions list. It’s a good thing.

But in NetNewsWire for iOS (currently in beta) this sometimes doesn’t work because, for some people, the system won’t let you select an OPML file to import. (This does not happen on Macs.)

Here’s What Happens

In our app, we declare an OPML type: org.opml.opml with a file suffix .opml.

The org.opml.opml part is a Uniform Type Identifier (UTI), which is Apple’s way of defining document types.

When the user wants to import subscriptions from an OPML file, the app presents a document picker, and the app tells the picker that the user can select files of type `org.opml.opml.

We don’t want the user to select, for instance, a plain text file, or a Pages document, or a GIF, or whatever. We just want to make OPML files selectable.

This works great — except when, for some people, it never works: it doesn’t allow them to select OPML files, and so they can’t import their subscriptions.

It took a while to figure out the problem, but we did.

Here’s the Problem

We found that if a user has another app that declares an OPML UTI — and that UTI doesn’t match ours — then the document picker will not see those OPML files as the type we accept (org.opml.opml) but as something else.

So far we’ve found two other definitions for OPML: com.reederapp.opml and unofficial.opml (from Overcast). (To be clear: Reeder and Overcast are tremendous apps, and this situation is not at all their fault.)

For someone with one of those apps installed, the system sees a .opml file suffix and decides the file is of type com.reederapp.opml or unofficial.opml. Which doesn’t match our type — org.opml.opml — which means the user can’t select the file. Even though the file suffix is .opml.

One Possible Solution: Declare All the Types

When presenting the document picker, we could declare that we allow com.reederapp.opml and unofficial.opml.

But here’s the rub: those are just the two we know about. We would need to do research on all the RSS readers, podcast players, and outliners to find all the various declarations of the OPML type.

And, furthermore, every time a new declaration appears in a new app we’d have to add support for that one too. (In the meantime, it would break subscriptions importing, for people with that app, until we do add support.)

Another Possible Solution: Tell the System that All Text Files Are Selectable

We could just let the user select any file that’s a text file. OPML files are text files, after all.

But then, so are HTML pages. And Markdown files. And any plain-text documents you may have.

This breaks the principle that you let users select only the kind of file that’s appropriate.

But that’s the solution we’re going with. I don’t like it. I’m not even completely sure it will work in all cases, but I am sure that it makes for a sub-par UI.

I don’t see that we have a choice. Please tell me if I’m wrong!

PS We found a related bug report for this from 2012: Apps can declare bad UTIs that redefine what a file extension conforms to.


On Replacing OperationQueue

Permalink - Posted on 2020-01-20 20:37

We fixed our mystery KVO crash by writing a replacement for OperationQueue.

Well, sort of a replacement. It’s not a drop-in replacement, because what we really wanted was slightly different from OperationQueue.

OperationQueue does a few things:

  • Manages a queue of operations
  • Runs operations in multiple threads
  • Supports dependencies — operations can be dependent on other operations
  • Supports canceling operations

But that’s not exactly what we want. We want something that:

  • Manages a queue of operations
  • Runs operations on the main thread
  • Supports dependencies — operations can be dependent on other operations
  • Supports canceling operations

Note the difference: we want to run operations on the main thread. That may sound crazy to you, but I’ll explain why shortly.

Note also some characteristics of OperationQueue:

  • Uses KVO (is finicky and crashy)
  • Subclassing is allowed and expected (of Operation/NSOperation)

But that’s not what we want either. Instead, we want:

  • Low-tech, non-crashy notifications
  • No subclassing

Canceling Is the Most Important OperationQueue Feature

Recall that OperationQueue — at the time just NSOperationQueue — came out before Grand Central Dispatch (GCD), and it was the best way to get code off the main thread.

But these days we do have GCD, and when we want to run code on a background thread, we use GCD. (And, often, a serial queue.) We don’t need OperationQueue just to be able run code on multiple threads.

Instead, the important thing about OperationQueue, the reason to use it instead of just using GCD, is the ability to cancel operations. This is critical in an app where conditions change — the network might fail, the app might move to the background, databases may get closed. Canceling is critical.

This is why we didn’t just stop using OperationQueue in favor of GCD. This is why we needed to write our own thing that supports canceling.

Why Run Code on the Main Thread

I’ve written before about writing main-thread-only code — it’s a paradise when you don’t have to think about concurrency.

You may think you’re good at writing thread-safe code, but are you 100% good? Is everyone on your team as perfect as you are? And, when multithreading bugs inevitably do happen, how quickly can you reproduce them and fix them?

Our default position is to write code that is not thread-safe — and not even safe to run on any thread besides the main thread.

That said, we do have a number of APIs that do async things and then call back to the main thread. Networking, for instance. Updating or querying a database. Parsing feeds.

Even though our operations run only on the main thread, they can — like any other code — call an API that does something on a background thread and then calls back to the main thread.

An operation’s code might look conceptually like this:

func run() {
	// On the main thread right here.
	// doSomeAsyncThing uses GCD
	doSomeAsyncThing(args) { result in
		// Back on the main thread.
		guard !isCanceled else {
			return
		}
		doSomething(result)
		informDelegateOfCompletion(self)
	}
}

To sum up: because we have GCD, we don’t need an operation queue that handles concurrency. In fact, we don’t even want it to handle concurrency.

MainThreadOperationQueue, MainThreadOperation

MainThreadOperationQueue and MainThreadOperation are part of our RSCore framework.

A few things to note:

  • MainThreadOperation is a Swift protocol. You don’t subclass it; you implement it.
  • When an operation is finished, it informs the queue by calling a method on the main thread. No KVO or other form of notifications.
  • The code is quite simple, but there’s more of it than you might expect: managing dependencies adds to the bulk. The code is basically just a thing that does a bunch of housekeeping.
  • It uses precondition(Thread.isMainThread) in a number of places, which will crash even a Release-build app. We use precondition over assert quite deliberately: if these functions are called outside the main thread, then we’re operating in a surrealistic environment, and we refuse to go on.
  • It has some tests, but of course it should have more tests.

At this writing, this code is already running on over 2,300 iOS devices, since it was included in NetNewsWire 5.0 TestFlight build 28 last night. That was the build where we switched our Feedly syncing code from OperationQueue to our own MainThreadOperationQueue. (I just checked number of installations in App Store Connect.) So far so good!

One bonus thing I like about it is that any given MainThreadOperation can create its own MainThreadOperationQueue to run a bunch of child operations, and then call back only when those operations have finished or are canceled. (We use this feature as part of Feedly syncing.)

But my favorite thing about it is how low-tech it is. There’s not even a hint of cleverness in that code — it’ll put you to sleep. But this makes bugs, including crashing bugs, way less likely.

Don’t Do This (Usually)

Normally I am very much against reinventing wheels. No points are awarded for writing your own version of a thing that 1) comes with the system and 2) is well-suited to your needs — instead, points are taken away for showing off and wasting time.

Even if a system-provided thing is not exactly right, but close enough, you should probably use it.

But when you do find you need write your own version of the wheel, think about what you need exactly, and just do that thing and not more. And don’t be clever — you don’t want to trade one problem for another.

Update 1:20 pm: I’ve been asked about using OperationQeue.main to run code on the main thread and still use OperationQueue. Answer: the thing that triggered all this was the mystery KVO crashes. I don’t want to dwell on that, but that’s really why we wrote our own operation queue.


Permalink - Posted on 2020-01-20 02:17

The hottest team in iOS development keeps on rockin’! We just released a new TestFlight build of NetNewsWire 5.0 for iOS.

🎸🐣🐯


Immutable Swift Structs

Permalink - Posted on 2020-01-17 04:52

As you read this, consider that I might be a squirrel and not, as I like to pretend, a rational programmer.

My Two Brains

My Objective-C brain — which will never leave me, even though I’ve been writing in Swift for years now — always told me to create immutable objects as often as possible.

Objective-C brain says, “Immutable means you never have to worry about it.”

My Swift brain — which is newer, and has all the fun these days — tells me another thing.

Swift brain says, “Value types are good. Use value types as often as possible.”

So my favorite thing in all of Swift is an immutable struct. It’s a value type, and it can’t be mutated!

Both brains happeeee! 🐥🐣

Var vs. Let

This came up in working on NetNewsWire: some model objects — some structs decoded from JSON returned by a syncing server — used var instead of let for their properties.

These model objects are not mutated anywhere. So, I figured, those declarations should use let instead. (Which would make my brains happy!)

An immutable struct is, after all, the greatest thing ever, right? You don’t have to worry about it. It never gets copied (at least in theory). If you share it across threads, it’s the same everywhere: you don’t get some number of different copies.

So I asked the author to change the vars to lets.

I didn’t expect the response — which was “Why?” (Asked earnestly, of course.)

I struggled with the answer.

Value Types Are Good

Here’s the thing: value types are good. Even though those structs aren’t being mutated now, we could imagine cases where they could be.

Why not leave it up to the code that has one of these to decide to mutate or not? After all, as value types, this makes a copy and doesn’t affect other instances. Value types are safe, regardless of mutability.

And yet…

Here’s Where I Might Be a Squirrel

I still insisted on using let for the properties in these structs.

There’s something to be said, of course, for always starting out strict and loosening up only when it’s actually needed. Don’t loosen up in anticipation. But that’s hardly a big deal here.

Instead I think it goes to code-reading: if I see let instead of var, I have some understanding of the intent. In this case, the structs are parsed versions of stuff-from-the-server, and that’s a case where you could expect immutability, and be surprised to find something else.

Those structs don’t get saved anywhere as-is; they don’t live long; nothing the user does can change them.

These structs are a report: “Server says this.”

So… I think it’s the right call, but I’m absolutely aware of the possibility that I’m just distracted by my Objective-C instincts, and I’m over-tidying.

I don’t know! What do you think? Should I have left it as-is?


Permalink - Posted on 2020-01-10 05:40

The NetNewsWire team continues to rock — there’s a new TestFlight build up.

Note the change notes — they represent just three days of work. We’ve got the best team. 🎸


NetNewsWire for Mac Mystery Scrollwheel Crash

Permalink - Posted on 2020-01-06 20:19

For NetNewsWire for Mac, I get one or two crash logs a week referencing scrollView:​scrollWheelWithEvent:.

Here’s the bug for it.

Chris Campbell, in a comment, writes:

FYI, I see this crash reported very frequently in the commercial Mac app I work on at my Day Job. Unfortunately, we’ve never been able to reproduce it first-hand. I used a Tech Support Incident to correspond with Apple about this issue (giving them hundreds of sample crash reports), only to have them ultimately give up and credit back the Incident.

-scrollView:scrollWheelWithEvent: is an API of the private NSScrollingBehavior class and its subclasses (class cluster). Those objects are an implementation detail of NSScrollView that are stored in an external structure, so there is significant opportunity for mismanagement of the memory references.

There has been speculation that “responsive scrolling” is somehow involved…

If you know more about this bug, or have more ideas for working around it, please comment on the issue. Thanks!

Update 2:20 pm Jeff Nadeau writes:

This should be fixed in 10.15. The 10.15.2 crash I see linked is something different.

This is great news! I hadn’t noticed that almost all of the scrollWheel-related crashes were in 10.14.

I have just one crash log that references the scrollWheel on 10.15, and it includes this:

Assertion failed: (![currentGestureList containsObject:​self]), function NSScrollingBehavior​ConcurrentVBL​AddToCurrent​GestureList, file /BuildRoot/​Library/Caches/​com.apple.xbs/Sources/AppKit/​AppKit-1894.20.140/Scrolling.subproj/​NSScrolling​BehaviorConcurrentVBL.m, line 102.


Estimating NetNewsWire for iOS Demand

Permalink - Posted on 2020-01-04 05:06

As we get closer and closer to shipping NetNewsWire for iOS, I’m starting to realize that the iOS version could be quite a bit more popular than the Mac app.

Here are a few numbers:

  • NetNewsWire 5.0 for Mac was downloaded 24,789 times.
  • The NetNewsWire for Mac beta builds are downloaded anywhere from around 630 to around 1,360 times.
  • Number of people who signed up for the public test of NetNewsWire for iOS: 5,263.

Five times more?

The number of testers tells me — very roughly — that there’s about five times more interest in the iOS app than in the Mac app.

If that holds true, then NetNewsWire 5 for iOS, once it ships, will get downloaded about 124,000 times.

Let’s round down — call it 100,000 downloads in the first two weeks. I would be amazed if we got that that many downloads. I’m really expecting a number much closer to the Mac app. But I could be very wrong — I admit to thinking like a Mac developer and not really feeling the greater size of the iOS market.

It’s quite possible that 100,000 might be too low.

At any rate, I’ll be sure to report the actual numbers on this blog. 🐣

What does this mean for interest in RSS readers in general?

Remember that NetNewsWire is just one of many RSS readers on Mac and iOS. There are readers for Android and Windows — and a whole bunch of browser-based readers, such as Feedbin, Feedly, Inoreader, and others.

You can’t just multiply my NetNewsWire estimate by the number of apps and come up with something meaningful.

But you can look at some things and get an idea. For instance: on Feedly, one of the most popular browser-based readers, there are 1.6 million people subscribed to Engadget. No, I have no idea if those are all active readers, but still.

I think it would be reasonable to guess that the number of people who use an RSS reader is probably greater than a million, and could be several million people.

Those aren’t Twitter user numbers, obviously, not even close — but I’m betting it’s more than what most people assume it is.

PS This blog has 16K followers just on Feedly. If it were possible to add up my subscriber counts from each RSS reader, it would be quite a bit more than the 18K Twitter followers I have. Which is as it should be.


The New Ranchero Software

Permalink - Posted on 2020-01-03 05:02

Ranchero Software, my old company, has actually technically existed in three different forms over the years — I’ve been an indie, then got a job and shut down the company, went back to indie and rebooted it, got a job, etc.

The most recent version — Ranchero Software, LLC — shut down a while ago. A year ago? I forget.

We got tired of reporting every month that it made $0. And we realized we had no plans to ever make money, since, well, I have a great day job at Omni.

But now it’s back, in a new way

The new Ranchero Software isn’t a company: it’s an organization on GitHub. Just today we moved NetNewsWire and associated repos to this new location.

We realized it would be easier if we had an actual organization with various teams — easier to manage, easier to add people, easier to set permissions, etc.

There was a little talk about what to call it. Name it after NetNewsWire? Or use the name Ranchero?

One of the things to remember is that it’s not just about NetNewsWire: there are also stand-alone frameworks and there’s another app: Rainier. (Which is way behind NetNewsWire. Nothing to see yet.) And we might do other apps, too.

So while we could have — a la the Apache folks — named the org after its founding project NetNewsWire, everyone preferred using the Ranchero name.

For me, at least, this is super cool. Ranchero Software lives!

PS You might wonder where the name Ranchero came from. It was 1996, and we were looking for a domain name that was 1) available, and 2) trendy. In those days, the hot stuff was Tango and Marimba and similar. We found that ranchero.com was available, and it kinda fit in with those names — plus it sounded kinda western — so we grabbed it.

PPS No, Ranchero Software isn’t an actual organization with papers filed anywhere. It’s just a thing on GitHub. But that’s all it needs to be.


My New Year’s Resolution Is to Focus My Anger

Permalink - Posted on 2020-01-01 21:44

For the last few years I’ve found myself getting angry at small things, which is so unlike me.

My resolution is to try harder to get angry only when it’s actually worth it. I can be angry at cruelty, angry at the forces destroying democracy for their own corrupt power, angry at the malevolences driving our climate crisis.

But I need to not get angry just because Instruments won’t profile my app, or I get a robocall, or someone on Twitter completely misses the point of something I wrote.

Anger — righteous, smashing anger — is completely called-for right now. But only at the right targets. This is the hard part, at least for me — it starts to spill out to where it doesn’t belong, and I can feel it corroding me.

I’m not by nature an angry person. Quite the opposite! But I do care deeply about some things.

My emotions somehow need to get smarter about what’s worth the anger and what things are not actually part of the current vast project of destruction.

I don’t know how to do that other than to constantly remind myself, when I feel it bubbling up over something small, that it’s not worth it.

But the problem with anger — even our current justifiable and necessary anger — is that it becomes a habit, and then it goes blind.


Permalink - Posted on 2020-01-01 00:50

NetNewsWire won an Upgradie for Best Newcomer Mac App! The whole team is so happy for this.

Other awesome stuff won too — one of my favorites is Automators, which won Favorite Tech Podcast.

Here’s the episode where Myke Hurley and Jason Snell talk about the winners and runners-up.


Permalink - Posted on 2020-01-01 00:32

There’s a new public TestFlight build of NetNewsWire for iOS. The NetNewsWire blog has the details.


KVO, My Enemy

Permalink - Posted on 2019-12-31 00:53

One of the keys to the stability of the shipping versions of NetNewsWire is that we don’t allow KVO (Key-Value Observing).

KVO is a false convenience — it’s often easier than setting up a delegate or old-fashioned notification. But to use KVO is to just ask for your app to crash.

And not just crash, but crash in hard-to-figure-out ways.

* * *

So we don’t let KVO into the app — except, well, we’re using Operation and OperationQueue for Feedly syncing, and the thing about Operation is that it uses KVO to signal when it’s finished. There’s no way of getting around that if you want to use Operation.

Okay. Fine. It’s worth it, right? It’s just this one small use of KVO. Surely we’ll be fine.

Nope.

KVO is why I drink.


Reminder: Select and Choose Are not Synonyms

Permalink - Posted on 2019-12-30 23:37

From the Apple Style Guide:

Use choose, not select, for menu items. In general, the user selects something (such as a file or disk icon, an email message, or a section of text) and then chooses a command to act on the selection.

…and…

Use select, not choose, to refer to the action users perform when they select among multiple objects—such as icons, graphic images, radio buttons, or checkboxes—or when they highlight text for editing.

People often think, mistakenly, that select is the polite or proper form of choose — but, in user-interface-world, they actually mean different things.


How We Run the NetNewsWire Open Source Project

Permalink - Posted on 2019-12-28 00:40

People ask me, “So — I can just show up, see something I feel like doing, do it, and then it will just show in the app?”

The answer, perhaps surprisingly, is no. Or, mostly no.

Well, kind of yes. It’s complicated. I’ll explain.

We run the project as if it were a commercial app

There’s a misconception about open source apps: people often think they’re not really intentionally run — they just kind of accrete whatever features and fixes that people who show up feel like doing.

NetNewsWire is not willy-nilly like that. We plan features and fixes the same way we would if the app cost money. We have a help book, a website, a blog, a Twitter account. We work especially hard on design. In most respects it’s indistinguishable from a commercial app.

We even set dates internally — and then blow right through them. :)

I’ve become fond of saying that NetNewsWire is a team. It is! But it’s also true that the app has my name on it.

My leadership style is to ask questions, talk things over, look for consensus, and trust people — but the last call is mine. It’s not a democracy, and it’s certainly not a thing where people just show up and ship whatever they feel like.

We definitely do not run the project as if it were a commercial app

But remember that NetNewsWire is free, has no budget (not one cent), and everyone who works on it is volunteering their time.

So there are some things we do differently from a commercial app.

Quality

A big one is app quality: we have to do way better than commercial apps.

This may seem surprising, but consider: we don’t have a support team. We help people when they have questions, but it’s vitally important that we ship the highest quality app possible so that we don’t get bogged down doing support. (The Help book is a big part of that too! But we’d do the Help book regardless, because it’s a matter of respect for people who use the app.)

You may remember older versions of NetNewsWire with fondness, and you may be missing some features the older versions had — but make no mistake: NetNewsWire 5 is a much higher-quality app than any older NetNewsWires.

And — this is smaller, but real — we publish the source code. Anyone can read it, and we don’t want to be embarrassed by it. Even better: we hope that people can learn from it! I’d bet that the majority of for-pay Mac and iOS apps couldn’t survive this kind of scrutiny. (I don’t say that to be mean. They don’t have to, so they don’t.)

This may sound paradoxical, but it’s true: because NetNewsWire is free and open source, we have to have a higher bar of quality than commercial apps have.

People show up

I said at the top that people can’t just show up and work on whatever and then we ship it.

Except, well — sometimes people actually do show up and work on what they want to work on, and then we ship it.

The difference is planning and design. We talk things over on our Slack group, in the #work channel: is that feature right for the app? Will it perform well enough? Does it depend on something else being done first? What’s the design for the feature? Does it need to go into 5.1, or 6.0, or…? Is it a Mac-only thing, or iOS-only, or is it for both? Etc.

(We also use the GitHub bug tracker and create milestones for different releases.)

Consider the situation with syncing systems. I knew we wanted to ship NetNewsWire 5.0 for Mac with Feedbin syncing. We couldn’t ship with nothing — and Ben Ubois at Feedbin has been super-helpful, and Feedbin is awesome, and so it was a no-brainer.

And then consider that, after that, Feedly syncing was by far the most common request, so it was obvious to prioritize that one next. (The iOS TestFlight build includes Feedly syncing, and the Mac app will follow suit.)

And then consider that our goal is to support all the various systems. Which one will come next, after Feedly? How do we choose? This decision is based in part on people who show up: what systems do they want to work on?

This is not how you’d do things with a commercial app, but in this context it works fine.

By which I mean there absolutely is an element of going with the flow of who shows up and what they want to do. That’s actually part of the fun.

No Revenue

People have offered money — just in general or for a specific feature. But we won’t take any money at all. Money would ruin it.

When money’s involved, it becomes an issue, and in this world it’s the issue. We have our own little utopia where we can pretend like it doesn’t exist. (“How fortunate!” you say. Yes, indeed, and we don’t forget that fact for a second.)

This means, though, that our decisions can be entirely about what’s best for the app and the people who use it — we never, ever have to think about what’s best for revenue.

This is so nice!

Transparency all the way down

No part of NetNewsWire is behind closed doors. The code is available, the bug tracker is open, and anyone can join the Slack group. You can watch us — and help us! — make decisions.

Because of this, I can’t do that thing commercial apps do where they keep quiet about stuff and then do a big surprise release with a bunch of new features. Luckily, I’ve done that enough in life — I have no interest in doing that over and over.

Instead, we’re honest and open about our goals and what we’re doing and when we’re doing it. Nothing’s hidden.

Which makes me feel sometimes like I’m doing a high-wire act and everybody’s watching. The level of difficulty is certainly higher than with the average commercial app, since we can’t hide our code or our thinking, since everyone is a volunteer, since we have to do better than for-pay apps.

But I wouldn’t have it any other way. I have always loved making apps, but making this app with this team is the most fun I’ve ever had. By far. (And I’ve worked on some pretty great teams.)

And you can join us if you like! Everyone’s nice. 👍

PS My favorite part of the page where I announced the TestFlight beta is the Credits, near the bottom. You could be in there next time.


NetNewsWire 2020: Roadmap Schmoadmap

Permalink - Posted on 2019-12-27 00:39

We don’t have a detailed, plotted-out roadmap. Who does? Software is fluid, and software schedules are hot air.

But there are things that seem most likely for 2020. Consider this all as an educated guess, not as a promise.

NetNewsWire 5.0 for iOS: Q1 2020

We hope to be able to ship this in the first quarter. There’s no guarantee, but — given that it’s now in public TestFlight — it’s looking close to being finished.

NetNewsWire 5.0.4 for Mac: Q1 2020

This will be a bug-fix release, and it will be the last release that will run on macOS 10.14 (Mojave). The most important part of this release will be database clean-ups — it will be much better about pruning the database of old stuff.

It will also improve performance and reduce memory use.

But, given that we’re concentrating on the iOS app right now, and we don’t know how long that could take, this could easily slip to Q2.

NetNewsWire 5.1 for Mac: Q2 2020

This release will require macOS 10.15 (Catalina). It will add features already present in the iOS app: Feedly syncing and a Reader view. It may add other features, including additional syncing systems (no, I don’t know which ones). Tentatively — not for sure yet — we’re planning on sandboxing this release and publishing it on the Mac App Store.

Ideally we’d ship this in Q1. If we can, we will — but I’d put money on Q2 instead.

Now picture me waving my hands

There will be more releases, obviously, on both Mac and iOS — we’re just getting started! — but it’s too soon to make more definite plans.

But I can say some of the things we’re thinking about. We just don’t know when we’ll get to which ones, or what they’ll look like.

  • More sync options — we’d like to support all of the various systems
  • Sync via iCloud — we’re investigating the feasibility of this now, and I’m optimistic
  • Article view theming — possibly much like older versions of NetNewsWire
  • Setting font sizes for the sidebar, timeline, and article view on the Mac — we consider this a form of accessibility support (we already have this in iOS via Dynamic Text)
  • User-created smart feeds
  • The ability to delete articles — support already exists, under the hood, for this
  • More sharing options — sending to Instapaper and Pinboard, for instance
  • Some kind of triage/queueing system — so you can quickly go through your articles, then go back later to the articles you actually want to read
  • Panic button — for marking things as read based on time criteria

Those aren’t nearly all of the features we’re considering, but they’re the highlights. We’re not going to get all those done in 2020, but we’ll get some of them done.


NetNewsWire 2019 Year in Review

Permalink - Posted on 2019-12-26 23:31

About a year ago, in early 2019, NetNewsWire for Mac was at the “d” (development) level, where it had been for years. For instance, we released NetNewsWire 5.0d8 on January 27.

We shipped the first alpha — feature complete, free of known bugs, but needing testing — by WWDC. NetNewsWire 5.0a1 was released May 31.

We reached beta in August, and then shipped NetNewsWire 5.0 for Mac on August 26.

We continued to ship updates to the Mac app — NetNewsWire 5.0.3, the most recent, shipped October 22.

Maurice started working on the iOS app before we shipped 5.0 of the Mac app — and, on Dec. 22, we shipped a public TestFlight beta of NetNewsWire 5.0 for iOS.

At this writing, four days later, 3,148 people have signed up to help test the iOS app. This is far beyond what we expected, and it’s super-exciting for the team.

* * *

The upshot: in 2019 we made both apps, Mac and iOS, great foundations for our future work. Getting to this point was no small thing — it took years, after all. But we shipped the Mac app, and we’ve gotten the iOS app to nearly-shipping.

I feel great about our pace! I know it can be frustrating for anybody waiting on some one specific thing — especially if it’s support for the syncing service you use — but, in 2019, the NetNewsWire team rocked.

Remember that it’s a group of volunteers who are doing this for love.

P.S. I’ll write another blog post soon-ish on plans for 2020. :)

Update a little while later: Here’s the 2020 roadmap.


NetNewsWire 5 for iOS Public TestFlight

Permalink - Posted on 2019-12-22 20:26

NetNewsWire for iOS icon: Earth with a satellite orbiting above it, in the foreground.

You can go sign up on our testing page for the TestFlight beta for NetNewsWire 5 for iPhone and iPad.

The testing page has a bunch of info on it — including how to report bugs — and it’s way too long, and I’m totally cool with that.

Happy holidays! Happy NetNewsWiring! And thank you. :)


Permalink - Posted on 2019-12-05 00:57

I can’t help but wonder if — given equivalent knowledge of UIKit and AppKit — iOS development isn’t harder now than Mac app development. At least for some kinds of apps.

Mac apps don’t have to deal with size classes, safe area insets, two very different classes of devices, getting killed by the system, a split view controller that isn’t suitable for some common purposes, presentation controllers, user activities, and — toughest of all — background app refreshing.

And some things that were Mac-only, such as multiple windows and contextual menus, are now iOS features too.

Even if I’m wrong, I can’t help but notice, as we work on NetNewsWire for iOS, that iOS development is starting to approach Mac-app-like complexity, and is already more complex in some areas.


Why I Listen to Podcasts at 1x Speed

Permalink - Posted on 2019-12-04 02:43

On my microblog I mentioned that I always listen to podcasts at 1x speed.

Here’s why:

We’re in danger, I think, of treating everything as if it’s some measure of our productivity. Number of steps taken, emails replied-to, articles read, podcasts listened-to.

While accomplishing things — or just plain getting our work done — is important, it’s also important that not everything go in that bucket. The life where everything is measured is not really a full life: we need room for the un-measured, the not-obsessed-about, the casual, the fun-for-fun’s sake.

So I’m in no hurry. I will never, ever be caught up on all the podcasts I’d like to listen to. So, instead, I just play whatever I feel like whenever I feel like listening.

I’ll miss things, and that’s totally fine. But, in the meantime, I get to listen to the human voice somewhat close to realistically, with its the natural human pauses, with its rhythms and flows relatively unmediated and natural. Its warmth and music means so much more to me than being caught up.

But, again — I’m not saying this is right for you. But I would remind people that we have choices about what falls under productivity and what doesn’t.


The Apple Curtain

Permalink - Posted on 2019-12-02 21:24

I’m always happy for a friend when they start a job at Apple — but I’m also sad when it means they have to stop their community activities: no more podcasting and blogging, developer meetup organizing, presenting at conferences, writing side-project apps, contributing to open source things.

Another friend of mine at Apple, who worked in an area relevant to some trouble we were having with NetNewsWire, wanted to look at the source code – and they had to go ask permission before they could even look.

I understand! I understand why Apple PR and legal departments are the way they are. But I still feel a loss to the community every time somebody I know goes to work at Apple.

There’s a curtain between us and them. Colorful, well-designed, made by lasers — but still a curtain.

PS This would even prevent me from ever working there. I have a great job, and I intend to stay at this job till I retire, but if I were unemployed and saw the openings in Apple developer publications based here in Seattle, I totally would have applied. Except that working there would have meant the end of NetNewsWire and, effectively, the end of this blog. I would have had to give up the two biggest pillars of my career. It’s flat-out not worth it.

PPS I don’t write this to make any of my friends feel guilty! Working at Apple is a wonderful thing. But it’s bittersweet, and I do wish Apple would do more to take out the bitter part.


NetNewsWire Status: Progress Toward Shipping the iOS App

Permalink - Posted on 2019-11-27 21:50

The team — we have a team! which you can join! — is continuing to work on several different things: NetNewsWire 5.0.4 for Mac, NetNewsWire 5.1 for Mac, and NetNewsWire 5.0 for iOS. We’re also figuring out what will go in subsequent releases.

The most attention has been going to the iOS app. We’ll be doing a public TestFlight beta as soon as it’s ready, which I’ll announce here and on the NetNewsWire blog. It’s getting close! A bunch of us have been using it every day for a while now.

In second place for attention is syncing with Feedly, which will appear in the iOS app and in NetNewsWire 5.1 for Mac. (We’re working on adding other services too, but it’s yet to be decided which ones will appear in which versions.)

No ETAs, of course — we’ll announce dates only when we know them for sure.

* * *

The design of the iOS app is what you’d expect, I hope. As NetNewsWire for Mac is so very much a Mac app, the iOS app is very much an iOS app.

Our design goals are the same as with the Mac app: make it stable, fast, clean, modern, and — most importantly — as obvious as possible, which helps make it easy to learn and use.

In other words, we did what we always do, which is to do the best job we can by using classic user interface design principles.

It definitely looks like an iOS 13 app. You can see its bones.

While I think it’s awesome, people who prefer something richer have other really great apps to choose from. We know NetNewsWire is not the only RSS reader, and we’re not trying to please everyone. Which is very freeing — it means we can please the people who like apps like this. :)


A Naming Challenge

Permalink - Posted on 2019-11-14 18:38

In NetNewsWire, we have a concrete Feed type that’s what you expect: it describes an actual web-based feed.

But there are other things that are feed-like in some important ways. Smart feeds, script feeds (in the future), search results, and folders.

They have some things in common: an icon, the ability to fetch articles, the ability to provide an unread count, etc. These common abilities each have a separate protocol: UnreadCountProvider, for instance.

But this is so common that we should have a single protocol that bundles these up into one.

The problem is — what should we call it?

* * *

Maybe the right for that single protocol is Feed. If so, then what should we call the concrete type for web-based feeds?

* * *

In the original design for NetNewsWire, five years ago, Feed was going to be a protocol. Then I started working in Swift, found that I wanted to use Set<Feed> and couldn’t, so I made it a concrete type.

I love Swift, but this limitation keeps coming up for me. I use both protocols and sets a lot, because they’re often the best choice, but in Swift they just don’t play together well.

* * *

Update a couple hours later, at 1 pm: We’re going with a protocol named Feed and the concrete type name WebFeed for, well, web feeds. This means a bunch of renaming in the app, but I think the result will be worth it.

Remember that it’s an open source app. The marketing team is not counting on a specific deadline. Our goals are 1) app quality, and 2) making it easy for people to work on the app (which really supports the first goal).

PS The marketing team is me. :)


Permalink - Posted on 2019-11-07 22:10

For the entire 20 years of inessential.com, I’ve been in the same house, at the same desk, with even the same keyboard.


Happy 20th to This Blog!

Permalink - Posted on 2019-11-07 21:19

Today is my blog’s 20th birthday!

It started like this: at the time I was working at UserLand Software on a blogging app called Manila, and this was my own personal Manila blog. It’s gone through a few other engines since then. (These days it’s rendered — as a static site — by some Ruby scripts.)

* * *

It‘s tempting to think that The Thing of my career has been NetNewsWire. And that’s kinda true. But the thing I’ve done the longest, love the most, and am most proud of is this blog.

* * *

The original tagline was “You don’t need to be here.”

The name inessential sounds like a low self-esteem thing. It’s not. It was named for the idea that literature is inessential. Without it, people would still go on fucking and fighting and grocery shopping.

In other words, the name comes from huge and unwarranted self-esteem, as if my blog would be the first to be literature. Sheesh! Now I laugh at myself. What arrogance!

I hope I’ve matured, at least a little, since then. But I keep the name, because nowadays that’s just its name.

* * *

Old proverb: “The best time to start a blog is 20 years ago. The second-best time is today.” :)


This Feature Should Be Easy

Permalink - Posted on 2019-11-03 20:11

From time to time people note, in feature requests, that a particular feature should be easy, and they’re surprised it hasn’t been done yet. Sometimes they even say that it’s so elementary that they really consider it a bug that it hasn’t been done yet. Especially given how easy it is.

I’ve written about this before. See Bug Guilt Trips from 2003 and Anatomy of a Feature from 2009.

A feature is pretty much never as easy as it seems. The main function of a feature — whether that’s making a https call to a read-it-later service or adding some fairly simple new view — is often the easiest part.

It’s everything around the feature that makes it harder: UI design, localization, refactoring, accessibility, state restoration, getting new artwork (for a toolbar button, for instance), dealing with errors, testing, updating the documentation, etc.

And then you still have to schedule it: as important as a feature request is, there might be others with a higher priority, and resources are always limited. Doesn’t matter who you are.

* * *

When you get developers alone, and you make a joke like “Why don’t you just…” or “I bet you could do this in an afternoon…”, they all laugh, because they’ve all heard this.

I most definitely do not want to discourage people from making feature requests, whether for my app or anybody else’s app. Please make feature requests! And report bugs!

But I would ask that you try not to call something easy. The developer of that app will have a pretty good idea of the requirements and the level of effort, and it’s never as simple as it looks on the surface. And they also have a good idea of what needs to happen, for various reasons, before work starts on that feature.


Amateurs

Permalink - Posted on 2019-10-31 20:20

One thing I’m weirdly proud of is my position as an amateur programmer.

When I point that out, people say, “Well, but…” — and I know where they’re going, that after 25 years of professional experience I’m not what you think of when you think of “amateur.”

And yet, it’s still true. It’s just that I’ve come out the other side, and now I get to work on exactly what I want to, the way I want to, without any thoughts of trying to make money at it.

I can take risks! I can work with anybody who shows up! It’s a pure thrill. It’s like writing single-malt apps.

And I would wish for more people to find themselves in this position — eventually, anyway — because I want to see what they would make.

PS The Dictionary app on my Mac says of the origin of the word “amateur”:

late 18th century: from French, from Italian amatore, from Latin amator ‘lover’, from amare ‘to love’.

Spot-on.


You Choose: Follow-Up

Permalink - Posted on 2019-10-31 00:35

It came to my attention after writing my blog post about how we choose the web we want that the pessimism is about not being able to make a living from blogging.

Here’s my followup: I don’t care. Bite me.


ETAs: Follow-Up

Permalink - Posted on 2019-10-30 20:10

Some people took my post No ETAs as if I were arguing against doing software estimates of any kind, ever.

I didn’t actually mean that. If your boss, project manager, or person you’re contracting with asks for an estimate, do your best to come up with something accurate. If you’re writing enterprise software, you may even be contractually bound to provide estimates for when features will ship.

There are ways to get pretty good at this. Pay attention to history and avoid wishful thinking. Don’t assume perfect productivity. Allow for the unexpected, because there’s always something.

What I’m talking about is the case where you’re writing a consumer-facing app — something that would get published on an app store, for instance — and customers or potential customers ask about an ETA for a given feature. Don’t do it! (For the reasons stated in the article.)


You Choose

Permalink - Posted on 2019-10-29 19:58

On Twitter, Molly Lambert writes:

RIP blogging we all tried real hard to make the internet good and then corporations and rich idiots destroyed everything a generation of writers tried to build

Charlie Warzel re-tweeted her with this comment:

there’s almost no space for writing anymore that’s joyful or an attempt to be creative. hardly anyone is playing around with form or even just trying to entertain. so much of the joy has been sucked out of the internet unless its crowdsourced by platforms from ppl who aren’t paid

They’re both right.

But I’d also note: fuck that shit.

Here’s the thing: there are good blogs to read. Some old ones are gone, but new good ones are created all the time.

And there are good RSS readers which you can use instead of (or in addition) to Twitter and Facebook.

And — most importantly — nothing is stopping you from writing joyfully and creatively for the web! You can entertain, you can have fun, you can push the boundaries of the form, if you want to. Or you can just write about cats as you develop your voice. Whatever you want!

There are plenty of great places for it. (I quite like Micro.blog, personally.)

* * *

You choose the web you want. But you have to do the work.

A lot of people are doing the work. You could keep telling them, discouragingly, that what they’re doing is dead. Or you could join in the fun.

Again: you choose.


No ETAs

Permalink - Posted on 2019-10-28 20:33

People often ask me about ETAs. When will the feature they’re waiting for ship? If you’re a software developer, they probably ask you too.

I totally get it! Though I write an app, I’m mostly a user of apps, and I too want to know when the features I’m waiting for will ship.

The Problem

But here’s the thing: ETAs are very hard to estimate with any amount of accuracy. Even if you plan well.

There are just too many variables. You have some very rough idea of the work to do, and how much time it ought to take, yes. To start with: those ideas are wrong.

You don’t know what you forgot to take into account, or what pieces you underestimated or overestimated. You never know what weird bugs will trip you up.

You don’t know what OS release between now and then will make you spend extra time on something. (For instance: iOS 13.2 just came out today. How is it different? Does it affect the app? Every OS release is a moment of anxiety for developers.)

You don’t know if you’ll need to do some serious, time-consuming refactoring or rearchitecting. You don’t know if the person working on the feature might get pulled away for some reason (vacation, emergency, reassignment, etc.).

You don’t know if the fallout from some other feature in progress will require more time, which ends up pushing back this feature. You don’t know if some other feature or bug fix will suddenly get a higher priority based on any number of good reasons.

You don’t know if your testers will be pulled away to work on something else. You don’t know if your tools will be updated in a way that affects productivity. (Hopefully for the better! Though, if there’s a learning curve, maybe it will hurt productivity at first.)

There’s all that and plenty more — and none of the above are extraordinary conditions. They’re all quite normal. So any ETA will almost surely be quite wrong. Even if you take all of the above into account.

On Not Setting Expectations

The problem with stating an ETA then, is that it sets up expectations. When you don’t meet them — and you won’t, most of the time — people sometimes get upset. Not everybody. But some people take ETA to mean “I promise to ship that day or damn close to it.”

So the better thing to do is plan which features go into which releases, and have a date for internal use for just the next release — and refrain from making public ETAs.

Even if you the software developer think you can make accurate ETAs — and maybe you did, once or twice — you’re not going to be that lucky most of the time.

PS This is all just to say that app-making is nothing like building a house. It’s more like building the first house ever in the history of houses, with a pile of rusty nails and your bare hands, in a non-stop tornado. It’s different every time, and it’s astonishingly complex, non-linear, and unpredictable. We all do our best to mitigate this, to make it more regular, but the industry just hasn’t gotten very far with that yet. The only reason anything ever ships is because people just keep working until it’s ready.

Update 30 Oct. 2019: See the follow-up, which explains that I’m not talking about all ETAs.