Are We Teaching the Best Things?
I'm in Denver right now, mostly to see family. Being the geek that I am though, you know I snuck a little time for the local Rubyists. One of those Rubyists that I was lucky enough chat with is Katrina Owen.
I always love getting a chance to talk with Katrina. She's so thoughtful that she raises the level of discourse and makes me feel smarter. Plus, it turns out that Katrina and I have been thinking about similar things lately.
For my part, I've been thinking about the various students that I've taught to program over the years. I have taught many and because they all learned from me, they learned roughly the same way. What's interesting to me is how different the results have been from that technique. In some cases my students were all set after our lessons and they just began coding up a storm. Other students didn't seem to feel they were ready yet though. They had more of a "Now what do I do?" attitude at this stage.
Katrina raised a similar point from her time teaching in a developer school. When they would get to teaching language basics, they would show several constructs and how they are used. This is similar to how I teach. Just as I have observed, this works for some students. They can just take what they know and run from here. But they also found other students felt a little lost at this point.
A Library in One Day
I was super inspired by Darius Kazemi's recent blog post on small projects, so I've been looking for ways to speed up my process.
Today, I tried an experiment: develop a library in one day. I wanted to go from an empty repository to a published gem that I could start using.
Obviously, I had to select a pretty simple idea to use. I wouldn't have time to do a huge project.
I think this may be the killer feature of this technique.
On one hand, you could argue that what I built may not be very library worthy. It's around 50 lines of code. It has ten specs and they really cover what it does. This isn't a complex beast and you could pretty easily hand roll a solution to replace it.
But in some ways that's the best part. I've dropped a 50 line pattern that I like down to a one line
Gemfileinclude. I'm making it even easier for myself to get some mileage out of experimenting with this code. I can mix and match this new library with other small tools to build up the ecosystem that I want for a project. Plus, if it turns out to be something I regret, it's not like I'm tied down to a huge dependency when I go to rip it out. This thinking actually has me wanting to keep this library minimal, at least for now.
Proof of Life
As many of you noticed, and some of you regularly messaged me about, this blog has been offline for quite some time. There are many reasons for this: I was rewriting the software this blog runs on, the host that served it closed their doors, I had to take an extended break in working on it for multiple reasons, and, when I got back to it, my half-complete rewrite had enough bit rot that I decided to start fresh. The good news is that all of that mess has finally passed. As you can see, that means this blog is back is business.
If you are a long time reader and you have a good memory, you'll notice that I changed the name of my blog. That's because the old name was a not-so-clever play on my name that was later appropriated for a rather different collection of writing. I think that's worth resetting the Google credit counter to get away from.
Oh and there have been a few upgrades…
All of my posts are back. Some content is a bit dated and I've tried to add clarifying notes where they were needed, but I was pleasantly surprised to see that much of it is still useful today. I believe my coverage of Character Encodings is what readers missed the most and it's fully restored.
Decorators Verses the Mix-in
It is a neat time to be involved in the Ruby community, if you ask me. A large portion of us are currently studying the techniques for doing good object oriented development. We are looking at the ideas that have come before and trying to decide the best ways to apply those ideas to our favorite language. This leads to blog posts, forum threads, and conference talks about what we are learning. No matter what, we all gain from explorations like this. Everybody wins as our collective knowledge grows. We all deserve gold stars.
So far, there's one point pretty much everyone agrees on: composition should typically be preferred to inheritance. The trickier part of that discussion though is deciding what composition looks like in Ruby. Generally you see Rubyists comparing the merits of decorators and mix-ins. [Note: the comments correctly pointed out that this was a bad use of the word "composition" on my part, to describe mix-ins.] There's a very representative thread on the excellent Objects on Rails mailing list.
I love playing with Ruby's
Hash. I think it has a neat API and experimenting with it can actually help you understand how to write good Ruby. Let's dig into this idea to see what I mean.
The nil Problem
In Destroy All Software #9 Gary chooses to show an example in Python because, unlike Ruby's
Hash, it will raise an error for a non-existent key. Ruby just returns
nil, he explains.
What Gary said isn't really true, but I'm guessing he just didn't know that at the time. He was in the process of switching to Ruby from Python and I'm guessing he just didn't have a deep enough understanding of Ruby's
Hashyet. I bet he does know how it works now.
But assume he was right. What's he saying and why does it matter? Consider some code like this:
class SearchesController < ApplicationController def show terms = params[:terms] SomeModel.search(terms) # ... end end
This is what Gary doesn't like, and rightfully so. Because I indexed into
paramshere with the
()method, I will indeed get a
:termskey wasn't in
Single Method Classes
[Update: I've changed my mind about some of the following due to this excellent counter argument.]
In the words of Dennis Miller, "I don't want to get off on a rant here, but…"
There's something that drives me crazy and I see it in so much Ruby code. I see it in the documentation for our key projects; I see Rubyists of all skill levels doing it; it's just everywhere.
Let's talk about when the use of a
Classis and is not appropriate.
The Chained new()
Here's an example of one form of code that bugs me:
class Adder def add(n) 40 + n end end p Adder.new.add(2)
The problem here is that a
Classhas been used, probably because as Rubyists that's always our default choice, but it's the wrong fit for this code. A
Classis for state and behavior. The example above is just using behavior. No state is maintained.
A handy tip for sniffing out this problem is watching for a call to
new()in the middle of method chaining as we have here. If you always use a
Classlike that, it's not really a
Class. Put another way, if an instance never gets assigned to a variable, something has likely gone wrong with the design.
Let's Patch Rails
In celebration of my first ever trip to RailsConf next week I wanted to be a good open source citizen and contribute a patch.
I'm giving a presentation at the conference on various random features that the framework provides. I selected features from many places like blog posts, books, and some that I just remembered from years of working with the software.
One of the features I decided to show was an old feature that I never see anyone use. It turns out that there's a good reason for that. When I tried it on a modern Rails, it didn't work anymore. Rails has undergone some changes under the hood and this feature was likely removed in that process. I figured out a workaround so I could still show it in my presentation, but it would be nice if I contributed the fix back to Rails so others could use it.
In this article, I will walk through the entire process of doing that.
ERb has always had an under appreciated syntax tweak. Everyone knows you can write code like this:
Riding the Testrocket
I say it a lot, but programming is about ideas. More specifically, it's about not running out of ideas.
Along these lines, I read the results of an interesting study recently. It was a study about how we think and solve problems. When I was in school, the belief was that we needed to cram our brain full of facts. We were pushed to memorize, memorize, memorize.
The more modern view of learning is that facts don't matter as much. Nowadays we just try to teach children how to think. The assumption is that they can find the facts they need, because information is so universally available, and their thinking skills will allow them to work their way to other bits of knowledge.
The study looked at people taught using both of these techniques and found some surprising results: us memorizers can often out think the thinkers. A leading theory about why that's the case is that the memorizers have more of a foundation to build their ideas off of. Thinkers may be starting closer to scratch each time. If so, they have further to go to get to the needed solution. Memorizers, on the other hand, may already have a lot of knowledge that puts them closer to the solution before they even need to start thinking.
A Stylish Critique
Before getting started, I feel compelled to point out that my dictionary defines a critique as "a detailed analysis and assessment of something." It seems like we often assume the worst of that word, but that's not how I intend it here.
The Ruby community seems to be talking about style guides lately. So let's talk about them.
The fact is that you will have many choices if you go looking for style guides for our favorite language. You can pick from:
- The old stuff
- Google's way
- GitHub's popular guide
- Guides from respected Rubyists, like Dan Kubb
- One of the many forks of the popular guides on GitHub
- And many more
It's obvious that Rubyists care about this topic. Let's see what's out there and consider what really is and is not useful from these guides.
What is a style guide really, and why do we even have them?
Defining style guides is surprisingly tough. I suspect they started out as formatting rules for code, but they have evolved pretty far beyond that now.
Most guides include general conventions that the author feels are important when writing the language in question. This can go all the way down to how to use certain constructs, opinions on what the author considers idiomatic, and syntax to outright avoid.
Learn to Love Mix-ins
The road to mastering Ruby is paved with understanding some key Ruby concepts. Mix-ins are one of those concepts. I'm sure everyone reading this knows the mechanics of how mix-ins work, but it pays to spend some time really thinking about all that mix-ins imply. Let's do just that.
Adding a Type
One of the primary reasons that Ruby needs mix-ins is that it does not support multiple inheritance. That leaves mix-ins as our only option for modeling hybrid objects. It's the way Ruby programmers can add another type.
That's a good way to think about it too: adding a type.
Take pagination, for example. Pagination methods are usually defined to return an object like this:
class PaginatedCollection < Array # ... paginated helpers defined here ... end
That's never really felt right to me though.
First, inheriting from Ruby's core classes can come back to bite you in some scenarios. The reason is that Ruby makes some performance tradeoffs to keep the core classes fast, but those tradeoffs mean that those classes don't always perfectly follow Ruby's rules.