Slack Status Updater (CLI) - Picking a language

A gopher, a gem, and an icon walked into a bar and ordered a drink. The icon left the bar right after ordering, promising to come back. Later when their friend didn't return they found a paper with a troll face drawn on it. Scrawled under the drawing was this: UnhandledPromiseRejectionWarning.

My future career is NOT in programming stand up comedy.

If you didn't check out the intro blog post to this, you should over here because I'm not going to repeat some of the rationale's behind my ideas while I setup scope. All I will say is:

  • I'm building out a CLI that will update my Slack status (probably from a preset list of statuses).
  • I don't know which features I'll have yet.
  • I don't know what I'm going to use to build this.

Language Choice

This one is a bit of a cop out. I recently had a chance to build CLI's and had to analyse tools that I would use. So I definitely have my biases already. But in the interest of being fair, I'm going to reflect on the tools up for consideration. But before that. I need to know what I want.

  1. I want a tool that's easy to get setup with in terms of development across most platforms. Windows support feels important and not important at the same time. I know it won't affect me. But I'm not sure that's right to think of it that way.
  2. Related to the above. The language should have well established patterns of using it. Starting a project, arrangement of code, testing practices, package management, and distribution are priority topics that must be established well.
  3. It's got to be possible to build a CLI that can do web requests and I/O without one having to go through a "If you hit a screw hard enough with a hammer it becomes a nail" approach. If there are any extra packages that help with building a CLI, even better. Also, making web requests, parsing responses etc would be considered grading points. Easier the better.
  4. Distribution across platforms should be easy. In this case, Windows is important. Basically I don't mind a language that's easy to setup only on Mac or Linux as long as it's really easy to distribute to all major platforms.
  5. Should be stable and generally well accepted in dev communities. There's no good measure for this one. But general squint and look at your thumb rule would be if I asked someone "have you used this language", the majority of answers should be "oh yes" or "no but I'd like to".
  6. Slack's official support for an SDK for a given language is not essential, but having one would be huge. Either an official SDK or an officially endorsed SDK.

Things I'm not fussed about.

  • Dynamic typing vs static typing
  • Related: Language performance

These are the languages I considered (and did not consider as well)

  • Bash. Mostly suited for this kind of thing despite all the jank in the language. I don't know how to distribute it to Windows so out that went. Yes yes. Cygwin. Linux Subsytem. I'm familiar with them
  • Python. I love this language. And there are a lot of little tools to build a CLI with. Well supported ones at that. I have to admit though, the prospect of distribution has me stumped here. In all honesty, it's easiest if I asked people to just install python on their machines and used it. And that's not a great thing. It looks like there'd be a long time of experimentation with this one.
  • Ruby. Possibly one of the best candidates. The community is really well established. The practices are really well established. The language is a damn joy to use. There's a library called rb2exe which despite its name actually compiles applications down to "binaries" that target all platforms. There's even a good cli gem apparently. This one is in the running
  • Java. Nope. Like that's it. Nope. Jokes aside though, I can't get myself to go through the pain of setting up the dev environment for Java. Moving on.
  • Golang. Very strong candidate. Compiling to various platforms is built in. Patterns are well established. Tooling is polished. Package management feels a bit weird though. But it even has a great CLI tool.
  • Node JS. Another super strong candidate funnily enough. For command line interface building, there's commander. For bundling apps, there's nexe. And I absolutely cannot ignore the fact that whatever people's grievances are about Node JS's tiny packages, installing stuff to do basic things like make http requests is beyond easy with npm (or yarn, possibly with workspaces you hipster).

The short list

Golang. Ruby. Node JS.

The first step to cutting this short list is to examine the SDK's available for each of these languages.

  1. Node JS is the strongest of the three. It has official support for Slack which is important.
  2. Both third party libraries for Ruby and Golang are decently maintained, but Ruby's falls pretty short. I couldn't find any code that told me that it has the ability to update Slack's status messages. This isn't a deal breaker for me, but it does move Golang and Node JS into their own category.

Convention says that golang is the more popular tool for this kind of thing now. I don't want to select a tool based on popularity however. This isn't a mega project that's going to be maintained by a company. It's probably going to be just me working on it and at max, maybe another 100 hundred people using it. So at this point, I tend to not focus too much on the pros and cons of each language. I instead try to go from the perspective of which language style do I assosciate most with. Which environment do I think I'll be happier in. And from everything I've worked with in Node and Go:

  • I love npm package management so much more than Go's for small projects. Careful. Don't shoot! That said with deps being passed an official tool for go, I don't think that matters all that much.
  • Node's synchronous/asynchronous promises hoo ha is something I can get used to but I do not appreciate. Not one bit. In fact, I can't pretend to have ever understood its purpose since most operations are always asynchronous. What am I going to do if the Slack API is taking a long time to respond? Move on? Yes. I have a frustration with this one as one can tell.
  • At the same time, go has certain oddities isn't exactly easy to pick up to be honest. Despite being supported with gofmt tools and what not, I can't pretend that I fully enjoy it's little weird assignment syntax's and whatever I've used in the language isn't instantly intuitive. Also, I hate the idea of all go code lives in a single workspace. That isn't how my computer is organised mate.

To be honest, Ruby's language and package management combination for me is the prettiest of the three. But is it to the point where I could almost bear with the fact that I have to use an external tool to compile the application into a binary and that I don't have an external SDK for Slack?

I think I need to test Ruby's binary compiling tool and determine if it's easy or hard to use. I can bear with the lack of an SDK. But not the binary creation part.

  • Installing Ruby isn't straightforward for a development process. This is mildly a dealbreaker. But again since I'm the only one working on this, and it's a tiny project, whatever. I could probably use Docker to be honest.

15:25 So I just ran docker pull ruby:2.5.0 and then created a file called test.rb where all it had as contents was puts 'Hello world'. I then ran it by calling:

  • docker run --rm -v $(pwd):/src -w /src ruby:2.5.0 ruby test.rb and it output Hello world. Now to get this to be turned into a binary.
  • So here's what I did. (I first ran docker run --rm -it -v $(pwd):/src -w /src ruby:2.5.0 /bin/bash):
[email protected]:/src# gem install rb2exe
Fetching: rb2exe-0.3.0.gem (100%)
Successfully installed rb2exe-0.3.0
1 gem installed
[email protected]:/src# rb2exe test.rb 
Your ruby version should be EXACTLY 2.2.2, not higher, not lower (your is 2.5.0).

Ouch! That's not going to cut it unfortunately.I didn't see that in the project's README where it specifically mentions that v2.2.2 is a hard requirement and it's a TODO to support other versions.

15:31 And because the tooling around Ruby for this kind of project doesn't match up with my requirements, golang it will be.

This post is part of a series of logs exploring how I'm building a CLI for updating my slack status. You can follow the full project here

Posted on January 18 2018 by Adnan Issadeen