Saturday, December 20, 2014

Word frequency counter in Elixir

Before I got into web/software dev seriously, I was pretty serious about literary analysis. (Ask me sometime about how pregnancy and history work in Edgar Rice Burroughs's Princess of Mars and Ursula K. Le Guin's Left Hand of Darkness.) And these two loves came together a few years ago in a new-ish field called "digital humanities": the crunching of literary data with computers.

For instance, we could go through an entire writer's work and see what words got used most often--or not at all. (Fun trivia for nerds: Lovecraft uses the word "squamous" only once, which is funny because parodies of Lovecraft love that word.)

Which is a long intro to explain why I like writing word-frequency counters in new programming languages. So, to count words in Elixir, you could use this:
  1. defmodule Words do
  2. @doc """
  3. Count the number of words in the sentence.
  4. Words are compared case-insensitively.
  5. """
  6. @spec count(String.t) :: map()
  7. def count(sentence) do
  8. sentence
  9. |> prep 
  10. |> count_words
  11. end

  12. defp prep(sentence) do
  13. sentence
  14. |> String.replace(~r/([^\w-]|_)+/u, " ")
  15. |> String.downcase
  16. |> String.split
  17. end

  18. defp count_words(words) do
  19. Enum.reduce(words,, 
  20. fn(word, map) ->
  21. Map.update(map, word, 1, &(&1 + 1))
  22. end)
  23. end

  24. end
Commentary: @doc and """ are for heredocs. Now if I type "h count" into the terminal, I'll get back that info.

You'll also note two things: (1) the program is written with two helper functions, in classic modular fashion (and these functions are defined with defp, which makes them private functions, only call-able by functions within the module); (2) Elixir uses pipes (|>) as a way of handling and handing off data. And I love pipes. 

Check out prep, a pretty straightforward way to prep a sentence for counting (with line numbers to help follow): 
(14) it takes the sentence; 
(15) runs it through a regex replacer to get rid of anything that isn't a word; 
(16) then runs that new string of just letters through the downcase function; 
(17) then runs that newly downcased string through a split function, which works like all split functions seem to work, taking a string and returning a list of strings. 

Now, if I wasn't piping, I would have to include the parameter, like
But when piping, the first parameter is assumed to be whatever is piped in. Now, without piping, I could write this sequence of functions pretty easily, and it would look like this:

String.split (String.downcase (String.replace(sentence, ~r/([^\w-]|_)+/u, " ")))

Which I can read, but which is a little less intuitive, because you have to read it backwards, with every left-side function taking as parameter the output of the right-side function. Yuck.

Then we get to the heart of the word counter program, the count_words function. This function is doing something interesting--and wasn't my first version of this.

My first version:
  1. defp count_words([], acc), do: acc 
  2. defp count_words([head | tail], acc) do 
  3. quantity = Map.get(acc, head, 0) 
  4. acc = Map.put(acc, head, quantity + 1) 
  5. count_words(tail, acc)
  6. end
My first version was a fairly standard tail recursive function that went through the list, calling itself until the list is empty. When the list is empty--i.e., when line 1 is called because the first parameter matches the empty list []--it returns the accumulator. If the list is not empty, it processes the word in a pretty standard way: words and values are saved in a map (which is a key-value structure like a Ruby hash), so I pull the old quantity from the map and then update the map with the new quantity for the word.

So let's look again at the second (or third) version:

Second version:
  1. defp count_words(words) do
  2. Enum.reduce(words,, 
  3. fn(word, map) ->
  4. Map.update(map, word, 1, &(&1 + 1))
  5. end)
  6. end
So, the heart of this is still a Map function; here, we call Map.update with the map to be updated (map); the key to be updated (word); the initial value to be used if the key is not found (1), and a function that tells how to transform the value if the key is found ("&(&1 + 1)").

We could rewrite that to make it clearer for new Elixir users, like: 
Map.update(map, word, 1, fn(x) -> x + 1 end)
But the real magic is Enum.reduce, which does all the work of going through a list until it's empty and resolving all the data in that list into a single structure or value. For instance, a classic use of Enum.reduce would be to sum all the numbers of a list:
Enum.reduce([1, 2, 3], 0, fn(x, acc) -> (x + acc) end)
So we have the list to be reduced ([1, 2, 3]); the initial value to use as the accumulator (0); and a function that tells reduce how to resolve all the elements of the list into a single value ("fn(x, acc) -> (x + acc) end").

(P.S. That's the long way to write the function, which I did to make the action clear; i.e., we take two parameters, the element of the list (x) and the accumulator (which starts at 0), and we add each of them. The really short way to say that would be &(&1 + &2). Awesome.)

So the Enum.reduce in this function takes the list of words; accumulates it in an empty map; and the function that it uses to resolve the list into the map is ... the Map.update function that adds one to the value of the word each time it finds that word.

Saturday, December 13, 2014

Shiny new computer, cruddy old flu, fun new Fizzbuzz in Elixir

I just updated my LinkedIn profile, so I might as well update you here: my new job is as a junior developer at Clutch Analytics, the digital invention arm of Windhaven Insurance. And this last week was my first week there.

Which makes it the perfect week for me to get the flu. Ah well, that's only tangentially related to coding, so I'll leave it at this: a slight fever might, occasionally, be helpful when studying a new language.

Another issue that's only slightly related to coding, but which I have to bring up here for other junior developers--especially those who come straight out of school without much work experience: starting a new job involves a lot of logistics, including filling out paperwork. (Note to self: fill out paperwork this weekend.)

So now I have a new(er) computer, set up with my preferred configuration; the lingering effects of a flu; some health insurance paperwork to fill out; and some fun Elixir challenges. To that end, I've (thank god) gotten back to committing to my Github, which has a new repo for Elixir challenges. The first, of course, is Fizzbuzz.

Saturday, December 6, 2014

Elixir Week, Day Five: Not quite as Elixiry as expected

When I titled my last blog post "Day One," I thought I would do a little Elixir each day and report on the fun things I found--

like the difference between case and cond; or how the h before a function name actually gets the documentation from the code file

--but since this week was also my last week home before moving to Austin, I've had quite a few other things to do. Like find a place to live and shower my dog with affection in the form of walks.

And also look through some Tom Green Country library books. In the future, I will create a page just for the books I've read, with some notes, both general and specific.

For instance, I read that O'Reilly book on Version Control with Git. (I do love to see which animal gets which book: Version Control is a bat.) So the general remark might be: "In-depth look at Git, more than really necessary for daily use. Excellent chapter on merge control." And some specific remarks might be "Use rm command."

(For some reason, I've never had reason to rm a file from my git index.)

And about Learning JavaScript Design Patterns, I'd probably say "Get it for the MV* chapter; though some of the other material feels a little too abstract if you're not trying to apply it to project; and some of it feels a little too concrete if ditto. Not an introductory book to design patterns."

But that seems to be the way with computer books, I find: there's a lot of danger that they'll be too abstract or too concrete or too in-depth for what you need right now.

So, you read any good books lately?

Tuesday, December 2, 2014

Elixir Week, Day One: books and just-in-time-learning

In a week, I start work at my first engineer/developer job; and so, while I'm trying to wrap up some other projects (including purely logistical (i.e., boring) projects having to do with transportation and shelter, ho-hum), I'm also trying to do some prep work for that job.

Which involves getting myself up to speed on Elixir, a functional, concurrent language built on top of the Erlang Virtual Machine. (Shout out here to my 10+ year old comp sci class for covering virtual machines. Of course, we couldn't cover Elixir back then, since Elixir is only 2 or so years old.) And so, I'm declaring the first week of December, Elixir Week.


Elixir Week, Day One

Thankfully, I had no trouble installing Elixir with just brew install elixir on my MacBook, which nicely installed Erlang as well. I've seen so many hours gets eaten by some seemingly simple step that I'm always thankful when this first step goes smoothly.

(If it doesn't for you, there's a few different methods for installing Elixir, some more involved than others, and hopefully one will work for you. See here for installation instructions.)

And so I could dive right into the official (I guess) Getting Started guide for Elixir, which starts, as most guides do, by talking about basic types, like integers, strings, and atoms.

Er, what's an atom? In Ruby, we'd call it a Symbol, but the Elixir guide goes on to define an atom:
Atoms are constants where their name is their own value.
And already I know this is a language that Jorge Luis Borges would love. There's a lot more in that getting started guide, but I just want to point out (for myself) some things that will be useful to remember.

> When talking about a function, the convention is name / arity, where arity is how many parameters it takes. So: IO.puts/1 refers to a function (IO.puts) that takes one parameter.

> To get help about a function, type and then the function name/arity.

> Elixir data types are immutable. (Not news, but something I'm going to need repeated.)

Books and JIT learning

Reading up on Elixir is fun, but reading about a language is, let's say, only the first step in getting to know a language. Trust me: I used to pronounce "awry" as "aw-ree" because I only ever saw it in books.

I'm not sure if there's an ideal way to learn a language; it probably differs for everyone. For me, I like a little abstract learning and a little getting-my-hands-dirty in equal measure. So while I've been reading the Getting Started guide, I've occasionally turned to my Elixir terminal and tried a few things. "Oh, I can do a boolean AND like this--but can I do it like this?"

Which is to say that I'm a big fan of just-in-time learning. I can pack my head full of data about a language, but they only start to become real information when I put it into practice. (Or: fail to put it into practice. That's a teachable moment right there.)

And that's why I have a complicated relationship with many coding books. Give me a book with some coding challenges interspersed and I'm pretty happy. Don't--and I won't be. Which is why right now, while I'm in San Angelo, I'm flipping though a library book on Git. It's not a deep dive into all the mechanics of Git. (Do I really need to know the history of Git to do my job? Probably not.) But it is one of those aforementioned projects that I'm trying to wind down before work starts.

Sunday, November 30, 2014

Post-MakerSquare, Week Two: Keeping your code sharp--and, oh yeah, about that job search

How do I not have just a plain jane "Coding" tag? Anyway, welcome to the tag family, "Coding"!

And I want a "Coding" tag here because I want to talk about a website that I have fallen in love with recently:

It is very much like those other websites where you get coding challenges, e.g., CodeWars, Project Euler, etc. (which I also like). That is, the goal of isn't to build any project (which I still maintain is the best way to really get into the nitty-gritty of a language), but merely to play around with a few challenges.

I especially like how keeps everything real clean and focused. Rather than running a test online (and oh, how online tests have given me heartache), you run the tests on your computer--as you would normally. also has a nice breakdown of various languages, so that you can try only the Ruby challenges or the Clojure challenges; and after you submit one solution, you can fetch the other. (The interface is not unlike Github, which is another reason I like it.)

And then, best of all, you get some commentary and feedback on your code. Because, sure, my DNA/RNA transcription agent worked, but the real benefit of using this is I have now discovered a new method--String#tr--that I never used before and wouldn't have used if I hadn't seen someone else use it.

So, if you want to practice a new language or keep an old language sharp, I recommend at least looking at


And about that job search, I've been offered and accepted a junior developer position. So I'm off the market for now; and very excited about starting in early December. I will say more about the job and the company--after I reread my NDA and figure out what I can say.

For now, my new challenge--both for fun and for work--is to learn functional coding. Come on, O'Reilly books, don't fail me now!

Sunday, November 23, 2014

Post-MakerSquare, Week One: Don't be so apologetic on the job search (plus bonus FizzBuzz)

"So, one note for you," said a mentor, after I went through a mock technical interview, "is: Stop being so apologetic."

Which really might be the centerpiece of why I don't love interviewing. I mean: I love talking to people, I love asking questions, I love answering questions. God help me, I even love coding challenges. Ask me to do FizzBuzz in one line, please!
Sidebar: How to do FizzBuzz in one line:

(1..100).each {|num| num % 3 == 0 && num % 5 == 0 ? (puts "FizzBuzz") : num % 3 == 0 ? (puts "Fizz") : num % 5 == 0 ? (puts "Buzz") : (puts num) } 
It's not pretty--or really all that maintainable--but it works in one line. (Note: tested on; and inspired by a Paul Irish post.)
Let's break it down:
  • 1..100 -- standard Ruby for an inclusive range
  • each -- loop over each element in the array/range and slip it into the following block
  • followed by a cascade of ternary conditionals
    • if it's divisible by 3 and 5, put "FizzBuzz", and if not, then
    • run through the next case (divisible by 3) and if that doesn't work,
    • run the next case (divisible by 5), and if that doesn't work
    • just put the number already
But I don't love selling myself. When I'm discussing my projects and my web dev foundation, it's pretty tempting for me to pick at the issues or the lessons (i.e., the mistakes that I made). Largely that's because of where I am in my career--just beginning, with plenty to learn and a big hunger to learn it. I mean, I really liked the early hackathon project we did, but weeks later, I can see some of the holes there.

Looking at those holes can be very educational and even rewarding. ("Look, ma, I'm learning!") But they don't always make the best interview discussion.

So, dear mentor, I'm going to try to be less apologetic during interviews.

And wouldn't we all rather talk about FizzBuzz anyway?

P.S. For actual information about my job search--well, I'm not going to get into details. Suffice it to say, I'm concentrating on Austin right now, with an eye cast on Chicago; I'm looking primarily for, let's say, middle-end to back-end--anything below HTML/CSS, which I can do, but don't enjoy as much. I've got some leads and had some positive interviews, so I feel OK. But I'll be 100% honest with you: I'd much rather be coding than searching for a job.

Saturday, November 15, 2014

MakerSquare Day 58: And so it begins... or ends... or ends and begins. Or maybe just goes on (12/5)

So, today was our last official day at MakerSquare, and after some teary-eyed goodbyes, it became clear that a lot of people will probably be around on Monday.

Because even though we're done with one step--the immersive, 12-week course--we've got a lot more to do, both in terms of our development as web developers and in terms of our job search.

That said, I think it's important to take a moment to appreciate how far we've come, both individually and as a group. I remember back to our first day--well, I don't have to remember it, I can just point to my blog post about it here. Back then, we were told to parse a list and the class largely responded with "what a what now?" We were told to model a recipe and I thought about striking a model pose.

Well, OK, maybe we weren't that clueless, but we were pretty close.

And now, after 12 weeks of constant and steady work, all of us had several projects that we could show off pretty successfully. Many of us have already posted about our projects (on reddit and elsewhere) or posted our projects online for everyone to use (more or less). We have portfolios.

Some of us even have interviews and contacts; and all of us have pretty good prospects for the future.

So, I have a bunch more to do today and beyond, and I fully plan to keep up with my blogging. On a more limited scale of course. As we move away from the daily blog, with me memorializing my time at MakerSquare (for potential and actual students to check), I hope to transition more into helpful bits of code I've discovered or made; and a record of projects that I'm working on.

I hope the last 12 weeks of blogging have been helpful or interesting. The last 12 weeks have been both for me.

Also, one last comment about our last day: a week ago, a classmate of mine said that we should have a high-five graduation ceremony, where everyone got to play one song and go around the room high-fiving everyone. At first, I wasn't sure about this idea: is that really how we wanted to go out?

So let me offer this advice for you: if someone asks you if you want to play a song that's meaningful to you and high-five everyone after working really hard for 12 weeks--you say yes.

(For those interested, the songs ranged from triumphant for finishing the course; to hopeful for how we're going to get better at this; to joyful. I can't help but jump to Icona Pop's "I Love It," which was one of the songs on repeat during my finals weeks.)

Friday, November 14, 2014

MakerSquare Day 57: Open House: The real short version (12/4)

And a good time was had by all. I'll have more to say when I've collected my thoughts, but the slightly longer version of the real short version is--I talked to some people. Everyone was nice. People seemed to like my projects.

And now, time to get some rest.

Just kidding: now I want to read a book about Scala and functional programming.

Thursday, November 13, 2014

MakerSquare Day 56: The short version (12/3)

For those of you who aren't going to make it to the open house tomorrow, I wanted to present a short, bullet-pointed version of things I may talk about. (It's OK, it's supposed to be terribly cold tomorrow, I get it if you can't make it.)

OK, so maybe this is just 15 minutes of me trying to articulate this stuff that I've been working on for a while. Starting with...

About me:

  1. My career(s) and interests have taken some left and right turns, though you'll see a lot of themes running through--
  2. People: I like working with people, I like working out problems with people in discussion, my dissertation was going to be on groups of people working together. Heck, even improv is primarily around being a good teammate. (And, though this is my professional blog, let's add here that I moved from Chicago to San Angelo, TX because my girlfriend got a job there. That too is about my love of people--or at least my love of one particular person.)
  3. I like paying attention to detail--and I can tell you at length how close-reading in literature or paying attention to your improv team is a lot like double-checking your code before shipping it.
  4. I like innovation and experimentation and getting better all the time. And here's the part where I kind of have to slag on my grad school experience. Not that English departments don't like innovation in certain ways, but those ways are somewhat limited. (Though, again, I can go on about the digital humanities/big data in literature movements.) But in web development, everyone I talk to has some interesting side project or is learning a new language or BUILDING A NEW FRAMEWORK. In a weird way, web development combines my loves of creation and analysis.
About my Chrome extension:
  1. I knew it had to be a Chrome extension since it ran on the back of another site. (Which limits the applicability, but also made it easier to scope the project.)
  2. I spent several days of the development cycle home sick, trying to read up on the subject; but as with most things CS related, reading gives you maybe half of the info--it's usually more informative to just get your hands dirty.
  3. A Chrome extension is a lot like a regular website in terms of stuff in it--HTML, CSS, JavaScript. (You can even put Angular in! Though that didn't seem like a good way to go for my extension.)
  4. But the architecture is very much based on convention rather than configuration: there's a way that things are done and you just have to learn them. So, for instance, content scripts are the only way to affect the DOM, while background scripts are sort of a virtual space where you can pass info from content to the browser itself and the pop-up window.
  5. I played around with the omnibox before deciding on a pop-up interface.
  6. My biggest difficulty was figuring out how to get it to re-run when new tweets get loaded, until I found out about Mutation Observers, which are perfect and new-ish, since they are objects with special methods for watching for changes.
About my ShareCare app:
  1. The idea that I came with, inspired by my experience of sharing responsibility for a dog.
  2. (I even tried to set up and send out a survey inspired by my watching of the Coursera course on Human-Computer Interaction. I did not get a lot of responses.)
  3. My biggest (first) difficulty was exploring some options for tech stacks to use. For instance, I never used Foundation or Bootstrap before, so I wasn't sure which might be better for styling. (I went with Foundation, which I was moderately happy with, except for some bobbles trying to get Foundation and Rails to work nicely together.)
  4. Rails was a lot of fun to work with, in part because it's so smart. You want an AJAX request from a button? Just add "remote: true." You want to separate out your page into modular parts so you can handle each part individually? Let me introduce you to partials.
  5. The second difficulty was thinking about how to best design the database. Just a few days ago I realized I could drop one whole table (Claims) and make the same call by just paying attention to the Task table's "completed" and "user_id" columns. (The lesson, as always: Don't make things more complicated than necessary.)
  6. The greatest lesson of dealing with a big project like this is the modular approach: break it down, and fix one thing at a time.
  7. I probably learned more from this project--both the mistakes and the successes--than any other project.
  8. Also, I have a ton of ideas for how to expand and improve this project. Though as it stands, it fits the need I had of passing info between me and my girlfriend about whether the dog's been fed or not.
OK, so that took longer than 15 minutes, but it's going to be mighty cold tomorrow, so some Austinites might not make it out.

Wednesday, November 12, 2014

MakerSquare Day 55: "I have the skills." (12/2)

That's my takeaway quote from tonight's alumni panel discussing, well, what it's like to be an alumni of MakerSquare. "I have the skills" was the realization that the alumnus in question had when working out a problem at their job. Maybe they didn't have the knowledge, per se; but from their time at MakerSquare they had the skills to find the answer.

Though today's panel was only a few hours of the day, with that sort of positive message, it certainly left something of a influence. Or maybe that's just how it is when people share their horrible interview stories.

(Although, is it wrong that every time I hear an interview story involving a coding challenge--like "reverse a string in JavaScript"--my brain always stops for a moment while I work out how I would do that? I guess the lesson here is, if you need to distract me, give me a fun coding challenge.)

(Also, it's a lot easier to laugh at horrible interview stories when the people are not employed and happily so.)

But really, today was spent doing a rather large amount of tasks. Is there anything better than crossing tasks off your task list? I don't think so, which is probably why one of my final projects is all about creating tasks and then marking them as done.

I also realize that I've been talking very vaguely about my final projects and about things I've learned. Well, OK, I did write about how to make a Chrome extension, both in general and in particular.

But what about Rails, which is what my ShareCare app uses? What about Foundation and HTML and CSS and JavaScript? (OK, not I'm just listing my tech stack.)

I'm coming to the end of my allotted 15 minute writing time, so I won't be able to get into all of that today. But I will say this: one thing that I've learned through my weeks here is that documentation--even the littlest bit--can make a huge difference. When I go to find a Gem to do something and there are several out there (there's a lot of overlap among Gems), I tend to choose the one with the best documentation.

Which is why I spent so much time this week working on my Github README files and that's today's lesson: good documentation includes a clear README.

Tuesday, November 11, 2014

MakerSquare Day 54: Wherever you go, there you are. And your code is there too! (12/1)

We're coming down to the wire here. And as much as I want to look up where that phrase comes from--something about horse-racing, maybe related to a photo finish? or maybe something related to barbed wire and trench warfare in World War I?--I feel a little too busy.

I would love to slow down a bit and tell you all the stuff I'm learning and trying. "Learning" includes a lot of trial and error, so I'm learning a lot with my final projects.

Of course, one of the things I'm learning a lot about is me. (Also: Rails and Foundation.) Which reminds me that, a few weeks ago, while the full-time MakerSquare students were filing out and the part-time students were filing in, I made a joke of the form, "I thought I was learning about JavaScript, but I was really learning about myself."

(If I had had more time to think about it, I might have gone with a Russian reversal joke: "In America, you learn about JavaScript, but in Russia, JavaScript learns about you.")

Besides getting a laugh (which is the point of jokes, right?), it seems that I might have accidentally said something truthful there (which is the real point of jokes, right?).

I mean, working on final projects is a reminder of everything good and bad about yourself. I like working in teams or at least talking through ideas with other people. (Brainstorming for other people is one of my favorite things. What do you need? A title? An app idea? A villain for your superhero RPG? Whatever it is, I want to brainstorm with you about it.) So working on a project all by myself--not my ideal situation.

Similarly, I love doing research before attempting something; but, at least in this situation, I've learned a lot by just getting in there. As I learned as a kid, breaking something is one of the best ways to learn how it works and how to fix it (and how to run faster than my older brother). So that day that I spent reading the docs for Foundation wasn't any more helpful than the hours I've spent wrestling with putting that into practice.

Saturday, November 8, 2014

MakerSquare Day 53: Incremental (11/5)

I named this blog "Incremental Code" for the best reason of all: brand consistency. Either that or a lack of ideas.

See, my other blog--the one where I talk about movies and books (mostly)--is called Incremental Catastrophe. Which is a name I chose years ago to capture that feeling of sudden and irreversible upheaval happening very slowly.

So when I started this blog to focus on my MakerSquare time*, I went through a few ideas about what to name it before deciding that "Incremental Code" was, you know, good enough.

Which is how I've discovered that "Incremental Code" is the perfect name for a blog about coding for me.

MakerSquare's program is accelerated; and there have been times when my knowledge of these issues has gone up sharply. And there have been times when I've felt my knowledge increase barely. But if you were to draw a line of my learning, it would, overall, average out to a very reasonable, incremental increase.

Which is, coincidentally, how I would describe my coding process. Sure, there are times, usually in the shower or when falling asleep, when I am hit by sudden inspiration about how to solve some problem.**

But most of the time, I get the work done by sitting in a chair and doing the work. (That's a lesson I take into coding from my time working on fiction.) You move the code forward every day; and even an incremental process can result in a big step forward.

*Note to future MakerSquare students: writing every day may not be for everyone. But I would set yourself some schedule and stick to it. If you say, "I'll just write when I have something to say," you'll never write.

If you say, "I will write every week to summarize what I've learned," you'll find--magically--that you do have something to talk about every week. It's almost as if--as if!--putting your butt in the chair and getting to work can be productive and inspiring.

**Of course, that sudden inspiration only happens because I've been steadily working on that problem before the shower/sleep. Again: incremental.

Friday, November 7, 2014

MakerSquare Day 52: Ask and ye shall receive, time permitting (11/4)

I'm inspired by this recent week, when I really worked on my skills in one particular area: asking questions.

See, I've always been of the "let me try this for myself" bent. And I still am; but when it comes to web development, I've gotten better about setting myself a time limit. "Let me try this for myself--for a half hour."

And when that half-hour is up, I go find a peer or an instructor to talk through the issue. Thanks to that half-hour I spent, my questions are less  like "Help!" and more like "I'm trying to do X; I've already tried methods Y and Z and wrapped all the way around to A." So really, I'm glad that I try to do things myself.

But I'm also glad that I've gotten more comfortable asking questions about this.

I'm also glad that I've gotten more comfortable asking people for help. For instance, I reached out to someone who came to speak to us the other day, and he graciously offered to talk for an hour on the phone about some questions I had.

That's just one very concrete example of how, if you ask, sometimes you get what you need.

So, inspired by this last week, I wanted to ask you: do you have any questions?

Thursday, November 6, 2014

MakerSquare Day 51: "You don't know what you don't know." (11/3)

A very short blog post today--please, contain your disappointment!

I realize I didn't tell you my plan for this last week before our open house: having finished (for now) with my Chrome extension, I'm going back to my first project, Sharecare, which was really in not the best state.

Which is a shame for a few reasons: reason one, I would actually like something like ShareCare. (And yes, I'm inconsistent with my capitalizations because I haven't decided yet; tonight, I am leaning towards the camel case of "ShareCare.")

Reason two, the closer we get to our graduation, the more we're talking about the upcoming job search. For instance, today we had two lectures by outside consultants: a HR person and a VP of engineering. Which made for a very interesting day, if not totally coherent.

I mean, the HR person might be one of the first people to see our resumes: he's the guy who decides whether our resume goes forward after that first brief glance. (Note: Not him, exactly; he's pretty high-powered.) So he's looking for a certain set of skills on paper; and then, in a behavioral interview,  he's looking for a human being to fit a human-shaped hole in the company.

By contrast, the VP of Engineering might not see our resume at first; but he's not only going to be weighing in--and weighing heavily--on whether we've got the actual technical and human skills to fit in with the company on a day-to-day basis. Ultimately, if we get hired, we might not see the HR person, but we'll be working with the Engineering person.

So these two people come to the task of interviewing with a slightly different set of perspectives.

But--and here's my English grad school education to the rescue--I can see the patterns of similarity that run between these two widely disparate views. (If I were writing an English paper, I might call these "themes.") They may differ on some details, but the core advice is mostly what you hear about interviews: be the best version of yourself.

On top of that, both speakers hit the notion that informs today's title: at this stage in our career, we may have some ideas about what we want to do, either technology-wise (front- vs. back-end) or field-wise. But we don't know what we don't know, so we should also think about being flexible, not getting too tied down to any fantasy of what the right job would be for us. The right job might be something we don't even know about.

Wednesday, November 5, 2014

MakerSquare Day 50: How to Make a Chrome Extension, For Real This Time (11/2)

  1. the manifest.json: This is what makes the Google Chrome extension. This json file keeps track of everything you want to give this extension: all the permissions you give about what Chrome APIs it can access; all the files it has--background, popup, and content; and information about where the extension can run.
  2. a background file, either background.html or background.js: a background file is basically a pretend page--something the user never necessarily sees, but that helps organize all the other files; if you like visual metaphors, I think of the background as a highway interchange in my app: nothing happens there, but it's a useful nexus for talking between the other files (and also between Chrome itself--the background.js is what tells Chrome to show the little icon).
  3. your popup files, if you have any, often a standard mix of HTML, JavaScript, and CSS: many Chrome extensions have little icons and when you press that icon, you get this little popup window. That window is basically a little webpage: mine has HTML to tell what to show, some CSS to tell how to show it, and a lot of JavaScript to tell how it should behave.
  4. a content script: this is not necessary for all Chrome extensions, but is the only way you can have a Chrome extension directly affect the DOM of a particular webpage. So, I can make a new tab and go to a URL with a background file; but if I want to affect that page once I load it, I need a content script.
So if you have all these different parts, how do we get them to work together? Here's a few remarks on my Chrome extension (still available here):

Basic background: to pass messages between these elements, you need to use a pair of functions--a sendMessage and an onMessage function. So, for instance, when you go to Twitter, my content script runs--because that's what the manifest.json tells it to.

My content script includes this
  1. chrome.runtime.sendMessage({}, function(response) {
  2. storage.get('banned', function(blockedWords) {
  3. var tweets = $('li.js-stream-item');
  4. runBlockedWords(tweets, blockedWords.banned);
  5. });
  6. });
Line 2 here gets something from (which I aliased to the variable storage because I thought I might want to change it to And notice that the storage extension function here involves a callback--because almost every chrome.extension function involves a callback.

So we get an object from storage and we call that object blockedWords; but that object itself has a key named "banned"--which is why Line 4 involves blockedWords.banned, which is the value of "banned" inside blockedWords.

Also, note that this is the content script, so I can use jQuery to directly affect and access the DOM. In this case, I'm grabbing all the tweets that match li.js-stream-item--which is all the tweets currently visible.

Now, on the other side, in my background.js, I have
  1. chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
  3.   sendResponse();
  4. });
Line 3--as I understand it--sends a response message, which ends that message cycle. As you see, I don't have any actual message to send back, so I'm just sending an empty response.

Line 1 is the important part: it listens for a message. From where? From anywhere, I think. It just so happens that background.js will only hear a message when content.js sends a message--and that will only happen on Twitter.

That's important for Line 2, which is where I tell the browser to show the icon for the Chrome extension--but only on the page that sent the message (

And that's how I made (at least part of) my Chrome extension.

Tuesday, November 4, 2014

MakerSquare Day 49: How to Make a Chrome Extension (11/1)

This isn't step-by-step instructions for making a Chrome extension. It's not even step-by-step instructions for making the Chrome extension that I made this last week, a spoiler blocker for Twitter.

But yesterday I solved some final problems I had with my Chrome extension, Shush!, and I wanted to make a few notes about the whole process.

First, writing a Chrome extension is a lot like writing any code. You start with an idea.

Then, you realize that your idea is way too big.

There's no way you can, in the time given, make a program that will scrape data from the internet to find out what words are related to what other words, so that it'll know to avoid "#RedWedding" when you tell it you don't want "Game of Thrones" spoilers. It's doable--and I'm still excited by the idea--but it's not part of the week-long project to make a minimum viable product.

Other things that are the same when making a Chrome extension: your idea of what it should look like or how it should achieve its goal will change--be prepared to change it. Also, and as usual, every project consists of smaller tasks that are immediately solvable. The key to any project seems to be having that dual-minded approach: remembering the big picture, while focusing on the solvable modular bits.

And, as with writing web applications more generally, one of your biggest resources is things people have already done. There are a lot of Chrome extensions out there--and Google has a nice library of example extensions that just do one or two things; so when you know the specific task you have to solve, it's interesting to see how other people approached it.

Anyway, it's not finished finished. For one thing, my mentor just pointed out that I should include some contact information on it. But if you're here, that means you know how to contact me, so, if you want to see the rough but functional code, it's up on Github right now:

Saturday, November 1, 2014

MakerSquare Day 48: Second week of final projects wrap-up (10/5)

This post is going to be shorter than usual (and also a teensy bit late) because (a) my girlfriend and dog are visiting this weekend; and (b) my midweek sickness really knocked my schedule back. (Also, I am not well yet.)

But I wanted to record something about this last Friday, the last day of our second week, because (1) after a few days of not really being able to concentrate on learning this new technology/pattern/medium (it's hard to know what to call a Chrome extension), I was able to break down the big problem into very modular issues and solve them to my satisfaction. What a difference enough oxygen to your brain makes; and (2) though there was the typical office despair going around, I was really impressed with everyone's work and with the creativity that went into both coming up with a project and fiddling with the details.

I guess that means I have to make this Chrome extension really good. So I'm off to do that, while sitting with a puppy at my feet.

Friday, October 31, 2014

MakerSquare Day 47: Maybe locking myself in my room with the disease wasn't such a good idea after all (10/4)

I didn't get a lot of work done (or oxygen to my brain) today, which is a little disappointing. (Well, the oxygen thing is slightly more than disappointing.) But it does bring up something--in a round-about way--that I'm not sure I've talked about but which has been on my mind:

Why did I leave writing for code?

Well, I didn't really: I still enjoy writing fiction and plan to continue with it in the future. I just left behind the field of freelance non-fiction writing.

(Except for blogging, which you may notice I've kept to like a barnacle.)

As much as I enjoy writing, so much of it is solitary work. And, as I've been reminded by my unintentional quarantine, code can be solitary--but it can also be team-work. Even if you're not in an organized team, you'll find that an open-plan office leads to some interesting cross-pollination.

At the very least, when I'm at the MakerSquare office, when I hear someone talking about some interesting code--either an interesting solution or an interesting problem--it can sometimes get me thinking about something useful. Or when I run into a problem, there's usually someone around to talk it out, whether the other person provides a solution, a hint, or merely a willing listener while you solve your own problem.

In writing, that's not so much the case. Don't get me wrong: if you're working on something, you may have people you can turn to, whether it's your writing group or just a friend willing to read something. But there's not really that same sense of team-work and collaboration.

And that is one reason why I really don't like being stuck at home, sick, right now; and it's one reason why I decided to move into a coding career: I like teamwork.

Thursday, October 30, 2014

MakerSquare Day 46: Hackathon ::cough cough:: (10/3)

At MakerSquare, Wednesday and Thursday are given over to a hackathon--late nights, food provided, and lots of coding on the second final project.

Here at the DevHouse, my Wednesday and (probably) my Thursday are given over to a lot of cold medicine and vitamin C and tea. It's kind of a bummer in the way that minor illnesses during final project weeks are kind of a bummer. I'm supposed to be working my portfolio now, but instead most of my energy goes into getting tea. (Never again will I take my electric kettle--still at home in San Angelo--for granted.)

Ah well, I guess the only thing I can do now is get better soon.

That said, during my brief lucid moments--when the cold medicine kicked in--I did find an interesting tutorial on using Angular in a Chrome extension.

Wednesday, October 29, 2014

MakerSquare Day 45: Final project #2 -- but really home sick (10/2)

I went home early on Tuesday, since I've caught that cold that's going around. (Or at least, that my housemate has.) So this'll be a short post, with the sound of me sniffling and coughing in the background.

Luckily, Tuesday was the first day of our second final project, and I've chosen a manageable project right now / for once: a Chrome extension that will block spoilers on Twitter.

So I didn't get that much done on Tuesday since my primary goal for the day was to always have a hot tea with me at all times. But right now, here's the minimum viable product plan, some notes on my progress, and some current pain points, along with some extension ideas.

Minimum viable product:

  • The user can engage the extension and type in a word or phrase that'll trigger the blocker, e.g., "Game of Thrones."
  • All tweets with that word / phrase will be hidden (both words and pictures).
  • The user will be able to show any hidden tweet if they choose to by clicking on the hidden tweet.

Some notes:

  • At first I looked into grabbing all the children of the container object in the tweet stream:
    • $('').children()
  • ... but then I realized I could just grab the individual tweets directly (and put them into a variable, which I then iterate over):
    • var tweets = $('li.js-stream-item')
    • for (tweet in tweets)
  • It's not terribly hard to hide the tweets and pictures (though I also thought about other ideas, including detaching the material with .detach() ):
    • $(tweet).find($('.tweet-text')).hide()
    • $(tweet).find($('.js-media-container')).hide()

Some pain points:

  • Right now, I'm having some trouble putting in a button that'll respond to a user's click to show the hidden tweet. When I put something in the tweet space, it acts like a normal tweet acts when clicked, i.e., it expands.
Some extension ideas:

  • It would be super-neat for this extension to block tweets that had the trigger words, but also to find some related tweets to block. So, e.g., if you put in "Game of Thrones," the extension might also block out certain related words like "Red Wedding."
  • It would be (slightly less super) neat for this extension to be platform agnostic, so you could block spoilers in, say, Facebook or elsewhere.

Tuesday, October 28, 2014

MakerSquare Day 44: A different type of hackathon (10/1)

Today we had a hackathon, but not the usual kind. Today was our--

Resume Hackathon!

I'm probably just using bold here to make it sound more exciting. To be clear: the idea of going out on the job market; of going to interviews; of getting my first job in web development--all of that is very exciting to me.

But writing and revising a resume isn't as exciting as embarking on a lifelong career in a field that I'm kinda crazy about.

(Have I ever told you guys about meta-programming in Ruby? It's when you write code that then goes and WRITES MORE CODE. As a long time fan of infinite loops, the idea of code writing code makes me very happy.)

Part of the general (I think) lack of excitement when writing resumes is that resume writing is a lot more cramped than writing code.

Or rather: if I give you a coding challenge, you could probably think of five ways to code out a solution; and if any way fails, you'll get an error message that tells you how to fix it.

Man, I love feedback.

Unfortunately, resumes don't offer the same level of detail in their feedback. You get less "undefined variable" or "stack level too deep" and more "no thanks" and ::crickets::.

For me, with my big change in career from ex-PhD candidate and education writer to programmer, it's interesting to see how much of my resume is no longer relevant. Although maybe I should leave some of that in. Wouldn't you like to work with a web developer who once taught a class on 19th-century science fiction?


(Actually, now that I think about it, I think my teaching experience really does help me with both public speaking and with translating certain concepts into more easily digested forms. So, it's going back in the resume, people! Along with my improv classes at the Second City.)

Saturday, October 25, 2014

MakerSquare Day 43: A very little view of a week's worth of work (9/5)

When we did our hackathon, I was in a team of four people; Kelsey and I had whiteboarded (with our TA Ben's help) the night before and focused on our minimum viable product, with a whole bunch of extension possibilities; and the four of us had pretty distinct responsibilities.

So when I look at my current project and compare it to my hackathon project, I don't feel terrible that this project is not as advanced. I mean, we had 4 * 2 programmer-days for that, while I've only had 5 * 1 so far for this.

That said, I'd like to take the focus off of me for a second--just a second, mind--and talk a little bit about the cool things I've seen my peers make. Now, not all of this is ready for prime-time, but I don't think anyone would mind me talking about, for instance--

A neat little web app for playing pong (all in JavaScript);
The neat front-end design of a recipe box (with some very nicely done CSS);
The figuring out of the interface with Yelp API or Twitter API;
A large content management system service;
A well-constructed financial modeling system;
A way to get info from that pays attention to the performance issues;
A front-end only collection of math/science tools with a really nice panel system;
A neat list-sharing app with a great in-place editing system;
The updated and improved version of the hackathon flash card app and the ping pong tournament app.

Like I said, they're not all done. But when I look back at what my peers have done before and see what we're capable of doing now, I'm very proud.

Bonus: yesterday we had a meeting with some people from Ivity Labs, an offshoot of SpringBox, including a MakerSquare alum; and today we had a MakerSquare alum from Lou Malnati's in Chicago come by. All of which adds up to this:

When we started, we weren't that good; now, we're a whole lot better; and with just a little more experience, we have the capacity to be a whole heck of a lot better.

Friday, October 24, 2014

MakerSquare Day 42: Stone on stone--until ... (9/4)

I don't have anything to show you right now. I'm not entirely sure when I will. (There's a possibility that I don't have any website to show you to, but only some screenshots since we build most of our apps on our computers; porting these local "sites" to other sites can be done, but may not be worthwhile at this stage.)

But rest assured, when you spend several days moving stones, eventually you will have...

... something resembling a pile of stones.

That might not sound like much, but I'm actually very excited. Because--and watch this metaphor of stones get extended--sometimes it can feel like you're hitting your head on a stone wall and not accomplishing very much. But sometimes some stones get dislodged with enough hitting. And then you might notice that some stone that you're looking at is actually the perfect shape to rest on this other stone that you just happened to be looking at.

(I don't want to over-dramatize the importance of happenstance and luck; but if you've spent as much time in libraries as I have, you know sometimes the important book is right next to the book you went to find. Almost the same could be said for coding: you can go research AJAX calls and instead find a cool Ruby gem for editing in place.)

All you need is time, a head hard enough to survive repeated pummeling, and the will (and curiosity) to keep going on moving stone after stone.

(To be more--ahem--concrete, today we learned about Promises in JavaScript (which is a way to chain asynchronous calls); and I got my database tables all re-written to do what I know think they should do.)

Thursday, October 23, 2014

MakerSquare Day 41: Commas; or, Masonry, Part 2 (9/3)

Oh, I remembered the joke I was going to use yesterday--and it wasn't actually that good.
Oscar Wilde comes into the pub at lunch, looking exhausted.
"Hard morning of work?" asks the publican.
"Yes," says Oscar, "I spent all morning putting a comma in."
Oscar has lunch, leaves, and comes back for dinner, looking exhausted.
"Hard afternoon of work?" asks the publican.
"Yes," says Oscar, "I spent all morning taking that comma out."
There are (as I've said before) some big similarities between comma world and coding world; and, in fact, a lot of today has felt like some version of this Wilde joke. Like:
"Oh, I should add in a section on all pages that will be blank unless there's been an error and that section could report the error."
Then, later:
"Hey, I just implemented a section for good messages under my section for error messages. Why not just make a section for messages and pass in any messsage--good or bad?"
That's not the only example of an added comma/removed comma shuffle. And I won't lie, I understand why Wilde might be so exhausted after a morning and afternoon wrestling with a comma. He feels--and I feel--exhausted because it is exhausting.

So why keep doing it? Because Wilde and I are secretly masochists who like torturing ourselves? No. Well, maybe a bit of that. But mostly because this thing that we're so exhausted by--we're making it better by playing with it.

Alternate possibility: Maybe Wilde just didn't know how to use a comma correctly?

Wednesday, October 22, 2014

MakerSquare Day 40: Masonry (9/2)

I thought of a really funny--and also insightful and humane and most of all, humble--joke to start off today’s post; but it was quickly forgotten during today’s grind.

“Grind" might be the wrong word to describe today’s work on my final project #1. When I hear “grind,” I imagine one stone … ::looks up synonym for “grind”:: … pulverizing another. Slowly, thoroughly, with great and terrible purpose. So after a full day of grinding, I expect a lot of dust and debris--and not a lot of stone.

Whereas today, yes, there was some dust and debris (some rejected bits of code and collections of bookmarked websites answering questions I'm no longer asking). But at the end of the day, there were a few more stones on stones than there were yesterday.

Which is why today’s title is “masonry.” It’s not a romantic, fantastic word. No one raises a flag for masonry. (Well, except maybe the Masons.) 

But masonry gets stuff done.

For instance, I figured out how to alter an ActiveRecord database table when I'd already added an email column and needed to re-add it to use the Devise gem's authentication capabilities. (The secret is t.change in your migration.) That said, today was also the day when I realized that security is not part of my minimum viable product.

Maybe "minimum viable product" should really be today's title. Or maybe I should go with my first choice and just get that tattooed on my hands so I always remember.

Because masonry gets stuff done, but it takes time.

Tuesday, October 21, 2014

MakerSquare Day 39: ...but implementation is hard (9/1)

Last Friday was a reminder that ideas aren't all that hard to come by. (Especially when you are a student and can feel free to, you know, steal from major companies and try to do it yourself. Because, honestly, my version of Facebook isn't meant to compete with Facebook, but merely demonstrate that I could make one.)

But today, Monday, was all about how putting ideas into practice is hard. Because today, I started to work on my first final project.

I'm calling it ShareCare: a web-based, mobile-ready(?), team-based app for sharing caretaking duties and keeping track of those duties.

And yes, it was inspired by the fact that my girlfriend and I sometimes need to communicate about whether the dog's been out and pooped (or as we say, "was productive").

So, in honor of the difficult process of implementing the (pristine, beautiful, unsullied) idea, here's some photos of notes I made as I attempted to chart out my path on ShareCare.

1) Minimum viable product:
Here's a reminder when doing, well, just about any product. You may be making something incredible, but you start with a deadline and a minimum viable product. Anything that's cool that's not part of the minimum viable product goes into the bucket.

2) "Weeks of programming can save hours of planning":
That's an old coding joke; it's also the reason why I didn't write a line of code until I had mapped out my database and the relations between these entities. (Note: And I still had to go back to change a few things!)

3) Don't be afraid to make mistakes:
If we were supposed to do everything right the first time, we wouldn't have invented erasers. Or, in my case, invented more ink to cross out things--and then even more ink to re-write what I crossed out.

Let's see what I can show you tomorrow.

Saturday, October 18, 2014

MakerSquare Day 38: Ideas are cheap (8/5)

I've said it before--and gotten some annoyed looks about it--but I'll say it again: ideas are cheap.

Note: I say "ideas," not "good ideas."

But even with that caveat, I feel like my training in creative and non-fiction writing gives me a perspective on idea-generation that could get me some annoyed looks. So, to be clear:

When I say "ideas are cheap," I don't mean, "Ideas are cheap for me, I have a million ideas, they just come to me like a friendly bird":

I mean "ideas are cheap for everyone."

Sure, some people have blocks or difficulties--like the block where they tell themselves that they are not all that creative.*

*Sidebar: OK, I have three experiences that give me a different perspective on idea-generation:
  1. my grad school career, where I both had to come up with paper topics and teach students how to come up with paper topics;
    • killer question: "what's weird about this book?"
  2. my creative writing hobby, where I kept long lists of things that sparked ideas;
    • killer habit: writing everything down--everything from full-blown ideas, to notes on characters/settings, to single lines of dialogue, to single words that seemed stuffed with potential;
  3. my roleplaying/gaming life, which taught me that I could come up with ideas;
    • killer experience: playing a game recently with another MakerSquare student who started out saying "I have no ideas" and ended the game with "what if this happened? What if this other thing happened?"
End sidebar.

But really, if you don't self-sabotage by telling yourself that you have no ideas, I'm sure everyone can come up with a bunch of ideas. (Remember: I'm not saying these ideas are good.)

You could start with thinking about your day: what would make any area of your day a little better? What would help anyone you know?

Now branch out from there into things you're interested in: What would someone you know really enjoy? What's something that's cool? What's something that I'm passionate about?

Think also about the techniques and tools you might use: What's something that's challenging? [Note: this is an especially great question for creative writing.] What's something that's almost inside my comfort zone but not quite? What's something that I can do to show off a little?

Take a lesson from Tina Fey and her book Bossypants (or better yet, take a lesson from the improv classes that you took--because everyone should take improv classes): at this stage, just write down the ideas, without judging them.

See? Ideas are cheap.

Friday, October 17, 2014

MakerSquare Day 37: Double your time projections (8/4)

Today we talked about some issues with our final projects. 

The first idea of which is we will be responsible for several final projects. Which is nice for people like me who (a) have many ideas* and (b) are interested in everything.

The second issue is that, damn, final projects start in a few days.

Third: We need at least one individual project, but our second could be a team project (as long as we have pretty strict separation of concerns, so that we can individually point to a project and say, "I did X on this project, and your company is interested in X, so...").

And fourth, when you scope our your project and think about how many hours it'll take--double that idea, because that's how long it'll take.

So, that's fun.

No, seriously, I can't wait to go through my list of ideas and find some that are (a) doable, (b) interesting, (c) involve interesting technologies, and (d) doable. And yes, "doable" is in that list twice. 

*Note: "many ideas" does not equal "many good ideas."

Thursday, October 16, 2014

MakerSquare Day 36: Zombies, Run! (8/3)

This is going to be a little departure for me in terms of content: instead of talking about our coding challenge (a Caesar Cipher, which was very fun), or what we learned in school (Rails, which is also amazing), I'm going to talk about an app I finally broke down and bought: Zombies, Run!

Here's the pitch: you start the app when you run, and you get messages about what's going on in the world around you--except the world around is overrun by zombies, with ruins and disaster. So you'll get notes about how you picked up supplies, but you'll also get notes about how zombies are chasing you and you have to speed up.

Pretty simple on that end (and we're ignoring the part where you rebuild the town), but effective. I mean, when I run (note: I've run three times in my life), at some point I'm liable to slow down. I could run with other people, but it's hard to find other people who (a) run around your same optimal pace and (b) are around to run when you want to. This way, I carry around a little bit of motivation with me, both for running more often (because the story is fun right now) and for pushing myself (when the zombies are chasing me).

So now, to bring it back to MakerSquare (and our upcoming final project), how do I use this example of a solid product to inspire me?

Or maybe I should just pretend that zombies are chasing me all the time and the only way I can escape is to code? Can I make Zombies, Code!

Wednesday, October 15, 2014

MakerSquare Day 35: Teamwork--without ping pong (8/2)

Last night, I tested a friend's quiz program (a really neat one). This afternoon, a friend helped me debug a use of the Soundcloud API. Earlier this evening, I ran a friend through a white-boarding exercise.

Besides bragging about all the friends I have--three!--I bring up these three stories just because I like them. OK, that's not entirely why. I like those anecdotes because in each I am occupying a different role, sometimes getting help, sometimes giving help (or, in the case of testing the quiz program, sometimes trying to break a friend's code in any way I can. And good news! I am very skilled at breaking code by doing the wrong thing, just like most end-users).

Also and more seriously: because in each, what we make with a little bit of teamwork is better than what we make alone.

Which brings me to the (slightly longer) anecdote I really want to tell you, about our morning coding challenge. (I could tell you about the bulk of today's work, working with Rails, but it's less anecdotable.

Today's coding challenge was to tell if a string was also a palindrome, disregarding non-letters and not paying attention to case. Pretty easy to get a rough version functioning: just downcase the string, use a regex to get rid of everything you don't want, make a copy that you reverse and compare them. Easy peasy--but not very nice.

(Aside: Nothing involving Regex is ever easy.)

One of my very algorithmically-minded peers had a different version, where you set an index at the beginning and at the end, and letter-by-letter, move to the middle of the word, checking that each letter is the same (after downcasing and skipping over non-letters). It was weird-looking, but super-efficient--except that he set a counter that incremented for each letter that matched and at the end of the loop, he checked that the counter was equal to half the string's length.

And suddenly I saw a way that we could skip all that and use a failure case to end the loop early, thus cutting out a few lines of code and stopping the function early if the string wasn't a palindrome. I was so excited by this that I almost ran to the board to ask our instructor if it would work. And here's a paraphrase:

"Together, this class created the most efficient version of this function."

Which I think is pretty neat, especially since we no longer have ping pong to bond us.

(Did I tell you that I miss ping pong?)

Tuesday, October 14, 2014

MakerSquare Day 34: The hard way first (8/1)

First, I've been bad about holding my blogging time to 15 minutes, so I'm back to setting an alarm. So let's see what I can tell you about the Monday of our eighth week in only 15 minutes. (It's so interesting to me how 15 minutes can seem like an eternity--if, say, you're waiting for a bus--or like no time at all if you're trying to get something done.)

(Speaking of buses, I decided not to wait for one last night, and on the walk home, I saw a fox running along the street, which means that I really made the right decision. Have I told you how much I like most animals in the Canidae form? I guess that doesn't really have much place in a coding blog. Unless I can somehow come up with a dog-related coding project...)

Many weeks ago, we learned how to use PostgreSQL to create and access database tables. Which meant that, on top of learning Ruby, we had big chunks of this other language in our code. Then we were introduced to Active Record, which is--ok, this gets a little jargony, but here goes--an ORM (object-relational mapping), or, in less-jargony form: Active Record is a way to write Ruby that will talk to your database in whatever language that database likes to talk.

I've said it before, but Active Record is kind of magical and cool (for at least some value of cool); and the topic was introduced to us with,
"Now that we made you learn PostgreSQL, we're going to teach you this easier way to do things, and you're going to hate us for making you do it the hard way first."
But I really didn't. It was hard to start with PSQL, but doing things the hard way first means that (a) you appreciate the magic of the easy way and (b) you understand what's going on under the hood.

I thought of that yesterday after our first day of Rails. Have you seen Rails? It's kind of amazing how Rails does so much for you. So after weeks of hand-producing files slowly and carefully, now I just type "rails new <Project_name>" and everything appears as if by magic. Which is great and amazing--but I'm still glad that we did it the hard way first, so I can understand what's happening.

Saturday, October 11, 2014

MakerSquare Day 33: Front- and Back-End (7/5)

When I started at MakerSquare, my sister asked if I could make her a website. At that point, we were deep into Ruby, which is not really (at all) what you would want to build a website in.

(Though, to complicate issues, there's lots of Ruby-ish qualities to tools that'll help you build a website, like Jekyll (for generating static websites) and Liquid (a template language that seems a little bit like code) and Sass/Scss (for styling your pages). So, yeah.)

But now, this week we spent two days playing around with HTML and CSS and...

...And I realized I never talked about the front-end/back-end division, which I've mentioned a few times. Is it clear what I mean when I say that? What if I said "full-stack"? (Don't worry, I won't say "full-stack," at least not in reference to my skill-set.)

The general division between front- and back-end is, uh, basically in the name. If you need an analogy, think of the front-end as the client-facing side of just about anything: the salesclerk helping a customer find the right size suit/dress is working front-end. The guy in the back, unloading pallets of clothes and organizing the employees-only room in back? He's doing back-end work.

Or, in honor of my librarian girlfriend teaching me about libraries: the librarian who helps you find a book and checks it out for you is only one small part of the library. In the back rooms, doing the back-end work, there are a lot of librarians doing the cataloguing and dealing with the rarer customer requests (like interlibrary loans).

In web development, that division of labor (or separation of concerns) comes out in the separation of back-end logic (how we store data and how we do a lot of work on that data) and front-end presentation (which is how the website is presented to the user and how it responds to that user). There's some overlap--even when I worked as a stockboy at a health-food store, I sometimes helped out customers find the right vitamins for their terrible ailments--but that's the general division between web developers.

So in a few weeks, after working on my sister's website, I'll probably be able to tell you if I like this far front-end work.

Friday, October 10, 2014

MakerSquare Day 32: Stump the Expert and Startup Crawl (7/4)

In his early work, George Carlin has a bit about how kids at his school would get to ask their priest really arcane questions, questions where they would add caveats and issues to try to stump the priest, questions like
"Father, what if you haven't done your Easter duty and it's the last day of Pentecost, and you're on a ship at sea and the chaplain goes into a coma, but you wanted to receive, but now it's Monday and it's too late--but then you cross the international date line..."
And there's a little bit of that when our HTML/CSS expert comes in. Which might be a good signal about how... mysterious HTML/CSS can seem. Like religion (oh boy, watch me step carefully here), there are some things about HTML/CSS that are relatively straightforward. Like: When you create a section (using a <div> tag), the div can be a block (and so take up the full width of the page) or be inline (and so only take up a certain amount of horizontal space) or be an inline-block (and so mix the two presentation-styles).

Actually, now that I think of it, block, inline, and inline-block aren't all that clear.

But there's a lot of info on those differences online and it all sort of makes sense. When you get to some other tags and options, this stuff gets arcane quickly. (Which might serve as a good tagline for MakerSquare: "Get Arcane--Quickly.") So when our HTML/CSS expert comes in, we often have a show-and-tell/stump-the-priest attitude.

"What if you want the text to be 3D and come out to the reader, but not too 3D? What if you want to make an entire section clickable as a link, without wrapping the whole section in a link tag? What if..."

Unlike religion (oh, careful, careful), once you see the answers, most of them don't turn out to be all that arcane. (Or, well, it's been a long time since I was in Hebrew school, but my memory of it is that all the stuff that seems arcane, really is arcane.) It's mostly a question of learning the right words and suddenly you can make 3D text that's actually behind a div container and make that container spin when hovered over.

This evening, MakerSquare--and some other offices--were taken over by the Startup Crawl part of Austin Startup Week, which involved a fair bit of parties and talking to people about their tech stacks. It was interesting to go from "how to present a website" to "how to present yourself as a human being, oh god, talk about something fun like George Carlin."

Overall, it was a good time and I did talk to a lot of interesting people at interesting companies who, though they didn't know it, were assigning me homework every time they talked about something I haven't yet mastered.

Thursday, October 9, 2014

MakerSquare Day 31: A Million Little Tiny Tricks: Trick one: Delegation (7/3)

Today was our last day of our current project, a single-page application that gave the reader a quiz. Simple enough to do (that is, not at all simple when we started), but then we had several extensions and expansions, like: allowing the viewer to create their own quiz. To do so, we learned all about localStorage, which is where we were storing information about the quiz.

Which brings me to something interesting that we discovered as a class (i.e., something the instructor wasn't quite clear on), which is that you can iterate over localStorage as if it were an array-like structure.

Which brings me to the real topic of this blog-post: there are a lot of high-level topics and concepts in learning programming, everything from abstract patterns (like MVC) to language foundations (objects, type-sensitivity, etc.).

But there's also a whole range of tiny details and little tricks that you pick up along the way, that even really smart and experienced instructors might not know. And I'd like to share some of them, as I pick them up.

Yes, finally, after 28 days, I have an idea for an on-going blog feature!

Today's trick isn't really a trick: it's a life-saving idea about JavaScript and event listeners. Beginning developers (cough, cough) often have a problem where they/we create an HTML button and add a JavaScript listener to the button--only that button is added after the event listener and so the event listener can't find the button.

So there's a nice jQuery fix where you set a listener to load after the page loads:
$(document).on('ready', function() {
...your listeners here...
 But you can also delegate the event listener to the document, like so:
$(document).on(...what event you want to listen to, ...what you want to trigger the event... , function( event ) {...}
That way, the event listener is delegated to the document, which will hand it off to whatever you want to trigger the event, and it will work whenever that event-triggering object is added to the document.

Wednesday, October 8, 2014

MakerSquare Day 30: Quiet room, loud room (7/2)

Instead of one big room like our Brazos office, the Congress office is, well, one big main room, but with a few smaller rooms coming off of it: we have our own kitchen, a little tv room area, and the Quiet Room.

I'm not sure it's actually capitalized like that, but as a long-time reader of horror, I like it with a hint of sinister. Though it's really not sinister; it used to be the tv room, where people would play Super Smash Bros. and other games from long ago.

But now it's the Quiet Room, where people can go to get away from the hubbub of the main room to get some work done.

I tried it out yesterday when we were continuing on our single-page-application project: a quiz purely written in JavaScript. It wasn't bad. (The room, I mean. My quiz page is also pretty nice, which brings up another issue we should talk about: front-end vs. back-end work.)

But the Quiet Room wasn't quite the productivity silver-bullet that it might sound like. Sure, I could get some reading done in there, but there were a couple of times where I wanted to talk to someone about what I was trying to do or see what they were trying to do.

I was reminded of (I'm always reminded of something) the title of a book about the culture of the Jewish shtetl that I read in college: Life Is With People. Except if I were writing a book about MakerSquare (and coding more generally), I'd title it Work is With People.

It's like what I learned about the culture of creative writing and really successful writers over the last few years: you may do some really great work by yourself, but what really makes it both possible and worthwhile is bringing your writing (fiction or code) to the group, either to get corrected or to show what you learned or just to share.

So maybe I'll leave the Quiet Room for the ghosts that surely inhabit it. I mean, a lot of Super Smash Bros. died in that room.

Tuesday, October 7, 2014

MakerSquare Day 29: First day on the senior side: so much to learn (7/1)

Today was the first day we spent on the senior side, which (as I said before) is both a philosophical shift (towards preparing for our final projects) and a physical shift (moving from our Brazos office to our Congress office).

Which might sound banal, but I'm a big believer in the effects of the built environment on people. So what effect will it have on us, I wonder, now that we've moved from the cod modernism of a big office building, with lots of glass and blank walls (and basement views), to the slightly warmer--but still windowless--office with the painted walls.

And on this day, I was struck with three thoughts.

  1. Biking to the office rather than walking is a lot faster. Probably an obvious observation, but one which was driven home to me since I only now have a bike here in Austin. (My girlfriend recently bought a really sweet hybrid road/mountain bike, but since she's not using it, she let me borrow it.)
  2. We know a fair bit of stuff already. Monday's task was to make a single-page application with a quiz, with a fair bit of wiggle room about what that quiz should be about or how it should be delivered. The goal was to think about MVC design pattern, where the Model, View, and Controller were all given their own design space. And there were lots of fiddly bits and some harder moments, but it all made sense and was doable. So it was striking to me how much trouble we would've had with this just a few days and weeks ago.
  3. There's still quite a bit that we need to learn. Which was less striking as a thought because it's a thought I've had constantly for the last few weeks. After finally really getting the MVC pattern (which I'd heard of before, when I was dabbling in iOS programming), I went to a meetup to hear about functional programming in Ruby. See? There's always more to learn.
Maybe's that's why I like this stuff so much.

Saturday, October 4, 2014

MakerSquare Day 28: Skills on the line (6/5)

Children play "Rock Paper Scissors" in jest, but web developers build "Rock Paper Scissors" apps in earnest. (To paraphrase Bion.)

It's been real interesting to go from some of our smaller, more focused projects--projects where we learned and employed one new technology or section of technology--to something like a full project. Because, even though "Rock Paper Scissors" is a pretty simple game, with a high requirement of two hands, as an app, there's a lot of little pieces.

You'll need HTML and CSS to display the page, with some sort of web app technology, like Sinatra, to host the server and pass info from your front-end to your back-end. Throw in a little Javascript and jQuery to make the site interactive, and you've already gone beyond the technology I had when I made my first website at Geocities. Then, on the back-end, you have Ruby handling the logic and ActiveRecord handling the database to keep track of how players are doing.

Also, at some point you have to grab some silly pictures of rocks, paper, and scissors; or come up with some weird angle to make your Rock-Paper-Scissors game stand-out. (My favorite theme so far is pirates.)

And you have to do all of that before the big, cohort-wide ping pong tournament on Friday. Because no matter how much your skills have improved in terms of HTML, CSS, Javascript, and Ruby, the real judge of a developing developer is ping pong.

Until next week, when we move into our new office. Then the only skills that matter will be coding skills.

And also Super Smash Bros. on the N64.

Friday, October 3, 2014

MakerSquare Day 27: Oh the places they'll go! (6/4)

If I haven't already mentioned this, MakerSquare currently has two classes going in Austin, known as C8 and C9, with C9 beginning halfway through C8's 12-week run. And this is the last time--at least for now--that Austin will be hosting two simultaneous cohorts.

Which is nice in some ways: I won't have to share my room at the DevHouse with anyone from C10; now we get all of the attention from all the teachers.

But it's bad in some ways. For instance, today we went over at lunchtime to see C8's final projects. And they were pretty gosh darn good. I mean, I was proud of our hackathon project, that we made in 36 hours; but these projects that the seniors did--some in weeks, some in days-- were really kind of great.

They also gave me a pretty good shot-in-the-arm about all the project ideas I have. Yes, I have lots of ideas for apps, but one lesson I learned in creative writing: ideas are cheap. Now, after seeing all the things that people who are only 6 weeks more advanced can do, I feel like, sure, ideas are cheap and implementation is expensive, but I can pay the bills.

Or rather: the C8 demo was really both inspiring and impressive, in that I can't quite pay those bills yet, but I feel myself getting closer.

And I'm very excited for my friends and peers in C8, who inspired the title of this post.

Thursday, October 2, 2014

MakerSquare Day 26: Little nifty bits of magic (6/3)

You don't often hear "magic" and "database" in the same sentence, except for those sentences that start out, like this one, noting how rarely you hear "magic" and "database" in the same sentence, except for those sentences...

I can never resist a recursion joke.

So "database" and "magic" don't often go together, except for today, when I came back to ActiveRecord and saw how it had all these nifty bits of magic.

Seriously: I can't think of a better word than magic--or nifty--to describe ActiveRecord.

Up till now, a lot of the database work I've done has been directly in postgreSQL, which I weirdly liked. About a week ago, we looked briefly at how ActiveRecord serves as a mediator between SQL-like language and Ruby. It looked interesting and, sure, helpful, but I didn't want to give up the control I had of talking directly to my PSQL database; and anyway, I didn't have any project that needed a database right then.

Fast forward to today, when I was implementing a Rock-Paper-Scissors game and needed a database, and, what's that?, my old notes on ActiveRecord. "Well, why not?" I said to myself.

If you've seen 2001, you'll know what it's like after that, with all the colored lights and the brain-expanding monolith. To be clear: there's something slightly sinister about the Monolith in 2001 and there's something slightly sinister in letting ActiveRecord mediate for you. But still, there are all sorts of--I'll say it again--nifty bits of magic that go into ActiveRecord. Like telling tables so easily what they hold and then, automatically, the entities for those tables know what they should hold too. Or the ease of telling a table to make sure that it has a certain bit of info with "validates." Or--

And so on. You see that none of this is ground-shaking, Level 9 spellcasting. But it's all useful and neat and easy to use. Perfect for a Rock-Paper-Scissors game.

Now I'm off to update my database to show that I've beaten a million people at RPS, because that's one of the simple pleasures of having server access.

Wednesday, October 1, 2014

MakerSquare Day 25: Shiny happy programmers (6/2)

I'm not on the job market right now, but I'd be lying if I said I didn't occasionally think about what the job market is like for developers. Or what it will be like in six weeks, when I am on the market.

And the market is even more on my mind on those days when we talk to career services; or when established developers--MakerSquare grads, mentors, or just allies--come to talk to us about what it's like for them out there in the real world.

The real world is rather disappointing when compared to the computer world, in that the real world has far fewer arrays. I hope it's not too forward of me to say this, but: I love arrays.

But the real world is not so disappointing in terms of careers and places of employment. For instance, today a group of front-end developers at RetailMeNot came to speak to MakerSquare at lunch and they were--what's the word? Happy. They seemed like they liked their jobs and their co-workers, which is a real shock for me to see. (In grad school, where a large chunk of my adult life post-college was spent, people by-and-large are not happy. Or not at my grad school, at least.) 

On top of that shocking expose of what it was like to work in this field (they have foozball tables!), I also had a nice one-on-one chat with the head of MakerSquare career services, discussing possible places I would like to end up and possible salaries. It was a little on the abstract side--nothing as concrete as "I will work for foozball table time"--but it was a good start and something I hope will pay off when I do go on the market.

Which, ahem, will be in six weeks now. In case any possible employers are reading. And have a foozball table that isn't being used enough.

Note: Although we did a bunch of coding today, from brain-waking morning coding challenges to logging users in to a website, I've tagged this as "Teambuilding" to memorialize the time we spent at the end of the day working through a bunch of visual puns and jokes. As a team.

Tuesday, September 30, 2014

MakerSquare Day 24: Time--important for traveling salesmen and sleepers (6/1)

This is the beginning of our sixth week, the last week before we move from the junior side to the senior side. Which is both a philosophical shift--from learning programming languages to planning our projects--and a real physical shift, since MakerSquare has two offices, one of which is the HQ for the younger cohort (when they have overlapping cohorts). Which means we have to get in as much ping pong time as we can.

And "time" is on my mind (yes it is), both because we spent part of today thinking about how fast/slow a recursive Fibonacci program would be (answer: much slower than an iterative version--unless you use cache-ing); and because I was up until 1am on Sunday night working out a working draft of my traveling salesman algorithm--the algorithm that beat me on Thursday.

It took a fair amount of time; and then, after I finished (closer to 1:30am) and had a chat with my night-owl housemate, I was a little too energized to fall asleep. Which is why I only had four hours of sleep on Sunday night and spent Monday in that low-sleep-dep fugue.

Still, as much trouble as I have building a traveling salesman algorithm, I love me some abstract data structures--like queues, stacks, and singly/doubly linked lists, which is what rounded out the day.

No, wait: what really rounded out the day was a meeting with my mentor where we discussed writing clear code, which gives me lots of ideas for making comments and clarifying my traveling salesman... tomorrow.

Saturday, September 27, 2014

MakerSquare Day 23: Hackathon Day Two: Getting (the Small) Stuff Done (5/5)

And... scene.

Or if you're not into improv and would rather think of web development as a school/testing environment: Pencils down, everyone.

Because today was the day when our time was up and we had to present our products to the class.

If you've never been in a hackathon situation, here's a key bit of advice I got from everyone: start small. As our friend/housemate/TA told us, when he was taking the class (because, oh yeah, he's also an alum of MakerSquare), at least half the students presented unfinished and unworking prototypes.

Which makes my class look like goddamn rockstars. Not only did everyone have a finished prototype (which seems like an oxymoron but is more an Irish bull), but every group obviously learned something through the process; and, more interesting, every group had some clear ideas about how to make things better.

And my group has some definite ideas about how to improve our web app, Eff Errands, our efficient errand organizing system. (It could also be used for efficient pub crawls, which is another statement that seems oxymoronic, but isn't really.)

Overall, it was a good 36 hours of working, thinking, experimenting, failing, trying new routes, and ultimately succeeding. (For a different POV--and some pictures of the finished(ish) prototype--see Kelsey's blog here.)

It also always interests me that a little bit of work can go a long way. Seriously: it takes about three lines of jQuery to make a list that will slide up or down if you click on it--and it makes people so happy to see that little list sliding around.

The lesson here, of course, is to use slideToggle all the time.

Friday, September 26, 2014

MakerSquare Day 22: Hackathon Day One: A Well-Laid Plan and the Joy of Blowing Things Up (5/4)

I'm right now 16+ hours into my first hackathon and stopping right now to tell you all about it would be a bit like stopping a movie halfway through and saying, "Well, how do you like it?"

The answer usually is "I don't know, but I think I like it. Let's see how it ends."

For those who don't know (hi, mom!), a hackathon is something like a mock production: in 36 hours (more-or-less), we're supposed to go from

  • idea to 
  • design to 
  • implementation to 
  • screaming into pillows to 
  • presenting the product
Usually, hackathons are done in teams, which gives people a nice taste of both taking an idea to a finished(ish) product and working together.

And I'm very thankful for my team. I've got permission to talk about our project before our unveiling Friday afternoon, so: we had four people helping to build our way-finder web app and each person had a pretty clear role, from our front-end UI/web designer, to our Google Maps API expert, to our floating troubleshooter, to our, well, me, who spent today working on the back-end algorithm for finding the best route from place to place.

Which brings me to the somewhat embarrassing part of the hackathon: my algorithm doesn't work. Now, this is both annoying (I like to finish things, I don't like being told I can't do something)*; and not all that big a deal, since Google Maps provides an algorithm for doing what we want it to do.

On the bright side (which I can find--thanks to some useful API), I did get my hands pretty dirty with some deep algorithm reading and a nice tour of some of Ruby that I hadn't played with before. Oh, hello (1.0/0.0) = Infinity!

*You now know the secret to getting me to do something: tell me I can't. Use that secret wisely.

Thursday, September 25, 2014

MakerSquare Day 21: Hackathon (almost)! (5/3)

Instructors, like everyone else, have catch-phrases. Now, it's possible that I was raised on old sitcoms, so I think everyone has catch-phrases, when in reality, only instructors do, but it comes to the same thing.

Instructors have catch-phrases.

And one catch-phrase that we heard several times in one day from our great Javascript instructor is that "The other students are our biggest resource."

And, as much as I like Google for looking for an answer, he's not wrong when he says that. Which is why I'm so excited about the Hackathon starting tomorrow. (Or, rather, starting today, by the time this is posted.)

A large part of today was dedicated to preparing for the Hackathon: coming up with ideas, dividing into teams, asking some questions of ourselves and our instructors (who, I'll admit, are also a pretty good resource).

And here's something else that happened today which may help demonstrate why I'm so excited for tomorrow. (Oh, and also: there will be breakfast tacos.) We started today with a coding challenge: given a list of words, find which words in the list are anagrams of each other; and return an array for each group of anagrams. Following the dictum "make it work," I wrote out several lines of code that were basically readable English. It wasn't an elegant or the fastest solution--it was merely the quickest to write out.

Then a peer/colleague presented her solution and it was this beautiful one line of code that worked because she found the Ruby method that was a perfect match for the task: group_by.

Now maybe in my younger days I would've been jealous to be outdone like that; but with the perspective of my thousands of years (or maybe it just feels that way), I can see that single line of code and just enjoy the elegance.

And also, now I know group_by.

So yeah, the other students are a pretty good resource.

Bring on the Hackathon!