Inline Percent Operator in Ruby

ruby

A quick tip, which I hadn’t discovered even after several years of using ruby professionally - you can use the % operator as an infix operator to perform string formatting.

1
"%d%d%d-%d%d%d%d" % [8, 6, 7, 5, 3, 0, 9] == "867-5309"

It follows all the same formatting codes as the regular string format functions.

Dell D3100 Dock by DisplayLink With XPS 13 Developer Edition

computers

I own a 2015 Dell XPS 13 Developer Edition, which is a truly fantastic laptop. A quick product review: I recently purchased the Dell USB 3.0 Triple Display UltraHD Universal Dock (D3100) in order to help me use my laptop more effectively as a desktop replacement at work.

I bought the dock mostly because of the promise of being able to use 2 monitors with my laptop. The dock worked fairly well and it looked elegant. It replaced an Amazon Basics 7 port USB 3.0 that I had previously bought.

However, getting monitors set up was not easy. I attached two, year old 1080p monitors. They were, eventually, auto detected, but I had to reboot the computer several times to get them working, even after installing the drivers from DisplayLink.

But the worst part - using the monitors used 50% of my entire CPU speed. It seems that the display-over-usb-3.0 works by compressing video for sending on the CPU; in any case, I obviously could not afford to constantly use one full CPU core just for my monitors - and monitors that caused the mouse to flicker on the laptop screen, at that.

This is an issue that has been reported widely, so DisplayLink should have gotten a fix out already - and apparently, it might be ameliorated on more recent versions of Ubuntu. But the bottom line is that the Dell D3100 does not work out of the box with the XPS 13 Developer Edition - would not recommend.

Learning Us a Haskell for Great Learnings

haskell

I recently reconnected with a friend from high school, Vrushank Vora. Vrushank had been trying to teach himself Haskell, and suggested that we collaborate on teaching ourselves Haskell over the next few months.

I thought this was a great idea. I’ve tried Haskell before, but have never really gotten deep into it. I’m not quite sure why this is - I’ve written plenty of functional-style code in Ruby and Clojure - but perhaps being forced to write in a functional style stymied me more than I’d like to admit. It is, after all, very easy to fall back into an imperative style, if there’s nothing preventing you from doing so.

Here’s the quick notes of what we did, and what we learned. To prepare, we read chapters 2 through 5 of Learn you a Haskell for Great Good. Without much of a formal plan, we decided to try some exercises from Code Wars. We ended up only being able to complete the screener that Vrushank needed to do to sign up and one other exercise.

First discovery: you access the fields of a record-syntax defined type with functions that corresponds to the field names. That is, if you have data Person = { name: String } as your type, and a Person that you have bound to, say, person, you would access the name of the person with name person. This was a little counter-intuitive to me coming from an Object Oriented / Message Passing background, but is really quite a clean way to do it.

We then did an exercise on writing a function to determine if a string is an “Isogram”, that is, if all the letters in the string are unique. This one took us a little longer.

I will say that the red-green-refactor strategy worked wonderfully for us. Our first version of the function was something to the effect of:

1
2
3
4
5
isIsogram :: String -> Bool
isIsogram xs = if null xs
                 True
               else
                 not ( (head xs) `elem` (tail xs) ) && isIsogram ( tail xs )

But, we ended up refactoring the code to be fairly beautiful, something to the effect of:

1
2
3
4
5
6
caps :: String -> String
caps = map toUpper

isIsogram :: String -> Bool
isIsogram "" = True
isIsogram (x:xs) = (toUpper x) `notElem` (caps xs) && isIsogram xs

There was an alternative solution that did not define a caps function. One of the questions I have is - which would be “better” Haskell? Is it better to define lots of named functions, or fewer?

Starting on MobiDick

codenewbie

Today I started working with Kerrie on a new web app: MobiDick. Kerrie is a good friend of mine who has been trying to figure out what to do with her life - and considering getting into tech - for a while. Over the past nine months or so, she’s taught herself a good bit of programming.

Like all new programmers, though, she ultimately needs to make the leap from “someone who can code” to “someone who can develop software”. The only way I know how to do that is to try doing a “full size” project, with all of the bells and whistles and pains.

Hence, MobiDick. The idea is simple: why doesn’t Project Gutenberg have a “Send to Kindle” button? And why do I have to store the ebooks that I purchase outside of Amazon, but ultimately upload to Kindle - like those from the Pragmatic Programmer - on DropBox? Why can’t I have a nice web interface for managing my non-Kindle-store books?

This is a nice sized project for a beginner, for a few reasons:

First, it’s of appropriate scope. You can get started with a single form and a listing.

Second, there are lots of directions to take it. Implementing a fully featured site will require all the key web application patterns, including authentication, file uploads, email notifications, regular notifications, comments, ratings, and the like. But there is room to do more! Just in our first planning session APIs to interact with a mobile app, background processing books to convert their file format, and actually figuring out the .mobi format so that we could make edits to the books came up. Plus the idea of writing a chrome extension to automatically send fan fiction to your kindle. There’s lots of opportunity to implement cool, challenging things, beyond your standard Twitter clone.

Third, it’s dear to Kerrie and my heart. Why build another Pinterest clone when you can build something that actually fills a need you personally experience?

Kerrie’s goal, as far as I know, is to learn more about web development, and develop as a programmer. My goal is to refresh my knowledge of Rails and early project development, and of my methods of teaching. Although I’ve onboarded several users onto existing applications over the past year, I haven’t worked with anyone as novice as Kerrie, and I haven’t done any greenfield projects - I want to make sure my skills stay up to date, and I find that teaching is the best way to do it.

The project will simulate, as accurately as possible, the real experience of being a programmer working on a small team for a medium sized web project. We’re recruiting a friend to serve as the product owner, and pedantically reject our stories in Pivotal Tracker. We’ll be doing user tests with some other friends who are kindle addicts. And the app will ultimately be deployed to Heroku just like any other real application.

Speaking of Pivotal, our first planning session was purely on the topic of Pivotal Tracker. Pivotal Tracker is the project management tool offered by Pivotal Labs. I’ve been using Tracker for almost two years now on all of my professional projects.

Introducing Tracker almost always has a learning curve, but introducing it at the same time as Agile is even more of a shock. Kerrie has never worked on a real project before, and hence has no familiarity with Agile or Scrum. I made the mistake of introducing Tracker first, then sort of talking about Agile once we had it open; I think it would have been more effective to introduce Agile first. The key points we covered were:

We probably could’ve skipped points for now, but since I was introducing Tracker, had to discuss them, as Tracker won’t let you start a story without assigning it a point value.

One note: The new tracker intro video, which Kerrie saw when she created the project, was very good. The explanation is much better than when I first started using Tracker. That said, I do not know why Tracker still defaults to a split “Current” and “Backlog” view. I always combine the views, and Kerrie initially was confused when estimating a early-in-current story at 8 points pushed sevearl other stories off of current, and hence, off of her screen. It definitely was not intuitive at the time - I think this part of their onboarding could be improved.

We then sat down to write stories. I do my best to offer guidance, instead of taking over the situation. We started with some great ones:

First comment: Why is everyone’s first story user log in? I suppose it’s obvious

We then started fleshing these stories out. This will, of course, be an ongoing process.

I tried to focus my prompts in two types:

First, disambiguating nouns. “As a user, I can scan the bookshelf” is a great start to a story - I actually think scan is a particulary good choice of word, because it helped us come up with some more interesting ideas of what “scan” means - but it prompts questions about what is a bookshelf.

So, we ended up with some new stories:

I also pointed out the question: where do books come from? So,

I then went ahead and added - I should not have done this -

In retrospect, it would’ve been better to let us discover this naturally. That said, I’m trying to balance expedience of teaching with the teaching, so hopefully it will not be too worthless.

We also came up with some fun reach stories:

That last one is my favorite - the idea being that it’s the same as writing in the front cover of the book, if you then lend it to others We also ended up with a couple that will need fleshing out, like “As a user, I can receive notifications” (notifications of what? from whom?)

The final list we ended up with as our current section, in order:

And that was the end of our 90 minute work session. I’m really looking forward to implementing these stories!

You can follow our PivotalTracker publicly here

Start Using Squish in Rails

rails

Just a quick tip - how many times have you found yourself cleaning up strings (maybe user input?) by doing things like this:

1
string = string.gsub(/\s+/, " ").strip

and the like? You want to replace consecutive whitespace with single whitespace and remove beginning and trailing whitespace.

If you’re using rails, try squish - squish. Note that squish removes newlines, so it may not be appropriate for every scenario, but it’s a generally very useful function.