Thursday, December 29, 2011

Selling Yourself Out of Projects

So, a friend tells me about a buddy who "has a software project you can help him with."

Prospects are very subjective creatures. I tend to think that a professional, whether a software craftsperson or an engineer, or something else, has a kind of fiduciary ethic even toward prospects. If a prospect asks about developing a software project, my immediate concerns are
  1. Does the client really need custom development?
  2. Is there an existing service that already meets their needs?
  3. Will the recurrent tangible and intangible costs  (of any desired path) present an impractical future burden ?
Unqualified prospects would result in No to the first question and/or Yes to the second question.  The third question is one that no salesperson in their right mind would venture to probe, but it represents a core value of the engineering ethos.  Is the prospect willing and able to accept the costs?

I'm in my right mind, but I'm not as much a salesperson as my friend.  So I informed the prospect of his options and alternatives early, and gave him some context of the cost. That approach pre-qualifies many prospects out of project, or at least, sends them looking for someone else who is more willing to lead clients down a primrose path. 

The thing is, my friend would have just jumped into the job, sweeping questions about the likely costs under the rug,  playing dumb about the prospect's needs and getting them to pay for scraps of functionality as soon as possible.  This sort of drive-by software development is all too common. 

I'd rather sell myself out of a project than put blinders on and lead prospects down a rabbit hole. That may not be the magical thinking that fuels so many Law of Attraction acolytes, but it is the path an ethical person will tend to follow. 

Thursday, December 22, 2011

Unconscientious Prospects


I was contacted recently via email, by a prospect seeking assistance with a small PHP/MySQL project. Now, disregarding my personal distaste for Rube Goldberg skunkworks cobbled together in PHP, I offered to help anyway. Paraphrasing the conversation it went something like this:

Prospect: 
Hi, I was given your name by *********.  I have a web based tool and would like to make minor modifications to it. I want to remove some functions for a one-time use.  It should not be very involved or big task but I need to have it up and running  in three weeks.  If you think you might be interested please let me know.

Me: (replying a few hours later)
I'd be happy to discuss your needs for the Web tool.  If you would like to talk, I have some time this week. Let me know. 

Prospect: (no reply for two days)

Me: (two days later, this time with a return receipt attached)
Hi, I just wanted to follow up to make sure you received my reply. Are you still looking for assistance? 

Prospect:
Hi, got follow up from someone else before your reply.  Will need to do some other work and will get in touch with you when I am ready.

Me:
My immediate knee-jerk reaction to this was, "hey, someone beat me to it, good for them!" but then a couple of thoughts occurred:
  • It is unprofessional to ask someone for help, then ignore their attempts to communicate.

    Everyone gets distracted once in a while, but even if you aren't immediately going to do business with someone, if they extended the courtesy of a reply you owe them the same courtesy in return.

    The oblivious lack of courtesy of dropping an email exchange is like walking through a door and letting it slam shut in the face of the person behind you. It isn't very pleasant to the slam-e, and it reflects poorly upon you.
  • Conversely, if you judge suitability based upon the how quickly one responds, you aren't looking for a relationship but a one-night stand.

    Look, as a freelance programmer I'm not seeking to date you or marry you.  But I do have an expectation of a certain amount of reciprocal attentiveness and return on my investment of time.  Treating your search for help as if you are casting chum and netting the first fish that bites, shows that you are not very conscientious. Or at least, when push comes to shove you become neglectful.   
I'm less and less interested in giving people second chances, perhaps because I've often been so long-suffering on the first go-round.  What is really beginning to annoy me though is the attitude that we're just "resources" or "commodities".  Damn it, Jim, I'm a person, not a commodity.  If you care so little about who you employ and you can't communicate and you consider the effort to be so small, why would I want to bother doing business with you?


Friday, December 16, 2011

CSS Grammar Considered Wrong

I get a little nit-picky every time I look at CSS.
Take the way that the media queries spec handles dimensions like width and height. They couldn't just say "width", no, no, that would be just too easy. Instead they say min-width, width, and max-width.


Flea microphotograph

CSS grammar is meant to be declarative, but that's not the reason for using prefixes. The CSS media queries section on media features tries to explain the rationale:

Most media features accept optional ‘min-’ or ‘max-’ prefixes to express "greater or equal to" and "smaller or equal to" constraints. This syntax is used to avoid "<" and ">" characters which may conflict with HTML and XML. Those media features that accept prefixes will most often be used with prefixes, but can also be used alone.

Never mind that CSS selectors already use the greater-than symbol. The grammar has gotten land-locked, but it has never used commonly accepted notation for mathematical expressions. You know, expressions such as:

width: (160,320)   (interval notation)


160 < width < 320   (set builder notation)


(160..320,true).include? width   (Ruby, using a range)


width BETWEEN 160 AND 320   (SQL)


Whatever. The nit I'm picking is not that the CSS editors have had to work with what they've inherited.

Whether an historical accident or pragmatic contingency, using prefixes (min-, max-) on property names as grammatical substitutes for logic expressions (>=, <= respectively) constitutes a multiplication of entities way beyond necessity. Instead of one property (width) within two scopes (logical and device), CSS presents us with:

width


device-width


min-width


min-device-width


max-width


max-device-width


aspect-ratio   (CSS pixel width/height)


device-aspect-ratio


min-aspect-ratio


max-aspect-ratio


min-device-aspect-ratio


max-device-aspect-ratio


orientation  (width > height ? landscape : portrait )

Them's A DOZEN MORE properties, baby.
That's just for one stinkin' property, so don't be callin' me all pedantic on this.   If y'all leave nits alone they grow and soon enough you find yourself infested with lice. (Not that I have any experience with lice.)




The gratuitous prefixes don't make the resulting media queries any more elegant to express:

@media screen and (min-width: 160) and (max-width: 320) {
  stuff {  goes: here;  }
}


The problem is that CSS uses a fixed set of discretely expressed predicates for continuous and dynamically varying values. What I want it to say instead is something more along the lines of:

@media screen and (160 < width < 320) )   {
  stuff {  goes: here;   }
}

or
@media screen and (width: range(160..320) ) )   {
  stuff {  goes: here;   }
}


CSS is what it is and for better or worse this design choice passed through the editing and public commentary process intact.  Other efforts can still learn from its missteps as much as its successes.  Injecting special-case grammatical devices is an easy way to make a language available early but injecting them often will turn even a greenfield language into yet another Rube Goldberg device. As a device, CSS has more than a little Rube Goldberg in it. 

Tuesday, December 13, 2011

Dropped Google Ads

For a long time, I had a little sidebar of Google ads displayed on my blog. No more.

At the time it seemed like the thing to do. Syndicated advertising was all the rage, everyone was supposed to find ways to monetize their sites, blah blah blah...

I just threw up the sidebar to go through the steps needed, in case I needed to do it for someone else and just out of curiosity to see what it would generate. Well, this blog is, should we say, along the road less travelled, so the ads never amounted to anything monetarily.

It turns out that Google ads looked really sucky when the mobile template was active. Actually, they look sucky any time, but their relative sucky-ness increases as the display window decreases. I don't know why, they were just ugly.

There was another downside too: besides detracting from the visuals, syndicated advertisements contradict one of the messages of the blog: our society has put so much of its human capital into manipulating perceptions that it has eaten away at workplace ethics and cannibalized its equity in the process.

Bye bye, Google ads, I'm not really going to miss you.

Monday, December 12, 2011

Musings on consciousness

Janice Janes had a very informal, very anecdotal hypothesis: before the human condition first acquired consciousnes, our existence was dictated by a non self-aware construct he termed the bicameral mind. Janes argues that the development of consciousness is in part language based, and in part wired into our brains, based upon the authority structures of the culture. Consciousness thus developed over time as the challenges of dealing with multiple interacting cultures forced the simple structures to break down and be reconstituted, generation after generation.

I don't know whether Janes' ideas were away in left field or in any way mainstream, but they were intriguing. Through his lens it was easy to interpret xenophobia, black and white doctrines, separatism, etc. as attempts by a subculture to regain some measure of the simplicity of the less self-reflective mind.

Janes' assumptions that consciousness was/is an ever progressing evolutionary eventuality are wrong. Cultures can and do move backwards towards a less than fully conscious hive mind mentality. If anything, consciousness is Lamarkian, not Darwinian. Consider the culture of Afghanistan, or, closer to home, religious cults. Fanatical followers of media personalities such as Oprah or Jim Bakker (not to say they are equivalent however) oven have great difficulty separating their own opinons from those espoused by their glorified leaders. Prejudice is the antithesis of consciousness.

And it isn't just about collectivist authority structures, but personal identity. Experience of the world drives consciousness about that world. Less experience implies a narrow, specialized focus but also a limit to consciousness. Ignorance is bliss. Experiences by proxy, as through the Web and TV, create a consciousness that does not accurately image or respond to the physical and social world. In this case, ignorance is not bliss as the conflicting and falsified viewpoints creates unnecessary and unhelpful reflection.

Thursday, December 8, 2011

Autocorrective Crowd Sourcing and Autocatalytic Systems Programming

So, a friend sends me this link about how Recapcha is being used to pawn off digitizing work to unsuspecting users, in an ingenious manner:




Setting aside for the moment any ethical considerations of virtual slavery and digitally indentured servitude, it really is a masterful plan.

The crowd sourcing model can even be used to clean up application data, even when the crowd is relatively small.

Another friend related the case where a US federal government department contacted him, to consult on  scrubbing business names from a terabyte scale database. The chief difficulty is that much of the data originated by people typing in whatever they wanted. My friend rightly points out that it is always cleaner to select a coded value from a list, rather than allow free form typing. That is not possible when the values vary, as human contrivances (company names) frequently do.

Systems may be designed to allow people to type in new names in a free form manner. Free form data input means Garbage in, Garbage out: there is no way to identify the unbounded variation of lexical strings by which a company name is known. Consider the morphisms of the Johnson & Johnson corporate apellation:

Johnson and Johnson
Johnson & Johnson
Johnson & Johnson, Inc.
Johnson and Johnson, Incorporated
J&J,
J & J,
J& J,
J. & J. ,
J and J
jnj.com

The letter case is not such a big deal. Neither is the variation of whitespace, or even the substitution of the ampersand for the word "and".  The problem is that the set of these names is finite but unbounded and the set changes over time. There is no easy way of identifying entries that go with the canonical name for a given organization.

Or isn't there? Applications capture this data in daily interactions with users. Combo boxes can list previous entries and make coded selections, while allowing novel inputs.  So use string pattern matching to do a lookup of the possibilities based upon the first few characters typed. But don't look into the old records, look into a map of generated and collected synonyms instead.

Allow the user to start entering the name of the company. If after the first few letters, you find an exact match on a canonical name and the user accepts it, you're done: just take the code for the canonical name. If there are no perfect matches, generate a set of weighted regexp patterns based upon the user input; any original names that match and are accepted by the user are recorded as a probable match for future lookups.

That is admittedly rather sketchy, but I'm sure someone has implemented a few schemes along these lines to clean up old data. What would some of the advantages be?

  • Cost is not incurred when the effort has no value.
    • Data for companies that are no longer participating is not touched.
  • Effort is expended whenever it is needed.
    • Data for companies that are participating often are improved more rapidly. 
  • Refinement of the data set is embedded as a design feature of the system.
    • Not one-shot: Cleaning of the data continues over the lifespan of the system.
    • Tracks the moving target: Data set targets are ambiguous symbols representing shifting human contrivances (businesses).  

Can the strategy work?  Biological systems do something analogous in the form of DNA error detection and repair. They are far from perfect, but organisms maintain their integrity for decades, up to hundreds of years... thousands if you consider some of the oldest organisms like trees and fungi.

The key idea here is accepting that determinism in complex systems is a convenient myth that is sometimes more trouble than it is worth.  That realization opens the way for explicitly probabilistic feedback loops -- just one more way for complex computer systems to fulfill their original design intent to illuminate the processes of life.


Tuesday, December 6, 2011

Attending Triangle JS Meetup

I'm attending the Triangle JavaScript Meetup tonight. They're discussing Toura Mulberry.

the original photo is by mauroguanandi on Flickr
The open source mobile development and deployment tool, not the fruit. @rmurphey from Toura is presenting.

Mulberry is a toolchain and deployment strategy wrapped around PhoneGap. The unofficial description is that it follows a Rails-like approach to the toolchain. As far as deployment is concerned, Mulberry acts as an HTML browser in a private application.

Mulberry attempts to be a full-cycle development stack for applications deployed as embedded Web-browser (using Sinatra?), displaying content from JSON. Most of the responsibility for presentation sits on the mobile device, implemented in JavaScript. In fact, most of the HMTML and markdown gets converted into JSON content data, which is then composed into DOM by JavaScript on the client.

Like Rails, Mulberry is opinionated, and provides generators for scaffolding. It relies upon the exposure of content through a "node" interface to publish data. Several of the artifacts created with the generator are configuration files for things like the media form factors, devices, site map, default content (in markdown), routes, etc. The system is then immediately available to test using "mulberry serve", the built-in server, without a build process. Also like Rails, the system uses special URL formats to convey configuration settings in the running app.

Basically, Mulberry is a single page, off-line application meant for quick deployment.

Mulberry sends most of the content down as a static set of nodes, but the deployment wrapper supports polling for content refreshes. Currently that functionality is limited to content, not including templates or behavior, due to Apple Store guidelines.

Also mentioned
Ripple
Weinre
iWebInspector

Saturday, December 3, 2011

Thinking matters, even in Condé Nast magazines

I'm on a quest to get healthier despite my programmer ways, and I do a fair bit of researching. To that end, I review medical literature from databases like PubMed/Medline, and look for the reasons supporting or conflicting with pop-culture (including government) recommendations.

In my perusing, I came across a nutritional site about the Fructose content of various foods, operated by SELF Magazine.  That's good, because fructose acts like alcohol to the liver, leading to cirrosis, insulin resistance and diabetes, which is bad.

SELF is one of those Condé Nast periodicals aimed squarely at the well-off-but-otherwise-insecure-young-female crowd.  I'm trying to limit the intake of high fructose foods in my lifestyle, and if is informative to hot, wealthy, young women surely I can use it too.

Except it doesn't matter if we guys have almost all the same genes as gals and fructose doesn't seem to respect any of the differences...



...because as presented the site offers utterly bogus information. In fact, the data is often upside-down.

Let's take a look and make some conclusions based on the site's rankings:

  • Molasses has half the fructose content of iceberg lettuce
  • Applesauce is ranked higher (worse) than honey
  • Plums and onions are almost the same
  • Celery is at #179, within the top 200, having 6.4 grams of Fructose
  • Cabbage is ranked higher than Raisin Bran cereal


By ranking the foods based on a fixed calorie count, rather than on a realistic volume or weight basis, the Condé Nast list implies utterly terrible lifestyle advice. It can't be that hard to figure out that foods like cabbage contribute a tiny amount of fructose to the diet.   People who rely upon SELF for nutritional information are not at all well-served by such a poorly designed guideline. Clearly, the folks over at Condé Nast aren't very serious about presenting good nutritional information to women.

If I were Sarah Chubb (president of Condé Nast Digital) I'd order the nutrition site taken down immediately and replace the person who had editorial responsibility for it.  Chubb should find people who can reason quantitatively, and think about the content, not just about how it is presented.