Jim's Depository

this code is not yet written

The Swift server packages are documented with the inline comment documentation system. I went ahead and used it for my recent test mule project (femtoblogger, you're soaking in it).

It's easy enough to add documentation, Xcode has a CMD-click Add Documentation menu that will jam in a template for your function with spaces for all the parameters and return types. You just type markdown after that. If you add an argument, click it again. Xcode will add more template.

Now people can Option-click on your function name (or whatever) and get a lovely Quick Help pop up.

I appreciate this greatly for libraries.

But…

There doesn't seem to be any pathway from this snippets to a real document where the big picture is explained, and all the functions listed in well organized categories. You know,… like the good old Apple documentation.

"Good enough" is the enemy of "Good".

This isn't a special flaw for the Swift comment based documentation. Essentially all in code systems I've ever used have suffered from this. (Halfway excepting one I wrote, but you can't use.)

The Moral

  • Do your "in code" comments.
  • Update your "in code" comments when you change the code.
  • Write book like documentation somewhere! and put the links to it in HUGE type in the middle of your project page.

Well that was a fair bit of gap in between posts.

Femtoblogger is now on its 4th implementation. I feel the need to try out Swift on the server, so here we are. 100% pure Swift Femtoblogger.

The previous incarnation was Go. Before that was PHP. There was probably a never deployed Python version in there too.

Thoughts on Swift and the design of the server this time around…

  • I very much like the type safety of Swift. When I code in Swift there are no runtime explosions, and very few bugs discovered in testing.
  • The Swift code is more information dense than the Go code was. The Go code felt like a great sea of text with a little bit of content. The Swift code packs a lot of content into a screen of code.
  • Performance appears to be a non-issue. SQLite backed pages are serving in 3-12ms. For comparison I added a caching layer for most popular queries and dropped that into the 80µs range for the query handling. That's not real, I handle them by doing a X-Accel-Redirect header back to Nginx and letting it serve a file out of a RAM disk directly. But it means my process is not going to be buried.
  • I haven't bothered with any compiler optimization. I want the checks to stay in place while I see if I've screwed up somewhere.

The Network End of Things

  • The Swift server network library, NIO, really wants to push you into a futures and promises style of programming. I resisted because it is so clumsy at the source code level. Your code begins to vanish under a sea of ritual. That said, I probably would have been better off to embrace it. A request needs to get out of the network queues to free them up while it gets in a non-concurrent model queue to work with the data, then out of there as soon as possible and into a render queue to do template expansion and back into the network queues to send the data out. It's a lot to coordinate.
  • I suppose I'll continue avoiding futures and promises in femtoblogger until Swift 6 and the beginning of its new concurrency model make it into NIO.
  • I didn't use Vapor or similar web frameworks, I build my server directly on NIOHTTP1 so I'd understand the architecture. The first 90% was simple! Then I needed to parse some form data and couldn't find the calls in the API. Eventually I found an email in a filing cabinet behind a sign that said "Beware of the Leopard" where the NIO team proclaimed that "out of scope". Maybe I'll make a post on parsing "multipart/form-data" (which can't be a String because it might not be valid) and parsing HTTP header values.

Using Other People's Packages

  • I did reach out for 'random dude' packages for a higher level SQLite API, Markdown to HTML conversion, and template expansion. It's a bit of a mixed bag there. I'm glad I did it, but there were issues. As always it seems to take a lot of research time to figure out which solution is well supported, not horrible, and will likely last a while.
  • I used SQLite.swift for accessing SQLite. The tutorial writing crowd on the internet likes it. It gives you a type safe way of interacting with SQLite without too much ritual. The package is a few years old and has been dormant for most of a year. I found a design flaw where it would try to read a mismatched datatype and explode your process. (Just because you called a SQLite column TEXT doesn't mean it isn't going to return a BLOB for one of the rows.) It looked to be an involved fix to use the receiver's datatype instead of the provider's, and in the absence of an active maintainer I didn't want to invest in making the changes. It was easier to rewrite all the rows to have their TEXT really be TEXT.
  • I used Ink for Markdown to HTML conversion. It is simple to use. Out of the box it choked on CRLF line endings. The patch ended up being a , "\r\n" in just the right place, plus about 16 lines of test cases. Hint: "\r\n" is a single Character in Swift… grapheme clusters and all. The maintainer is active so I sent that one in.
  • I used Stencil for template expansion. I've used it before and the rough edges I used to have to hammer off are now addressed. Note: Stencil could really use a SafeExpansion mode which escapes HTML for when you have untrusted users. It has user created filters, I ended up making one instead of forking and adding a safe expansion feature.
more articles