Tuesday, June 26, 2012

Nest of inequity and despair

not realy


Today's instalment covers a few tricks I've encountered while working on Wami this last week:

Bootstrap autocomplete

Bootstrap has a JS plugin called typeahead, which is crap. Some guy tried to extend  it and his was crap also.
I used to use jQuery's autocomplete, but that was crap in Bootstrap. Until this guy re-styled it to work. That's the shit.

Simple_form

Absolutely rocks, use it! waaaay simple

Am I the only guy who thinks of 
when I read: 

plataformatec


...moving along...

Nested_form

Also very usefull, if only to get the link_to_add and link_to_remove helpers. You can read more here.
<%= f.fields_for :tasks do |task_form| %>
  <%= task_form.text_field :name %>
  <%= task_form.link_to_remove "Remove this task" %>
<% end %>
<%= f.link_to_add "Add a task", :tasks %>
Nested_form also works nicely inside simple_form: simple_nested_form_for


Fake it!

If like me you seem to be a corner-case magnet, then you have wondered how to use fields_for to render fields, but not the ones included in the model already. In my case, I wanted to add documents to a model, but not render a field set for any existing documents.

The answer ( in the context of the original documentation):

<%= f.fields_for :tasks, [] do |task_form| %>
  <%= task_form.text_field :name %>
  <%= task_form.link_to_remove "Remove this task" %>
<% end %>
<%= f.link_to_add "Add a task", :tasks %>
This will let you add child items, without cluttering the view with existing items


Thursday, May 17, 2012

T2D or not T2D

The  hidden costs of  meeting moronic ideals

Recently, I've had the distinct misfortune of working with an advocate of test driven development.

Now, generally this is not a bad thing. There is a case to be made for testing, certainly. My extreme and utter distain for TDD however, is rekindled anew when I see how inefficient it realy is. (The developer is a cool guy, this is not a reflection on him, just on the TDD philosophy)

Have you found Jesus?

I often hear the same old sales pitch: 'you will save so much time later' or 'you write better code'. Bull Shit.

People who advocate TDD  have either never had to cost a project for development, or have never had to pay for some other insipid ass-hat to dev with it.

It won't save you time later.  All you get for having a 'good' test set is the guilt-induced obligation to maintain it.

It will cost you a lot of time. Often when you can least afford it, like two days before a deadline.

When I develop an application, I often don't know where it will end up. That's agile development. I jump in and code and the app will bring itself into existence. Obviously this is an oversimplification of the whole process, but I want to put it in stark contrast to planned development.

Yin

In planned development, developers make implementation decisions that drive the stream of application growth ever closer to the well defined end goal, in as straight a line as possible. The cost of planning is upfront, and the incentive is there to not deviate, because it negates all the planning.

I compare this to building a tunnel to get to the other side of a mountain. It's startlingly direct and incrementally very expensive in effort. Developers are often forced to use the biggest hammer they can find to bludgeon the code toward the end goal.

Yang

In the other corder is agile development. Developers guide the code into being. Coaxing it toward some end goal.

In the analogy, this is akin to building a curving mountain pass that follows the contours of the land *. Doing it the scenic way is incrementally cheap and you can always change your mind and follow a different curve at almost any point.

To milk this lovely construction analogy some more. With agile development, you get to see the view from the top of the mountain and often see outcomes and possibilities that you would never have even considered if you were stuck in a tunnel. So fuck tunnels.

What ?

What has this got to do with testing?  Well, a lot and almost nothing at the same time.

When you plan software ahead, you can write tests to evaluate against the planned outcome. If the tests pass, then presumably you have not fucked it all up. I'd stop short of saying it's guaranteed to work, because all a passing test proves is that a test passes.

Writing tests beforehand puts a goalpost down that you then code towards. So there goes all agile intentions and benefits. If you still want agile development,  you have to embrace writing and rewriting tests until ...

You go north. You are in an cubicle. 
The letters 'TDD' are scrawled in feces on the wall. 
A dead developer lies in the corner.

This applies on every scale. If you want to test methods, then you need to know those methods before you have developed the code. So you need to  go and guess at what the solution might be, without the benefit of experience of actually solving the problem. And then ? Well then you anally mauraude your code until that quick guess is the solution, because fuck, we have a test that needs to pass!

I shall now coin the phrase: Goatse Driven Development! **

Not testing methods, just testing requests? Same shit, different scale. What if in the solving of the problem you realise a complete new controller actually solves it elegantly. Instead, you are stuck with a test for your 3s hair-brained guess from before, that you now have to make work.

This is where many TDD ass-hats jump up and scream that you need to just adapt your test. Really ? "Adapting" it just a euphemism for "rewrite your tests at every turn in the agile development process".

That's insanely expensive, on every level. Good developers change their minds about almost every single choice they make, because they question themselves. You are beating that doubt out of them, and making them stick with the first crap that comes into their head, just to avoid writing that test one more time.

So inconclusion:

Say 'TDD' again. Say 'TDD' again, I dare you, I double dare you motherfucker, say TDD one more Goddamn time!


* This is an awesome analogy, like a hotdog
** or, I guess Goal Driven Development. But fuck that. ***
*** oooh, double entendre! Score!

Monday, January 9, 2012

Work it like a chain gang

From time to time I find myself using ternary conditionals to output information in an app. If that made little sense to you, you likely should not be reading this blog.

In groovy, we have something like this:

condition ? 'value if true' : 'value if false'

It get even nicer if you considder this form:

condition ?: 'value if false'

where the true case will just return the condition as the value.


Consider:

book.author ?: 'unknown'

which will return author.toString() if it's not false/null or 'unknown'.

I've long thought Ruby lacked that elegance and so often resorted to the very cumbersome

book.author ? book.author : 'unknown'

until I stumbled onto this (even more elegant) approach:

book.author || 'unknown'

One can take this one step further, and chain them up. The first 'true' output is returned:

book.author || book.publisher || 'unknown'

or even

author.books && author.books.first || 'unpublished'

This latter form will prevent "null.first" errors.

Monday, November 21, 2011

Say what one more fucking time!*


So I recently inherited a Soundblaster audio card from a friend. In general I maintain that average people just cant hear the difference in good and bad sound, but I decided to install it in any event, just cause I can.

Or so I thought.

Enter the hell that is linux support for audio drivers. Fuck all worked.

I eventually (20 forum trawls later) settled on trying to install OSS, which proceeded to break what sound I had before I started.

So, out with the Soundblaster and remove what I could of the changes. Still no sound. My Logitect cam which I use for skype (+ internal mic) were not on the available hardware lists even.

My startup drivers no longer loaded my on-board sound even. An entry for  snd-hda-intel eventually fixed than, but still no cam-sound.

So I left it for a few days...

This morning, wanting to skype again, I looked around and found a damn blacklist file installed by OSS, in /etc/modprobe.d.

I checked and oss4-base was still installed, I had missed it somehow. So I removed it and removed it's modprobe files and that storted everything out.


Afterthought


I've been pondering a better setup for my PC. I try to play a few games like Eve and LOTRO when time allows. For that I have an ancient XP boot on a slow second HDD that I change to.


I think a much better setup will be a new fast HDD, installed with Windows (whatever is latest, 7, 8 ?). Then install ubuntu on a virtual box inside that. I'ts not like I need ubuntu for anything heavy, I just need it "in front" when I code, so I can just switch into the VB and work like that.


This way I wont have to reboot (well other that for windows' own moronic reasons, which I'm told is few and far between lately), and my work "machine" can be transferred if ever I upgrade windows (as opposed to the nervous "did I just fuck up my partition table" moments otherwise)

*I believe this is a Samuel Jackson line form a movie. I don't really care, I just needed an offensive title.

Monday, September 19, 2011

QOTD "Faster! Faster!"

I recently advised our team to used single quotes instead of double quotes, unless they obviously need interpolation in the strings.

Of course, I immediately got a nice reply about about a benchmark to compare the two use cases. I did not even look it up before making the recommendation. I try not to let facts cloud my opinions.

So there is the benchmark, as extolled on StackOverflow:


$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.6.2]
$ cat benchmark_quotes.rb
require 'benchmark'
n = 1000000
Benchmark.bm do |x|
  x.report("assign single") { n.times do; c = 'a string'; end}
  x.report("assign double") { n.times do; c = "a string"; end}
  x.report("assing interp") { n.times do; c = "a string #{'b string'}"; end}
  x.report("concat single") { n.times do; 'a string ' + 'b string'; end}
  x.report("concat double") { n.times do; "a string " + "b string"; end}
end

$ ruby -w benchmark_quotes.rb 
      user     system      total        real
assign single  2.600000   1.060000   3.660000 (  3.720909)
assign double  2.590000   1.050000   3.640000 (  3.675082)
assing interp  2.620000   1.050000   3.670000 (  3.704218)
concat single  3.760000   1.080000   4.840000 (  4.888394)
concat double  3.700000   1.070000   4.770000 (  4.818794)


So doubles on the whole are just fine to use all the time. In fact, single quotes are a tad slower in basic use. Who knew.


To quote http://blog.ntrippy.net/, "Just because my opinion has changed, does not mean the fact that I'm right has."*

*See what I did there?

Friday, September 16, 2011

On the other other hand

I like using polymorphic tables in Rails, it's often a very nice way of structuring access to a single object from multiple points.

To define a polymorphic association, you need to to this in your class:

class Thing < ActiveRecord::Base
   belongs_to :thingable, :polymorphic => true
   #...
end

and on the other side

class Foo < ActiveRecord::Base
   has_may :things :as => :thingable
end

class Bar < ActiveRecord::Base
   has_may :things :as => :thingable
end

Your migration looks like:

class CreateThings < ActiveRecord::Migration
  def change
    create_table :things do |t|
      # attributes ...
      t.string :thingable_type
      #turns into thingable_id
      t.belongs_to :thingable
      t.timestamps
    end
  end
end

Enter the hand that is short

class CreateThings < ActiveRecord::Migration
  def change
    create_table :things do |t|
      # attributes ...
      t.references :thingable, :polymorphic => true
      t.timestamps
    end
  end
end

Tuesday, September 13, 2011

Preach it sister!

I don't often/ever repost other bloggers, but  this guy has such an elegant solution to serious pain in the ass, I thought I'd give him a mention.

alfajango


The problem he solves is very simply: ajax file uploads with jQuery in rails.

He explains the problem and wrote a neat gem called remotipart that just rocks, and is completely unobtrusive to the application.

Good on ya mate!