Tuesday, January 25, 2011

Is Consulting Like Dating?

If so, it really explains a lot. The tech republic has a blog entry that goes all pedantic about the simile, but there is at least the illusory feeling of truthiness to it.

I never dated as a kid. As a teen I think I had one date, and it went nowhere. Truth is, I didn't know what was expected of me in social situations then, and more or less still don't now.

The article starts off with, "keeping clients happy may be similar to keeping your significant other interested," which strikes me as ironic and a little funny given that most married folks in the US end up divorced.

Well, I tried to bend over backwards to keep people happy. It doesn't work, for them or for me. So when a recent prospect complained to a mutual friend that I was a "dead end," because I hadn't been in contact for three weeks, at first I was a little bit taken aback and afraid that something I had not done was unprofessional and had spoiled the relationship.

Then I realized, we don't have a relationship, that prospect and I. We never did. She said she'd be in touch, but expected me to be banging down her door. She wanted me to tell her I had free hours I did not have. She complained to her friend instead of probing me back. She wanted me to dance, and I'm not a dancer.

I understand. I know there are many people far more successful than myself because they do the dance, they have a knack of schmoozing and persuasion. Those were skills that at first I merely lacked, but then consciously eschewed. It was not just a recognition of how much effort was wasted, or that the cost to me personally of trying to do that dance was too exhausting.

It was the false premise of it, the inert fakery sitting behind the outward countenances, and the desire of seemingly nice people to take advantage of your openness. It does not excite me to be constantly mindful to probe and prod clients constantly when I'm solving technical problems.

And when my own family members aren't interested in talking to me, worrying about whether I'm stroking a client's ego frequently enough just isn't on my list of priorities. Frankly, the prospect complaining to her girlfriend told me a lot about her style of communication and her own ability to think straight, and it isn't good.

Acting like a consultant

This week-end I had a small verbal slap on the knuckles reminder that acting like a programmer is not sufficient to be a good consultant. It is difficult for some of us to come up from the sea of hardware and software and breath, and in the meantime people can feel abandoned or ignored.

Truth is, my boldness comes in fits and starts, and it is difficult for me to maintain constant communication with my network. It is complicated by my personality, but it isn't
who I am
, it is rather a skill that, in practice, I haven't mastered.

On the other hand, I find that it terribly distracting to be thinking about who I need to contact, keep their particulars in my head, and think proactively about their situations. I have to block the social aspects out of my mind while I'm programming, otherwise everything blurs.

Thinking like a consultant has other differences from programming in the raw:
  • Strategic thinking versus an "order taking" mentality
  • Dialog versus top-down communications
  • Probing for needs versus accepting plans as communicated
  • Asking questions to build a strategic understanding instead of focusing on tactical steps
  • Build a working context of the client's business: how they generate income; how they differentiate themselves from competition; industry shifts; customer and employee issues; the problems at hand and the client's objectives
  • Leading the discussion and influencing it to set expectations
  • Keeping the dialog going (this is a pain point for us programming types!)

Saturday, January 22, 2011

Hobos hacking on Rails

Testing my newly found programming confidence, I started hacking up an example survey form for a client. I tried Hobo, which led to some interesting observations about what Agile really means.

One moment my sample app was working, the next it was not. The problem was that I had generated a resources controller and model combination with a name that Rails did not like.

I checked over the model names and use ack to search for deviances. Convention over configuration, they say, except that nothing appears to be deviating. Somewhere along the line something got mixed up, and now it doesn't just work. Instead it broke the whole application.

Well, that points up a couple of ugly properties of Rails apps.

Small changes have an application-spanning impact


Pre-Web languages, such as C and Perl, have their issues with program structure and encapsulation, but Ruby on Rails (and other Web frameworks) have nothing to write home about in this respect: it is trivially easy to expose your system to breakage.

The thing Rails does right is to help ensure that such changes don't get pushed out to production. That's the test-first methodology. The thing it does wrong is a feature: the use of English language part-of-speech heuristics to create mappings amongst the MVC components. It gets it wrong about 10% of the time, that is to say, I get it wrong but the framework makes it easy to do so and hard to spot the location of the incorrect guesswork.

I'd rather not have to keep fixing the 10% or so times when the heuristics don't match the way I want to phrase the solution. But heuristic gaps are correctable; the persistent itch is that the framework wants to tell me to stick to a formula but hides all the wiring that would tell me where and how I'm crossing the lines, and translates tiny errors into epic fails.

A System That Uses HTML Is Not A Hypertext System


MVC frameworks are not really Web application frameworks but application frameworks that utilize the syntax of Web technologies to communicate. That is not easily correctable by slight alterations in practice.

State representations and transitions in a Rails app are all wired up through explicit code. Each entity is identified by a row number and associated by integer relations (this management strategy is reminiscent of DBase, but what "relational database" means and how Rails isolates the database layer is another discussion altogether). MVC uses views that spit out markup, but in themselves, views do not comprise state representations.

The RESTful Web uses links to stepping through the state space, and delivers markup documents that embody the current state representation along with the transition paths. That takes a kind of markup calculus to implement. Although Rails attempts to derive MVC patterns and hides a lot of its complexity in convention and meta-programming, there is an essential difference in the level of logic at play in the reduction of a solution.

A url format does not makes a system RESTful. A framework that stores almost all but not quite everything in sessions, and wires up features in point-to-point coding is doing what amounts to a Web algebra. That is very un-RESTful. Rails is on the top of the MVC heap, but what MVC platforms do is a little of the wrong sort of bespoke calculus mixed with a lot of idiomatic algebraic logic.

Bottom Line


MVC platforms are more than a slight inductive mismatch to the RESTful archetype. In my humbler opinion, REST requires a comprehensive markup calculus to accomplish. An effective REST platform should provide comprehensible algebraic representations and coherent integration and derivation techniques that do not require nail-up code to implement, conventions not withstanding.

Tuesday, January 18, 2011

Recent proverbs, aphorisms, and admonishments

Never interrupt an interrupt.
If you don't understand this, you may be functionally ADD.
  • Me: "Do you know what that means?"
  • She: "No."
  • Me: "_That_, is why you fail."
  • She, laughing: "No, sir, that is why I succeed."
From experience, I can tell you she lets her interruptions get interrupted all the time. One might also suppose that it is bad to stack interruptions, or shuffle them around, but let's not bend the metaphor too much lest it break and we expend too much time picking up little pieces of interruptions all about us.
Organized like scrambled eggs
My son suggested this simile after attempting to design landscapes with a group on an online game called Minecraft. It applies well to the domain of programming. Ad-hoc development, whether coding, Minecraft landscape layout, or any other design regime and medium, all share common characteristics... what seems organic and natural at first may quickly decompose into an amorphous slurry of mush.
Code Grieving
Another anti-social pattern observed in Minecraft, and doubtless other online simulacra. A "griever" is a game player who rather purposefully destroys other peoples' creative efforts. By analogy, a code griever is a peer who, without acting collaboratively, breaks down working code that is already there. (Pair programming can sometimes feel as if you are being grieved, but it isn't the same phenomena.)
Vanity of vanities. All is vanity.
Explaining that wouldn't be worth the effort.

Monday, January 17, 2011

Minimal Viable Specification

Every now and again you get to see glimpses of how people think in the way they formulate and frame up a discussion, that tells you they obviously adopted language from someone who did not think as they did. Such is the case with the term "Minimal Viable Product".

The term is remarkably similar to euphemisms for unborn babies [er, "fetuses"]. It invokes a metaphor of a gestating product, which might be aborted should it fail to exhibit a minimal feature set.  I personally find the term to be in poor taste, and more than slightly stupid in assuming requirements form a static set over which you can assess a minimum.

Nevertheless, it is commonly used in Agile/Lean circles.  Transitively and reflexively, one might ask the question of why there is then no "Minimal Viable Specification". It is not a foregone conclusion that a system must be over-specified before building can proceed, but neither is it an obvious truism that a stream-of-consciousness approach to coding gives the best value proposition to the client.

A minimum viable product implies that a set of coherent requirements could have been envisioned at some scale, while some who use the term often advocate explicitly against just such specifications.  I understand why: as programmers, we get paid to code, not to specify. Well, sort of.  Maybe, maybe not.

I've also heard it said that the code _is_ the specification. Or that the tests in TDD/BDD are the specifications. While these arguments have merit from the programmer's perspective, they are arcane and continue to sound weak from a customer's viewpoint -- at least as far as the tests or code don't rise to the level of abstraction that the customer's brain is at.

Einstein is widely credited with saying that things should be as simple as possible but no simpler; yet it was Newton hundreds of years before who was able to practically refract white light and recompose them again... thereby demonstrating that the most apparently simple of colors is also a composite and the most complex colors of all.  The trouble with scientists is that sooner or later a few of them will make inconvenient things like facts get in the way of conveniently wrong abstractions. The trouble with reality is that it doesn't respect Agile ad-hoc abstractions and just keeps on behaving the same whether you believe in it or not.

So I posit that there is some minimal specification that really does need, in effect, to be professionally drafted and validated, else someone is taking too much risk, paying too much money, and/or just getting suckered into a co-dependent relationship with coders.  Not that I pretend to know what that minimum is, I am just suggesting that it must exist, and the tangible artifacts representing it should consist of more than just a few notes taken while schmoozing with a client.

Different Shades of Grey

I just spent some time finishing cleaning up my gemsets, and re-installing Bundler, per my earlier posting about using RVM.  In all, I have three distinct Rails applications set up in my workspace right now, each with a slight variation on the technology stack:
  1. Rails 3 and Ruby 1.9.2 
  2. Rails 3.x and Ruby 1.8.7 and Hobo 1.0.3
  3. Rails 2.3.5 and Ruby 1.8.7 and Hobo 1.0.2
Using the "put everything in @global" approach worked OK for (1) alone, but when (2) and especially (3) came along, Bundler got downright confused about which Rails to run even though it knew which one was supposed to have been installed and which version was called out in the Gemfile. 

Two failure modalities were found. First, even though the Ruby version-specific global gemsets had been emptied, the 1.8.7 global gemset had inadvertently been repopulated by an errant bundle install.  Second, neither that gemset nor the app-specific gemset contained the Bundler gem itself, which had been silently "adopted" from the enclosing (system wide) environment.  

The solution was to reset... go back and clear out the gemsets like I had before, and this time make sure the app-specific gemset had been properly selected before running gem install bundler and then bundle install. 

Incidentally, how you start the server depends, but it seems that there are at least two ways :
  • script/server
  • rails server
I guess I don't know enough about the blessed way of Ruby server zen, but it certainly wasn't obvious by looking at the files sitting in the local directory. 

Monday, January 10, 2011

Pretending Javascript has Object Orientation

Suppose I have a Prototype.js class:


var Parent = Class.create({
initialize: function() {... }
invariantProcess: function() {
this.part1();
this.part2();
},
part1: Prototype.emptyFunction,
part2: Prototype.emptyFunction,
});


and a subclass


var Child = Class.create(Parent,{
initialize: function($super) { $super... }
part1: function() { ... draw part 1 ... },
part2: function() { ... draw part 2 ... },
});


Ordinarily, inheritance and virtual dispatching allows us to override part1 and part2 without touching the invariantProcess in the base class. This often fails in Javascript as an indirect side-effect of the fact that classes are library constructs, not first-class objects.

In Javascript, what is commonly called "inheritance" is actually just copying properties around instances and instance prototypes, and names in method bodies are lexically bound to the scope in which the method is defined.

None of that is a bad thing. The bad thing is when you take a second-class method and treat it as if it were an independent function. This can happen, for instance, when you pass the method as a callback function. The bindings can get botched, with names either undefined or bound to the wrong object. In the example above, "this" might not be the "this" that we want it to be.

I ran across this recently while creating Prototype.js class wrappers for a Processing.js example. Processing expects a callback that will bind a drawing function to the library, but when a method is used as the callback it can horribly ugly to get the bindings correct.

The solution generally amounts to using a Factory pattern, returning a new function with the critical variables defined in the enclosing scope. This all but rules out using methods directly, which then take the role as supporting functions instead.

Saturday, January 8, 2011

More hoboization

I was playing with Processing.js and decided that it would be easier to use a Rails server to fiddle with the prototypes than installing an apache server or ftping to a host.  So I returned to one of my trial apps, leapercan, and tried to run the server.  It bombed out.

Yet I hadn't touched that code tree! When side-effects happen just because, is an obvious sign that you have violated (or never adopted) the axiom of closure. I happen to think closure is a good thing in general, when you can get it. I'd much rather trade extra disk space to get it than my time in debugging strange errors.

It happens that we use RVM, the Ruby Version Manager. We also use Bundler. What we haven't been using is RVM's Gemsets. Other developers with whom I've been pairing with over the past few months maintain a practice of always using the @global gemset, and use Bundler to maintain the gems. In this practice, RVM is relegated to maintaining only distinctive Ruby versions.  This is supposed to work in theory because Bundler version control for the gems used by an application.

The root cause for the failure?  My Leapercan application was based on Hobo 1.0.x, using Rails 2.x and Ruby 1.8.7. With a Splotchup application I tried out Hobo 1.3.x, using Rails 3.x and Ruby 1.8.7. Starting to see the trouble yet?

Bundler is fine for fetching and installing specified versions of gems. But in practice I have found that it did not maintain two different versions of the same gem, each for a different application. I'm told that it should, and that the ".lock" file should fixate the versions of the gems in use. But when I switched my working context, things just broke. My working hypothesis is that my Gemfile did not specify a version for some gems, and the use of a single gemset allowed bundling from one app to affect the gems v another app.

Using @global gemset is a good idea when you run a single Ruby version for a single application, and want to save space. It is a bad idea otherwise.

My solution? Impose closure. I don't care if I lose a little, or a lot, of disk space with separate gem copies. I want my application development and source tree completely and utterly self-contained and self-consistent. The way to accomplish closure is to get rid of global defaults and spurious sharing.
  1. Don't rely on the System ruby. Unfortunately, if you've done anything interesting already you'll have to hack some directories to get rid of the system gems. Ironically enough Mac OSX lacks even a half-baked GUI for managing system add-on components. It would be better to fix RVM to avoid the real problem, which is that it does not sandbox out the system gems, but I had already done the removal before thinking of that approach.

    sudo mv /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8 \/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8.default
    sudo mkdir  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8 
  2. Use RVM to install each Ruby version you will use

    rvm install 1.8.7
    rvm install 1.9.2

  3. For each application, create a gemset; empty the global gemset for the ruby it will use.

    rvm use 1.8.7
    rvm gemset empty global
    rvm gemset create splotchup
    rvm gemset create leapercan

  4. When you start developing, switch to the gemset automatically

    cd ~/workspace/splotchup
    echo "rvm use ruby-1.8.7@splotchup" > .rvmrc

    cd ~/workspace/leapercan
    echo "rvm use ruby-1.8.7@leapercan" > .rvmrc
  5. Install Bundler, then let Bundler take care of the rest; avoid using gem to install gems other than initially installing bundler.

    cd ~/workspace/splotchup
    gem install bundler  # if you haven't already
    bundle install

    cd ~/workspace/leapercan
    gem install bundler
    bundle install

  6. If you maintain different mainline branches of development (an unnecessary complication in my book), create and use a corresponding empty gemset.
There now. My apps are completely isolated from one another. A purist might object that I'm duplicating a lot of code here, but there are two answers to this:
  • So What? Most ruby gems are small. The supposed space saving is a false economy, since the bugs introduced by violating closure cost much more. 
  • There is no duplication and this is not a violation of DRY. Application-specific gemsets are necessary and sufficient because the gems are a factorable part of the application source, not universal attributes of the environment.

Saturday, January 1, 2011

Knowledge is not infinite; neither is ignorance

A FB friend posted a quote by Zhuang Zi,


Life Is Finite, While Knowledge Is Infinite.


Thing is, words have meaning, and those many meanings that words can have may be unbounded. Yet while  unbounded implies pluralities it certainly doesn't necessitate infinities. The real difficulty here is that we neglect an operational definition for knowledge, one that allows us to allocate our ignorances wisely.

Knowledge poses an interesting term in this respect, because we so often conflate the many meanings to the point that the word itself barely means anything distinguishable.  To Zhuang Zi, knowledge is certainly not a trait wholly attributable to humans, else his quote would be silly on its face. Zhuang's knowledge exists outside of Life, something to be pursued yet which is unfathomable.

On the other hand, what is knowledge if it is not known by a knower? The true knowledge of every man perishes with him, whether he be an author or a ditch digger, rich or poor, wise or foolish.  Without a knower, our thoughts may be meta references to that we don't yet know; they may be delusions, or  dreamlike feelings reverberating in our skulls affirming that we know when really, we don't.

It is the arrangement of neural inter-patternings enabling imagining of our universe including concepts such as "other" and "self" that we call knowledge. Those patterns are complicated. Numerous. Interdependent. But not infinite. It is that finitude that allows us to learn, make practical generalizations, and to reframe and parameterize our understanding.

While the experiences that are thrown at society in general and us in particular are unbounded,  they induce knowledge if and only if they alter someone's brain chemistry; and that knowledge only remains around as long as those brains retain their altered states. In effect, our brains are big self-mutating hash functions, funneling those experiences from an infinity of infinities down to a countable set of neural patterns. And like any hash function, the pigeonhole principle rules.