The Joel Test: work vs. home

Joel Spolsky, 18 years ago, wrote “The Joel Test: 12 Steps to Better Code“.  Granted, it’s 18 years ago, but I thought it would be amusing to score my home work environment with my work work environment:

One point for each yes:

Work:

Do you use source control?  1/2 (yes, but not properly)
Can you make a build in one step? 1
Do you make daily builds? 0 – no, manually initiated
Do you have a bug database? 0 – not that I’ve ever seen
Do you fix bugs before writing new code? 0 – hahahaha
Do you have an up-to-date schedule? 0 – schedule, what’s that?
Do you have a spec? 0 – do you count screenshots in Excel as a spec?
Do programmers have quiet working conditions? 0 – unless you count needing to wear headphones
Do you use the best tools money can buy? 0 – VS2015, .NET 4.5, etc.
Do you have testers? 1
Do new candidates write code during their interview? 0 – I wasn’t.
Do you do hallway usability testing? 0

Score: 2.5

Home:

Do you use source control? 1
Can you make a build in one step? 1
Do you make daily builds? 0
Do you have a bug database? 1
Do you fix bugs before writing new code? 1/2 (I really try to practice this)
Do you have an up-to-date schedule? 0 – my clients are pretty loose about schedules…
Do you have a spec? 1 – …but they’re good about specs.
Do programmers have quiet working conditions? 1 (as in, total silence)
Do you use the best tools money can buy? 1
Do you have testers? 1 (assuming the client doing the testing counts)
Do new candidates write code during their interview? 0 – don’t interview people
Do you do hallway usability testing? 0 – unless the cats count.

Score: 7.5

It’s sad how my home environment scores considerably better than my work environment.  No wonder there’s a “no telecommuting policy”, right?

 

TDD is not the Failure, our Culture of Development Is

In the article TDD is dead.  Long live testing.  and a subsequent response The pitfalls of Test-Driven Development, both authors, in my opinion, are missing the mark by a mile. In the real world, walking into an existing code base, the reason you need TDD (but can’t use it) is because programmers didn’t spend sufficient time on good architecture practices, resulting in code that is an entangled morass of intertwined concerns, and yes, as one of the author’s points out, because the code itself was never intended to be tested except through, at best, acceptance test procedures (most likely the pen and paper variety — with the developer watching in the background hoping he rolls a 20.)  There is an overall lack of attention paid to designing a component with sufficient abstraction that it can accommodate changing requirements, and little or no attention paid to separating (decoupling) the behaviors between components such that component A shouldn’t ever care about what component B is doing. We have a philosophy of refactoring with “just get the minimum to work” to blame for that — the days of thinking about architecture and abstraction are long gone.

The metaphor of building a sky-scraper is inaccurate because anyone building a sky-scraper would know that you can’t make the walls of the first floor so weak that they can’t support a second floor. Except it is accurate because, not paying attention to the requirements and living in a “do the minimum work” philosophy, promoted by the likes of Kent Beck’s Agile Programming and Martin Fowler’s refactoring philosophies (along with their mutant child Extreme Programming), this actually is exactly what ends up happening, and thus TDD is an absolute necessary fallout of a broken coding paradigm. A more accurate metaphor would have been, the requirements called for a single story building, then the requirements changed. Again, with sufficient abstraction up front, the straw-bale walls could be replaced with titanium reinforced hay quite easily.

As for Rails (or rather Ruby, or rather any duck-typed language), TDD is again essential because duck-typing allows for variances in the behavior at runtime, both of type and function calls. The non-strictness of duck-typing is leveraged in lieu of good object-oriented design–why create sub-classes when I can just pass in an instance that quacks just like the other “ducks.” While object-oriented programming cannot be done well without object-oriented design (and yes, I’ve seen both the “P” and the “D” done horribly and have done it horribly myself) a duck-type language allows the programmer to completely eliminate the “D” — class, method, quack, quack. Perhaps we should take a clue from the name, “duck-typing”, that it is actually quackery, and like medical quackery, promises rapid “feel good” development that you end up paying for in little fragments of time running unit and integration tests because you didn’t do the necessary up front design, you haven’t clearly abstracted how the rules are handled, you haven’t clearly decoupled the behaviors of complex systems to identify the dependencies (which all complex systems will have.) If you add up all the time spent running those tests (which of course spawned whole new technologies to run those tests faster and faster) you will discover that over the lifetime of the product, you spent far more time watching little green bars (or red ones) than you would have spent on solid up-front architecture, particularly in the areas of abstraction. But nay, it quacks, and it’s fast. At first.

As for “the industry’s sorry lack of automated, regression testing”, here, let’s not blame the programmer directly even though they consistently over-promise and under-estimate, but rather, let’s blame a culture, yes, starting with “the geek” but also placing responsibility firmly on the business practices of management and the continually demonstrated lack of understanding of the importance of regression testing, and the time & cost that developing regression tests and even more costly, maintaining those tests, requires. As with essentially all other aspects of our society, we are living in a constant tension between short-term gains and long-term investment (TDD can be considered an investment) and we all know which side is winning. We have a culture that rewards quick results and punishes the methodical and (seen as) slow thinker. Some of this may be justifiable due to market pressures and real budgetary constraints, but what is lacking is the consciousness to balance planning and activity.  So what we have instead is a knee-jerk culture oriented to quick results (Agile Programming and Refactoring) which, to support a broken development paradigm, demands TDD as the “fix”, but nobody seems sees that.

When one of the author’s writes “I have yet to see a concrete illustration of how to use Test-Driven Development to test a back-end system interacting with a 20-year-old mainframe validating credit card transactions” I laugh because I have done just that — CC validation systems all have the means of simulating transactions, it’s actually trivial to write TDD’s against such systems. Yes, the author does have a point that much of the “…source code [encountered in legacy systems]…was never designed to be tested in the first place…”, but again, that’s missing the point — TDD is clearly the wrong tool for those systems. TDD works best in an environment:

  • lacking architecture,
  • most likely using duck-typing languages,
  • and, most importantly, one that has started from ground zero with testing as one of the coding requirements.

This is independent of whether it’s a 200 line gem (as in Ruby library as opposed to a “great thing”) or a 100 million line application. If those 100 million lines were written with the intention of being unit / feature tested, then there is no problem. Except that it’s TDD and probably not well architected out of the gate.  And let me be clear that TDD, when applied to a well architected application, is a perfectly valid and beneficial practice, but then TDD is also simplified because it ends up testing behaviors, not architectural flaws and geese trying to pretend to be ducks.

So, is the failure TDD? No. The failure is in a culture entrenched at all levels of software development that says that Agile Programming and Refactoring can replace thinking and it’s brothers “design” and “planning.”  We have Kent Beck and Martin Fowler (I commit sacrilege in criticizing the gods) to squarely blame for that “regression”, excuse me, “story.”  And it’s those two aspects (pun intended) of programming that should be given the boot, not TDD, which has a validity in and of itself under the right conditions.  However, even Agile & refactoring are merely symptoms  (or victims) of a cultural disease that demotes thinking (we need only look at our K-12 education systems and Common Core for proof) and promotes the short-term gain (as demonstrated by our economic, medical, agricultural, etc. practices.)

Beware of Ruby’s string split function

Observe this behavior:

split

 

 

 

And the description in the documentation:

“If the limit parameter is omitted, trailing null fields are suppressed. If limit is a positive number, at most that number of fields will be returned (if limit is 1, the entire string is returned as the only entry in an array). If negative, there is no limit to the number of fields returned, and trailing null fields are not suppressed.”

Now, while I can somewhat understand this behavior, it is certainly in opposition with regards to the behavior of the split function in other languages that I’ve used.  Ruby’s default behavior can cause serious problems when parsing CSV files and auto-populating fields where you expect empty strings rather than nils.

Which brings up the next point:

split2

 

 

When I index outside of the array length, no exception is thrown.  Come on, Ruby!  That’s just bad form.  Again, the Ruby documentation for array says:

To raise an error for indices outside of the array bounds or else to provide a default value when that happens, you can use fetch.

Sigh.

 

LibXML — empty nodes (and the libxml-rails gem)

I was going to title this post “LibXML — how to fail right out of the box” but then thought a more accurately description of the problem might be better.  There is something I don’t understand about the open source community: its tolerance.  I encountered this problem right out of the gate:

The XML:

<?xml version="1.0" encoding="UTF-8"?>
<root_node>
<elem1 attr1="val1" attr2="val2"/>
<elem2 attr1="val1" attr2="val2"/>
<elem3 attr="baz">
  <elem4/>
  <elem5>
    <elem6>Content for element 6</elem6>
  </elem5>
</elem3>
</root_node>

The resulting root children:

libxml-1

 

 

 

 

Do tell me why whitespace and CRLF’s are seen as empty nodes?  Do tell me why this is absurd behavior is tolerated as the default?  I had to google for some indication as to what’s going on.  This fixes the problem (Ruby code):

doc = XML::Document.file('foo.xml', :
  encoding => XML::Encoding::UTF_8, 
  :options => LibXML::XML::Parser::Options::NOBLANKS)

Other than that, it looks like a decent enough package, though I haven’t explored it further.

The libxml-ruby gem

The libxml-ruby gem worked fine, but I did have to, as the documentation says, copy three binaries into the one of the directories in the Windows path.  Happily, the gem comes with the precompiled binaries – that’s a real help and kudos to the gem authors for providing the MinGW32 binaries.

Recaptcha, Foundation, Sass, and the “different prefix” error

Recaptcha and Foundation

After creating a test project, I finally connected the dots that my inclusion of foundation_and_overrides.scss was causing the problem with the rendering of the recaptcha block (see my previous post.)  A quick google search led me here where DinkoMiletic provides a good solution:

#recaptcha_area input[type="text"] {
  display: inline-block;
  height: auto;
}

Disturbingly, “thedeerchild” writes: ” It’s not really feasible to pull out a core part of our styling due to third party compatibility issues, and it’s fairly easy to overwrite the Foundation styles to fix reCaptcha.”

Now, personally, I think that’s a cop out.  If you’re going to write something as “foundational” (pun intended) as a presentation layer styler, then it is damn well your responsibility when some third party component has compatibility issues, especially one so prevalent as Google’s recaptcha.   Now, granted, I’m not using the most recent version of Foundation, so perhaps the issue has been fixed, but at a minimum, I think these kinds of compatibility issues should be easily found in the documentation, not buried in some forum post.

SASS and the “Different Prefix” Error

However, when I set up my new test project, I started getting the following error:

ActionView::Template::Error (different prefix: "C:/" and "E:/rails-projects/airity/app/assets/stylesheets"

I have never, until this morning, had a problem running rails projects on a different drive.  Now, this morning, this happens.  As others suggested, moving the project back to the C drive where I RailsInstaller did its thing is a solution.  While I came across a few different “solutions” (none of which worked and some of which required forking the sass-rails gem), the only solution that worked and allowed me to keep the project on the desired drive was to use a simlink.

Because this problem appears to be common with other gems (like bootstrap-sass, read here), I am definitely interested in a global solution rather than something that fixes the problem for just one issue.  The mklink command was for some reason undecipherable to me, so as per a suggestion here, I downloaded Directory Linker and filled in:

Link Location: the new folder name on the C drive that I want.  In my case “c:\rails-projects\airity”

Link To: The existing folder name on my E drive.  In my case “e:\rails-projects\airity”

Click Go!, it does it’s thing in a second or so, then verify that the project files and folders exist on the C drive.

After reloading the project in RubyMine from the C drive, lo-and-behold, no more problems with the prefix.

Now if I could only bill the 4 hours I spent this morning working around problems that someone else caused by some update (which I was completely unable to track down, even after setting specific versions of sass and sass-rails based on my laptop version numbers).

Then again, those people that have suffered through this and found solutions which I then used, well, they should be the ones getting the money.

So, now it’s almost 3PM and I’m finally able to get to what I wanted to at 9 this morning (yes, there was lunch and grocery run in between.)  And yes, the reCAPTCHA block now works with Foundation:

recap1

Ruby, Nested Yields, and Implicit Return Values

This is one of the many reasons I cringe at languages like Ruby with implicit behaviors.  Take this example:

class DoStuff
  attr_reader :accum

  def initialize
    @accum = ''
  end

  def do_a(&block)
    @accum << 'a'
    @accum << yield
  end

  def do_b(&block)
    @accum << 'b'
    @accum << yield
  end
end

def fubar
  do_stuff = DoStuff.new

  do_stuff.do_a do
    do_stuff.do_b do
      "rec\r\n"
    end
  end

  puts (do_stuff.accum)
end

fubar

Quick, tell me why the return is:

abrec
abrec

The reason is because the outer call do_stuff.do_a() has an implicit return of the result of the call to do_stuff.do_b() and so also returns “rec”.

To fix this, one must explicitly return an empty string as the return:

  do_stuff.do_a do
    do_stuff.do_b do
      "rec\r\n"
    end
    ''
  end

and now the return is:

abrec

So, beware, especially beginner programmers, of the implicit return in Ruby functions.

Compare this with a C# implementation:

public class DoStuff
{
    public string Accum {get; protected set;}

    public DoStuff()
    {
        Accum = "";
    }

    public void DoA(Func a)
    {
        Accum.Append("a");
        Accum.Append(a());
    }

    public void DoB(Func b)
    {
        Accum.Append("b");
        Accum.Append(b());
    }
}

class Program
{
    static void Main(string[] args)
    {
        DoStuff doStuff = new DoStuff();
        doStuff.DoA(() => doStuff.DoB(() => "rec\r\n"));
        Console.WriteLine(doStuff.Accum.ToString());
   }
}

We get a compiler error:

Cannot implicitly convert type ‘void’ to ‘string’

This clearly tells us we have done something wrong.

If we change the return types to strings, then it becomes obvious (hopefully) that we want to return an empty string:

public string DoA(Func a)
{
    Accum.Append("a");
    Accum.Append(a());
            
    return "";
}

public string DoB(Func b)
{
    Accum.Append("b");
    Accum.Append(b());

    return "";
}

and we get the desired behavior.

We can of course write the code the illustrate the implicit return of the Ruby code, but of course the C# code clearly illustrates this (and therefore the error of our ways):

public string DoA(Func a)
{
    Accum.Append("a");
    Accum.Append(a());
            
    return Accum.ToString();
}

public string DoB(Func b)
{
    Accum.Append("b");
    Accum.Append(b());

    return Accum.ToString();
}

And indeed, we get:

abrec
abrec

just like in my “wrong” Ruby example.

Microsoft, SQL Server 2012 Express, and Failure

I’m doing a bit of multitasking today, mainly fixing a bunch of Ruby on Rails features for my client while doing some setup stuff on my workstation, like installing the latest version of SQL Server Express.

So I go this download page:

http://www.microsoft.com/en-us/download/details.aspx?id=29062

First thing I notice is how poorly this page correlates the download options with the filenames.   Here’s a screenshot of the download page:

fail1And here’s the descriptions (which of course requires that you click on “Details” to even see.)

fail2Notice that there is nothing that says “this installer is this file”.  You have to figure out that “With Tools” is the “WT” version, etc.

Finally, after 40 minutes of waiting for a 600 MB download (why are things so slow on your systems, Microsoft?) I get this message:

fail3And yet:

fail4It says right there that Windows 7 is supported!!!

So Microsoft, four failures for what should be one simple task.  Nice batting average.

“We Fought The Good Fight”

“‘We fought the good fight; we just didn’t win,’ Boehner told a radio station in his home state of Ohio in reference to GOP efforts to dismantle or defund President Barack Obama’s signature health care reforms and extract deficit reduction concessions around the need to fund the government and raise the federal borrowing limit.” (source)

No, Mr. Boehner, you did not fight the good fight.  Instead, you are a traitor to the American people, causing the suffering of untold Americans.  Here’s an example:

“Our Shutdown Fears Have Been Realized”

To quote from the above article:

“But temporary layoffs for Lorien and 200-plus workers at the resort went into effect on October 1 after the park’s closure. She expects to come back to work after the government resumes, but she won’t get back any of her lost pay because the lodge is owned by a private company.” (my bold text)

I agree with an op-ed piece I had on NPR a couple weeks ago.  Boehner and the rest of the right-wing conservative Tea Party Republicans should be tried as traitors to their country.

 

When Metro Fails

Here’s a great example of a fail, in my opinion, of a Metro design.  It’s the installer for Wix Toolset:

wix1

This is a Metro looking starting screen, and it took me probably 15 seconds to figure out where I was supposed to click to install the toolset.

First issue: What’s with all the red?  This means I should be paying attention to something, right?

Second issue: What the heck is this screen?  I was expecting a standard install screen.

Third issue: Now what?  What am I supposed to do?  The icons are meaningless to me.  Oh wait, maybe I should read that teansie-weansie text for each of the boxes.

Fourth issue: Ah, there is “Install” in a tiny font.

Really, just because Microsoft says “Metro” doesn’t mean we all need to jump like automatons, does it?  And if you think Metro is the right way to go, please, please, design something that actually is intuitive.

Further Failures

After clicking on “Install”, I note the following further failures:

  1. The entry on my Window’s taskbar shows an icon that I can only assume is from Wix with no text.  wix2That’s helpful.
  2. The installation starts with a spinning “gear” – I have no idea what it’s doing.
  3. A lot of meaningless file information eventually flashes by, too fast to read, too long to fit on the screen.
  4. The progress bar (if you can figure out that the darker red is a progress bar) jumps right, left, right, left, like a spastic hamster
  5. After it’s completed, the first screenshot still stays there.  Now what?  I guess I should click on “Exit”?

That my 2c.

Occupy Patent Office – Apple Patents that fail

We really need to start an action group (Occupy Patent Office???) to stop idiotic patents. I’ve been reading the patent that Apple sued HTC over, and came across this one as well, and I must say, these are so blatantly obvious ideas, they cannot possibly be patentable in my mind. A patent should be an “invention”. Algorithms like these are not inventions, they are simple parsers that anyone with a modicum of intelligence will think of.  You can tell they are trying to turn it into an invention with terminology and processes like this:

The system provides an analyzer server, an application program interface, a user interface and an action processor.

So, how did HTC get sued over this implementation? You don’t need an analyzer “server”, or an “API”, or an “action processor” to do this stuff. WTF? Yes, those are nice abstractions, but that’s all they are, not some “invention”.

From dictionary.com, “invention”:

U.S. Patent Law . a new, useful process, machine, improvement, etc., that did not exist previously and that is recognized as the product of some unique intuition or genius, as distinguished from ordinary mechanical skill or craftsmanship.

Apple. You FAIL. Patent Office. You FAIL.  These patents are not a display of some unique intuition or genius.  They are very ordinary, obvious, solutions to improving the user experience.

This is why I don’t by Apple stuff. I refuse to feed the monster.  Of course, that just means I’m feeding a different monster.