Skip to content

Instantly share code, notes, and snippets.

Last active August 29, 2015 13:57
Show Gist options
  • Save CoryFoy/9441665 to your computer and use it in GitHub Desktop.
Save CoryFoy/9441665 to your computer and use it in GitHub Desktop.
require 'set'
GEM_FILE_TO_PROCESS = "Gemfile.lock"
def gem_list_finished?(line)
def non_gem_line?(line)
line.include?("GEM") ||
line.include?("remote:") ||
line.include?("specs:") ||
def gem_name_without_version(line)
line.split(' ').first
def get_files_in_gem(gem)
#gem contents returns the files
#as a line break delimited string
`gem contents #{gem}`.split
def line_count_for_file(file)
output = `wc -l #{file}`
#line count is the first column from
#the returned value
output.strip.split(' ').first.to_i
def log(message)
puts message
gemfile_list =
gems_to_process =
total_line_count = 0
gemfile_list.each_line do |gem_line|
gem_line = gem_line.strip
break if gem_list_finished?(gem_line)
next if non_gem_line?(gem_line)
log "TOTAL GTP: #{gems_to_process.count}"
gems_to_process.each do |gem|
log "Processing #{gem}"
contents = get_files_in_gem(gem)
gem_line_count = 0
contents.each do |file|
gem_line_count += line_count_for_file(file)
log " LOC: #{gem_line_count}"
total_line_count += gem_line_count
log "Total Lines: #{total_line_count}"
Copy link

jbrains commented Mar 9, 2014

I teach design through the metaphor of listening to the code. Signals from names are usually harder to understand than signals from duplication, and so when I find an example of the former, I like to highlight it. I find one here.

I see this pattern frequently: a purely structurally-named thing, often so named to avoid a naming collision, indicates some code worth extracting.

local... but local what? Local total (of lines), I guess. There doesn't seem to be a pithy, precise name for this, which hints that we've put it in a larger scope than appropriate. Here, it has a pithy, imprecise name. If I wanted to be cruel, I'd call it lazy. I've been that lazy. You've been that lazy. "It'll be fine."

So I rename local to something like line_count_for_this_gem, and then I notice total matches the same pattern and rename total to total_line_count. When I say "make names more precise", I mean something like this. Now the latent structure slaps me in the face: to avoid the verbose names and duplication, I extract a function for lines 20-28 computing line_count_for_this_gem. I call the function countLinesForGem. Now, within this scope, we can name things more pithily without losing precision. Alternatively, we can remove the newly-introduced duplication between the name of the new function and words in the more-precise names of these variables.

Inside the new function, I notice amount, which exhibits the same pattern. I extract a function for lines 23-27. Even better than renaming the resulting temporary variables, they can probably disappear. (That comes down to personal preference for me.)

Of course, none of this accounts for the choice of the name GFILE. That's just wrong.[1]

[1] I can't be entirely humorless; you shouldn't, either. That includes your reaction to this footnote.

Copy link

CoryFoy commented Mar 9, 2014

It should be noted that JB's post above was in response to version 2 of this Gist. The above version attempts to take into account better code principles, and I blogged about it at: Put Your Best Code Forward

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment