Lots of Web Stuff – And it’s All Going to be Tossed
I did it again today. I pushed myself to get a lot of stuff done today for a big, important demo (again), and along the way a few people interrupted me to ask me to look at a few things. Had I been smarter… had I been wiser… I'd have said "I'm sorry, I'm on this push for the demo, how about I get to it on Monday?" But I didn't.
What I did was to push myself to the point that I was very upset with the things I was working on. Oh, it didn't start out that way. It started out with me thinking that I could easily track down this problem that one of the data science guys pointed out. It was in my code for grouping the merchants where I wanted to be smart and clever. I should have known.
First, I wasn't accounting for the case where two groups of overlapping merchants are built and then a single merchant bridges both groups. I messed up. So I needed to go back and fix a few things. First off, I didn't have a general overlapping service method. So I took the old one and expanded it:
# this method returns true if ANY service is shared between the two # merchants. ANY. def self.services_overlap?(ying, yang) if ying.is_a?(Array) # explode the calls for an array in the first position ying.each do |d| return true if services_overlap?(d, yang) end return false elsif yang.is_a?(Array) # explode the calls for an array in the second position yang.each do |d| return true if services_overlap?(ying, d) end return false end # this is the simple call for a 1:1 check !(get_services(ying) & get_services(yang)).empty? end
Basically, I just allowed arrays to be passed in, and where necessary, I exploded them to allow the basic logic to be applied to the individual merchants. It's not hard, but at this point, I didn't need to worry about what I was passing in to check for an overlap.
The next thing was to completely redo the group_by_service() method as it was far too complex, and it wasn't even working. I didn't like the fact that it was doing a lot of extra checks, etc. but that seemed to be the Ruby Way. Poo. I changed it into a simple single-pass loop that's far simpler and far faster:
def self.group_by_service(otcs) # start with the array of groups that we'll be returning to the caller. groups = [] otcs.each do |d| added = [] # add the OTC to all groups that it has some overlap with groups.each_with_index do |g, i| if services_overlap?(d, g) g << d added << i end end # if we added it to more than one group, then consolidate those groups if added.size > 1 added[1..-1].each do |i| groups[added[0]].concat(groups[i][0..-2]) groups[i] = nil end groups.compact! end # if he hadn't been added to anything, make a new group for him groups << [d] if added.empty? end groups end
The ideas here are a lot clearer - add a new guy in to all the group he'd match, then look for multiple matches. If there are, then simply and cleanly consolidate the groups, and continue. My co-worker in Palo Alto liked this code a lot more as well. I do too. It's ruby, it's just not incomprehensible ruby. And it's right.
But in the midst of this, I'm trying to get more web stuff done for another interruption for the demo, and it's nothing I'm happy with. It's all very lame. I don't like the interface I have to CouchDB, I don't have a lot of time, and it's making me very cranky.
I've run into this before, and it's not the first time I've not been able to say "No", and it's cost me something I didn't want to pay. I know I'm no great graphics designer. I know I can make things that work, but they aren't going to be "Wow!" with anyone but someone looking just at the functionality. That's just not in my DNA. And it is exceptionally frustrating to be in a situation where I'm forced to do this work.
I know what is good. I can appreciate it. But I can't generate it. And to be forced to do it is hard. Because I know they are going to throw it all away. Any half-decent designer will look at what I've done and say "Nice, but let's take out the data collecting and put it in a nice design" - as they should.
So I've got to work harder at keeping my cool.
I've got to say "No" more often.
Or I just won't last.