FeedAgg.com Logo
Your Account | Sign In | Sign Up

Add Feed | Search | Home | Help | Contact | Blog

Feed: My Secret Life as a Spaghetti Coder - AggScore: 68.2



Summary: My Secret Life as a Spaghetti Coder


Posts about Ruby, Java, Coldfusion, OOAD, TDD, DSLs, and more (some not TLAs!)...

Future Companies


MichaelBleigh'stweetsaying'Inthefuturetheonlylargecompanieswillbethosethathelpfacilitatethesaleandpurchaseofgoodsfromsmallvendorstoindividuals.' My take at this concept was too long for twitter, and I was too lazy to pare it down: In the future, the only companies that sell physical goods* will be the ones that figure out how to mine atoms from raw materials which can be used as "ink" in 3d printers which people use to print their own products from (probably pirated) plans they found on the internet. * This excludes non-mass-produced art Thoughts?
Comments?
Date Published: Feb 08, 2012 - 5:51 am



Rethinking Routing in Rails


You know when you see code like this:
class CompulsionsController < ApplicationController
    # ... standard actions above here
    def update
      if params[:obsessions].include?(ObsessionsTypes[:murdering_small_animals])
        handle_sociopathic_obsessions
        redirect_to socio_path and return
      elsif params[:obsessions]
        handle_normal_obsessions
        redirect_to standard_obsessions_path and return
      end
     
      # normal update for compulsions
      @compulsion = Compulsions.find(params[:id])
     
      if(@compulsion.update_attributes(params[:compulsion]))
      # ... remainder of the standard actions below here
  end
and the phrase "WTF were they thinking?" runs through your mind? I have a theory about that little "pass a flag in the url to skip over the real action and perform a different one" trick I see so often (and have been guilty of using myself). It's because you've got this omniscient file that knows everything about where to route requests that's not part of your editing routine, so finding and opening it breaks your train of thought. It's a pain to open routes.rb when you suddenly realize you need a new route. That got me thinking: Should controllers route themselves? Would it make more sense for a controller to tell the router how each of it's actions should be reached? In the second edition of Code Complete (that's an affiliate link), Steve McConnell writes about using the Principle of Proximity (page 352) as a way to think about organizing code.
Keep related actions together.
From that point of view, it certainly would be easier to follow along when you're questioning "how do I get to this action?" Further, I think it would help solve the "pass a flag to an action to perform a different one" problem I illustrated in the code snippet above. It was on my mind over the weekend, so I put together this little experiment to see what controllers routing themselves in Rails would look like. In that repository is a one-controller Rails project which specifies routes to itself using a gem you'll find in vendor/gems/route. One major drawback to doing routing in this style has to do with nested routes: should a controller that's part of a nested route know who it's parents are? Should a higher-in-the-nest controller know about its child routes? And if you choose one or the other, how would you specify it? What if there are conflicting routes -- who wins out? It leads to a lot of questions for which I have no immediate answers. Anyway, what do you think? Would this help solve the problem of recycled routes? Is that even a problem? What are the drawbacks of such an approach? Do you see any merits?
Comments?
Date Published: Feb 01, 2012 - 4:44 am



APIs have the signup process backwards


Most online developer API services that I've used are set up as if the customer is also the software developer. That should change. As the software developer, I don't want to be the owner of my customer's accounts, and I don't want to worry about trying to figure out how to transfer ownership (if your service allows it, that is). Because of that, theres a lot of waste that goes on: wastes of my time, which wastes my customer's or my company's money. I'm saying "customer" here, but you might substitute that with "the person who really needs / cares about the account," because that person, in my estimation, is rarely the software developer. Unless I'm developing an app for myself, I only care about that API because someone else needs me to. And even when I'm developing for myself, I hope it gets to a point where I need to hire someone to care about it on my behalf, so I can focus on more important things. The typical signup process for me goes like this: TypicalAPIsignupprocess,describedinlistbelow.
  1. Me: If I already have an account, sign out.
  2. Me: Sign up for the service. Find what I need to integrate with the API. Note the steps I perform.
  3. Customer: Signs up for the service, with me providing the steps they'll need to take.
  4. Me: Ask my customer to give me the info I need, or grant me access if that option is available.
  5. Customer: "I can't figure it out, here's my login info, find it please."
  6. Me: I find the info, and tell the customer to reset their password. I doubt they ever do.
You're offering the service, yet there's no "you" in that process. Here's the process I'd like to see: AbetterAPIsignupprocess,describedinlistbelow.
  1. You: Tell me I can easily transfer the account (or project or access keys) before I bother to sign up
  2. Me: Sign up for an account for myself.
  3. Me: Get everything working.
  4. Me and You: If I know my customer already has an account, provide a place for me to enter my customer's email address. If you offer more than one thing I'll need access to, let me indicate what I need for this project.
    • You: Send detailed instructions of to grant access to my needs.
  5. You: If my customer does not have an account, you send them detailed instructions for how to sign up and what they'll need to know to get value from your service.
    • Customer: signs up for their account, indicating they are actually working with me.
  6. You: Hook up our accounts, with me transferring ownership of that "project" to my customer.
There's a lot less of me and my customer in that process, and a lot more of you. It's certainly more complex, but it's simpler for the people who matter: your users. Remember, the software developer is often the one who makes recommendations as to which products to use. Make it easier for me, and I'll be more likely to choose your service over a competing one. post scriptum side note: I used Lucid Chart to do the flow charts. I really like it, but given how rarely I've wanted to diagram online, I don't see myself becoming a paid subscriber. What do you use?
Comments?
Date Published: Jan 27, 2012 - 5:01 am


Three passive-aggressive ways to feel like you're getting back at typecasers


Myvocabularyisfailingmerightnow.Whatdoyoucallitwhenapieceofcodechecksthetypeofanobjectbeforedoingsomethingtoit? Type Casing is the act of using case statements in a program to determine what to do with an object based on what type of object it is. It's an OO fail, often hoping to implement Multiple Dispatch. (See also Case Statements Considered Harmful) Here are three passive-aggressive ways to feel like you're getting back at typecasers. The first tactic turns your object into an everything, so it's whatever the typecaser was looking for. I've called it OmniObject.
module OmniObject
  def is_a?(*)
    true
  end

  def kind_of?(*)
    true
  end
 
  def nil?
    true
  end
end

foo = "hello, world!"
foo.extend OmniObject
puts "Is foo a Fixnum? #{foo.is_a?(Fixnum) ? 'yes' : 'no'}"
puts "Is foo a Kernel? #{foo.is_a?(Kernel) ? 'yes' : 'no'}"
puts "Is foo a NilClass? #{foo.kind_of?(NilClass) ? 'yes' : 'no'}"
puts "foo.nil? => #{foo.nil?}"
The next one makes your object unable to decide what it is, turning it into a FickleTeenager. If he has to check more than once, the typecaser is going to have a tough time with a kid who can't make up his mind.
module FickleTeenager
  def is_a?(*)
    sorta
  end

  def kind_of?(*)
    sorta
  end
 
  def nil?
    sorta
  end
 
  def sorta
    truish
  end

  def truish
    rand <</span> 0.5
  end
end

foo = "hello, world!"
foo.extend FickleTeenager
3.times{ puts "Is foo a String? #{foo.kind_of?(String) ? 'yes' : 'no'}"}
Finally, we have the AntisocialPrivacyAdvocate. When the typecaser asks him what he is, he tells them like it is: It's none of your damn business!
class WhatBusinessOfItIsYoursError <</span> StandardError; end;
module AntisocialPrivacyAdvocate
  def is_a?(*)
    raise  WhatBusinessOfItIsYoursError
  end

  def kind_of?(*)
    is_a?
  end
 
  def nil?
    is_a?(NilClass)
  end
end

foo = "hello, world!"
foo.extend AntisocialPrivacyAdvocate
result = foo.kind_of?(String) rescue "#{$!} OMG, How Rude!"
puts result
Comments?
Date Published: Dec 21, 2011 - 7:49 am




I'm sorry I didn't give you a chance, #each_cons


With a name like each_cons, I thought you were going to iterate through all the permutations of how I could construct a list you operated upon. For example, I thought
[1,2,3,4].each_cons do |x| # I did not notice the required argument
  puts x.inspect
end
 
would output:
[[1,2,3,4], []] [[1,2,3], [4]] [[1,2], [3,4]] [[1], [2,3,4]] [[], [1,2,3,4]]
So when I needed to find the local maxima in an image projection to algorithmically find the staves in sheet music, I found myself wanting a C-style for loop. I didn't know you'd provide me with a wonderful sliding window!
[1,2,3,4].each_cons(2) do |x|
  puts x.inspect
end
[1, 2] [2, 3] [3, 4]
From now on, I'll turn to you when I need that functionality. Thanks for waiting on me, each_cons. Not everyone would be as patient as you. Warm Regards, Sam PS: In case you're interested, the "cons" in "each_cons" is short for "consecutive," not "construct," as Matz informed me: Matzsays'Iamnottheonewhocomeupwiththename,butIsupposeconsistheshortformofconsecutive.'
Comments?
Date Published: Oct 24, 2011 - 8:45 am


Algorithmically recognizing the staff in sheet music


It's a small step, but emcee-3PO can now identify the staves in an image of sheet music for my single test case of "My Darling Clementine." I need to include hundreds more test cases, and I plan to when I implement code to make the tests mark the sheet music with what emcee3po detected so I can visually inspect the accuracy. Ichiro Fujinaga's "Optical Music Recognition using Projections" (PDF) explains the process in detail, but it turns out to be relatively simple. To locate the staves:
  1. Do a y-projection on the image. A projection just reduces the number of dimensions in an image. In this case, we just take the number of dark-colored pixels in a row of the image. It's similar in theory to 3D projection, but instead of projecting three dimensions onto a plane, we're projecting a plane onto a line. I used a threshold of 50% to determine if a pixel was dark enough to include in the projection. So, if R+G+B < (FF+FF+FF) / 2, I count the pixel as dark.
  2. Find the local maxima. We want to find the places where the number of dark pixels in a row is highest - those will indicate the horizontal lines on the staff. To do that, we find all the places where the number of pixels stops growing and starts getting smaller -- or where the slope changes from positive to negative. To ignore noise, we set a threshold as Fujinaga suggests at the average of each row, so we don't include anything less than that in our collection of local maxima.
  3. Find the tightest groups of 5. We want to find all the places where 5 local maxima are the smallest distance apart, which should indicate the 5 lines in a staff. This part is accomplished by examining each 5-element window in the array of local maxima, and finding the one with the smallest distance between its points. Then you can remove all the windows that include any of those points, and continue until there are no more windows.
  4. Expand those indexes to collect the places where the notes fall outside the staff lines. I don't remember Fujinaga mentioning this in the paper I linked to above, but I'm thinking it must be in there. Essentially, since the local maxima get us only what's in between the 5 lines of the staff, we need to expand it a bit so we can get the notes that don't fall directly between the 5 lines. Right now, I've used 1/4 of the average of the rows in the projection, but I think it will need to be an even smaller threshold because I'm still not reliably getting all of the notes.
Up next: reading the notes on the staves. That's going to be cool.
Comments?
Date Published: Oct 17, 2011 - 3:20 pm


plupload-rails3 available as gem; works on 3.1


plupload-rails3 is now available as a gem, and it now works on Rails 3.1. Automated tests are still virtually non-existent, which was a result of me not having a good idea for a strategy on how to test it in any useful manner. But after briefly bouncing ideas off of Jesse Wolgamott last night at the HRUG meeting, I think that will improve. If you have an issue or improvement, don't be afraid to let me know. PS: I'd like to give a little thank you to David Radcliffe, who prompted me to make these changes.
Comments?
Date Published: Oct 12, 2011 - 1:58 pm


How to save your ass when tech support tells you the best way to solve your problem is to start over with a new server


If you follow me on twitter, you already know I ran into some trouble compiling Ruby and OpenSSL the other day. Calling it "Some Trouble" might be a bit of an understatement. The next morning, I likened it to this title bout: Macvs.Cthulhu Not only was Ruby and OpenSSL giving me trouble, in my quest to get it working, I totally messed up everything that depended on OpenSSL. Email with TLS? Gone. SSH? Yep, gone as well. Tech support's first recommendation was to requisition a new server. Howoftenis'getanewserver'the1sttechsupporttroubleshootingtactic?Surelytheyshouldaskifitwaspluggedinbeforewegotthere Of course I wasn't going to accept that for an answer -- I'm the guy who, when someone tells me something is impossible, I cannot help but find a way to do it. It turned out that all I had done was mess up the configuration of where dynamically linked code looks for the shared libraries it's supposed to use. You can avoid that:
  • Don't mess with the LD_LIBRARY_PATH environment variable in a way that makes it persist longer or outside the scope of your compilation. For example, export LD_LIBRARY_PATH=/path/to/non_standard_lib would be a bad line all on it's own. It would be worse to stick it in your .bash_profile. Just run it on the same line where you do you configuring or compilation, and don't let it persist outside of that.
  • If there is a setting like the crle command on Solaris, make sure you read the man pages. For example, there's no way to simply add a library path -- you need to include the default ones yourself (if you still wish to use the default paths). So make sure you write them down correctly. In the end, I didn't write them down correctly, so all that was needed to get the system back to working the way it was, was to delete the ld.config file (which sets the system back to default).
What other ways can you mess it up? (Let me know in the comments!) Anyway, along this journey I got to use ldd, the command line tool I've always wanted on Mac when I had problems with gems being unable to compile their native extensions. For the Mac, you can use otool. Basically, they tell you which libraries a compiled piece of code is dependent on, and where it is looking for those libraries on disk. In the case of ldd you can use the -r option ldd -r /path/to/binary which will let you know what symbols can't be found, which was helpful in diagnosing some of my issue. I just wanted to let you know about these useful tools in case you were unaware. Being able to check the dependencies got me out of a tight spot, so maybe it will help you in the future as well.
Comments?
Date Published: Sep 09, 2011 - 1:43 pm


Dealing With Embarrassing Breaking Changes


Frequent changes and deprecations to technology you rely upon cause dependencies to break if you want to upgrade. In many cases, you'll find yourself hacking through someone else's code to try to fix it, because a new version has yet to be release (and probably never will). That can be a chore. I get embarrassed when something I've recommended falls prey to this cycle. Backwards compatibility is one way to deal with the issue, but in the Rails world, few seem worried about it. It doesn't bother me that code and interface quality is a high priority, but it does cause extra work. There's a trick you can use to help isolate the pain, decrease the work involved in keeping your app up to date, and improve your code in general. You've probably heard of it, but you might not be using it to help you out in this area: encapsulation. What I'm about to describe talks heavily about Ruby on Rails, but that's only because it was the focus of what got me thinking about this. I think it really applies in general.

Problem

Rails changes frequently. Some people think it changes too frequently. I'll leave it for you to decide whether or not that's the case. One consequence of change is that plugins and gems designed to work with Rails break. Perhaps as a result of frequent changes (in Rails or just the whims of the community about which project in a similar area does the job best), the authors of those packages become disillusioned and abandon the project. They could just be lacking time, of course. Now you get to fix their code (which doesn't have to be a bad thing, if you contribute it back and someone else is sparred the trouble), use a new project that does the same thing, roll your own, or sit on an old version of Rails that time forgot, and everyone else forgot how to use. Don't you get at least a little embarrassed that you have to recommend large changes to your customer or product owner or manager as a result of upgrading to the latest version of a technology you recommended using? It reminds me of a quote from Harry Browne I heard as part of his year 2000 United States Presidential election campaign:
Government is good at only one thing. It knows how to break your legs, hand you a crutch, and say, "See if it weren't for the government, you couldn't walk."
Ageekwhoisabully I'm likening programmers to the government of that quote, except we don't pretend to give the crutch away. We tell them "you can't walk without our crutch, so pay up." We sell people on a technology which they build their business around, and then tell them they have to choose between keeping a substandard version of it, or spending a lot of money to upgrade all the components. (Understand that I'm talking about how it feels overall as a result of what happens in the community of programmers, not a particular instance of particular decisions by any particular well-defined group of programmers.) I just got done migrating a Rails 2.3 app to Rails 3.1 that was heavily dependent on several plugins and gems. After writing a ton of missing tests, I made the switch and ran them. As expected, there were loads of errors. More than half of them were due to the application's own code, but those failures were fixed with very little effort. By far the most excruciating and time consuming task (even longer than writing all of the tests) was spent getting the plugins to work (or in some cases, using new plugins and changing the application to use them instead). I acknowledge that I'm doing something wrong, because surely not everyone has this problem. So tell me, how can I improve my experience?

A Solution?

Something I'd like to see more of in this area is to encapsulate your plugin usage. Rather than include NoneSuch, why don't you take the time to wrap it in your own code? In doing so, I see a couple of benefits:
  • You document which features you're using by only writing methods for those in use. That means you have something specific to test against in your app, and something specific to run those tests agains when you trade one dependency for another. It also means you know exactly what you need to implement when you swap dependencies.
  • You ensure a consistent interface for your app to use, as opposed to having to change it when you swap out which plugin you're using. Also, all your changes to that interface are localized, instead of spread throughout your source code.
That means you can change one external dependency for another with greater ease, which means you'll be a lot less likely to get off in the weeds trying to make something fundamentally unworkable work. Thoughts?
Comments?
Date Published: Sep 02, 2011 - 2:18 pm


Pipe music through a Markov Model to generate new, similar music


emcee-3PO takes a text file of music, runs it through a Markov Model, and generates new music to be played with Archaeopteryx. It's an idea I've had for a while, which _why day gave me a good excuse to start. There's not much there yet -- the first sentence above tells you exactly what it does -- but I hope to add some features to it as time allows:
  • Read from sheet music
  • Use different instruments instead of simply playing the notes as written / make it symphonic
  • Choose probabilities in some smart way to provide to Arkx (right now it's just 100% play this note)
  • Mixing multiple songs
I just thought it'd be a fun exercise, but I bet there's some really cool practical stuff this could turn into. Feel free to watch the repository if you're interested in seeing this develop. More importantly, and use your imagination here: Do you have any thoughts about what something like this could do?
Comments?
Date Published: Aug 19, 2011 - 4:46 pm


Ruby random numbers


Update: Ruby 1.9.3 adds the ability to use ranges as arguments to rand, which produces more obvious code. So if you're using it, instead of using "magic offsets" like I did in the original post (as Joni Orponen mentions in the comments below), it would be better to use rand(1..6) to simulate a die roll. So to summarize: if you need a percentage between 0 and 1, just call rand. If you need an integer between 0 and x (not including x), you can still call rand(x). Finally, if you need a number in a specific range, just call rand(x..y) where x is the lower bound of the range, and y is the higher end. (And recall that if you want a non-inclusive range, you can use 3 periods, like rand(1...100) to get numbers from 1 to 99. Although if you're typing the number out, it's certainly better to use 1..99, if you had used a variable in the higher part of the range, the 3rd period is preferable to 1..(x-1), in my opinion.) The original post follows: Another quick note today... I surprisingly have yet to need a random number in Ruby up to this point (or forgot if I did), so I went through a little hassle trying to find out how. Turns out, you can simply use rand(int). So, if you needed a random integer to simulate a roll of a six-sided die, you'd use: 1 + rand(6). A roll in craps could be simulated with 2 + rand(6) + rand(6). Finally, if you just need a random float, just call rand with no arguments. After that, you can modify the range as you normally would in anything else (i.e., using addition and multiplication). I guess I used some crappy search terms, because I couldn't find this via google, and I didn't see it skimming the usual suspects in the Ruby docs.
Comments?
Date Published: Feb 15, 2012 - 4:58 am


 
Visitor Rating: 7 (1) (Rate)

Story Clicks: 118

Feed Views: 410

Lenses (Add|?)

Comments (Log in to add)

Feed Details
Date Added: 01/19/2009
Date Approved: 01/19/2009
By: Anonymous
Search FeedAgg.com




3600 mp1537 serv 0.5854 seconds to generate.