Sunday, November 28, 2010

Things I Don't Miss About Windows

After working on a MacBook Pro with OSX Snow Leopard for a few months, I almost go into convulsions when I am forced to tolerate the utter inferiority of Microsoft Windows.  Don't ask me which version: XP, Vista, or 7 are all just different colors of terrible.


While UNIX was a proven and well-understood operating system (OS) for mini computers, the original PCs were underpowered and had to settle for much less than a real OS. Yet UNIX had captured much critical knowledge about how to succeed at providing access to computer resources.  Support for multiple users, connectivity, and the security it would require were accommodated by fundamental design decisions built into its core.

Over years the feature set of Microsoft's OSs have expanded to cover many of the same requirements as UNIX, yet without the same level of consistency and performance as the latter.  The Windows OS line is itself probably responsible for more security breaches and real dollar losses expended in dealing with its security issues, than any other OS on the face of the planet.

Steve Jobs made a brilliant move in adopting a UNIX style core for OSX. Are there still flaws? Sure. But you just don't see the time robbing, attention wasting, excessive security risks that you are guaranteed to see under a Windows regime.

They say, "Time is Money,", but really it is worse than that. You will never get back the time you lose dealing with the short comings of the Microsoft platform. Best never to go that way, for down that path lies madness.

Friday, November 26, 2010

Industrial Strength Testing for Joomla Part 3

Under a test-first development practice when you're rolling out an add-on, you should also be rolling out a rigorous suite of tests to demonstrate that the add-on really works and satisfies some fundamental security and accessibility criteria.

Lacking such an automated test suite, it is not rational to expect an add-on to perform correctly. It is certainly not reasonable to purchase an add-on without the assurance that a test suite passes and can be repeated under your host environment. 

The truth is, most software is crappy. Let's posit a valuation function Crppnss(t) to determine how crappy a piece of software is, and suppose it is inversely proportional to the number of automated tests V(t): Crppnss(t)=1/V(t). That's a reasonable assumption. Although there are studies that suggest the relationship between latent bugs and number of tests is linear, even a small number of tests can have an impact much greater than a linear correspondence.

Since most Joomla components show little or no evidence of automated testing, it follows that most Joomla components should have high Crppnss. That is to say, the theory would predict that they should be quite crappy, and that is just what we see in practice.

Am I missing something here? No doubt. Yet I suspect that the Joomla/PHP testing cup will still be less than half full when I'm filled in on what I'm missing.

After my initial draft of this post, I did more research. Apparently PHPUnit and Selenium, with a Joomla specific runner, is the soup du jour for Joomla 1.6 testing. It is evident that the team has put in a good amount of effort to put together a rational tool chain and process. So the Crppnss for Joomla has officially gone from infinite in version 1.5 to less than one in version 1.6. 

Thursday, November 25, 2010

Industrial Strength Testing for Joomla Part 2

Following up to my previous post, I'm really regretting the lack of general testing facilities in Joomla. 

Curiously, the Joomla MVC framework doesn't seem to help as much as hurt. Unlike Rails/Grails/Cake etc the framework doesn't do code generation and doesn't speak to clean coding idioms. So you end up with the worst of both worlds: the constraints of a framework with the productivity of from-the-ground-up work.

It isn't that testing in the framework is poorly framed -- it is simply absent from the picture.  The developer shouldn't really be "rolling his own" when it comes to extending and integrating with a content management system. An active Joomla contributor could speak better to the test coverage and soundness of their PHP tool chain and technology stack, but I've seen little evidence that testing is handled with any rigor in the Joomla community at large.

Why do I bring it up? It costs a lot of time to fix stuff that other people broke, and I cannot afford to do that. I don't like doing it either. Foundations should be demonstrably sound and stable.  If you cannot demonstrate soundness and stability with rigorous tests, your are living in a magical pixie dust land where everything flies because you wave your hands and say it is so.

Wednesday, November 24, 2010

Let The Right One In

As I sit here in my favorite pizzeria, Anzio's, having downed one too many of the tasty circular sectors, I notice someone walk in the door that I recognize. It is the owner of a local auto repair chain, and a prominent member of the local chamber.

We've met a handful of times; his blank expression says that he either doesn't recognize me or doesn't want to acknowledge my presence through eye contact. Either way it is fairly strange behavior from someone in sales.

Now, ordinarily I might re-re-re-introduce myself, but I've gotten some very peculiar vibes from chamber people. Like they don't know me, and don't want to. There's something very icy about meetings that they and other organizations do as networking-for-networkings-sake events.

When someone doesn't want to acknowledge you it probably isn't worth a second thought. Like this blog entry. Ah well. No harm, no foul.

The second thought is this. I contrast his behavior to that of a sales clerk. During a visit to the local Tiger Direct, uh, sorry, "CompUSA", turning to speak to my son I heard someone say, "hey, I know you". Looking back, I immediately recognized a guy who had visited the Raleigh-Durham Web Design Meetup several months back.

The guy had taken a sales clerk position after a business venture failed to come together. We chatted briefly about a common problem of finding resources to pursue projects, about networking, and his new job, then he showed my son where some cables were.

What's the difference between these two people's perception of me?  One was approachable and open, and treated me as a peer; the other was absent and closed, and treated me as a total stranger. One was searching for business, the other had inherited his business from his family. One seems to have more money than the other, but I'm more likely to get leads and business from people who are open like the sales clerk than people who are closed like the auto guy.

We can and do affect how people perceive us through our initial contacts with them. On the other hand, no amount of contact will alter a person's integrity. Some people are just going to play you. Others will maintain an adversarial position and keep a poker face on, no matter what your intentions, altruism, or openness. It is best not to let those ones in.

Industrial Strength Testing for Joomla Part 1

Ugh. Developing with PHP seems like such a crap shoot, and the picture gets even more muddled if you try to work with a rats nest of third-party components. In general, the quality just isn't there.

My development environment for PHP bears some of the blame. I'm not a Zend user yet, though I probably should be. Still, like C and Perl, PHP seems to encourage inelegant coding.

One tool that I have used is VirtualBox. "What," say you, "does VirtualBox have to do with testing?" Well, for one thing, VirtualBox allows me to virtually reconstruct almost any hosting environment on my Lenovo T61 or MacBook Pro. The result replicates the hosting environment much better than a "WAMP" style native installer, compartmentalizes the services in a sandbox that can be put to sleep, and avoids application upgrade hell. It can even replicate the horrors of "open_basedir=." in its PHP configuration (that breaks a LOT of packages).

I've used the Joomla JumpBox appliance for a test deployment server, but recently switched to using the TurnKey Joomla appliance. Could I use shared or cloud hosting for test deployment? Yes, but the local virtual machine is private, fast, and can be junked much more quickly.

When used in the development cycle, a virtual appliance is, in effect, an industrial strength test fixture. But test fixtures are only a part of the solution to testing. A general purpose test framework is needed.

Monday, November 22, 2010

Hobo, Finally

During the previous setting up of the Heroku staging, I found out the name Heroku gave to my new application:

Creating afternoon-water-18...... done
Created |
Git remote leapercan added

OK, that's a bit strange, but I can deal with it. The name of my app as known by Heroku is "afternoon-water-18". 

I need a database for my Hobo. I choose MySQL, just because it makes me do something to set up. Plus, I've already got it installed. 

I update my Gemfile to include the mysql gem:
mvim Gemfile
gem 'mysql'

then invoke bundler again
bundle install

Now to create the database:
mysql -h localhost -u root 
mysql> create database leapercan;
Query OK, 1 row affected (0.12 sec)
mysql> quit

I don't have a password set up for my database. I should. There's no excuse for laziness, except procrastination. I'll do that later.  The changes will go into database.yml . Since I don't have a password set up it should just work.

Now I call Hobo to generate the application:

hobo -d mysql leapercan

Lots of output. Well, everything is great, except that the app now lives under a subdirectory. I use mv to put the files up one directory. 

mv leapercan/* .
rmdir leapercan

There, that's better. Next time I'll do that a bit differently. 

I follow the tutorial from here, and create a hobo migration:
ruby script/generate hobo_migration
Unknown database 'leapercan_development'

Uh-oh... did I miss something obvious? Yup -- I omitted the _development from the intended database name... go back into mysql... drop database leapercan; create database leapercan_development;

Try again... looks good this time. It asks me if I want to generate or migrate now, or cancel?  I migrate now and accept the default migration name. Hobo takes care of running the migration for me, so I don't have to rake db:migrate at this point.

OK, so time to try it out a little:

ruby script/server 

A mongrel server is started, which we can visit at localhost:3000.  Very niftily (I know that's not a word): hobo has created a closed shell of an application with user accounts, and is ready to set up an administrative user.  Hobo feels more like a 4GL rapid application builder than Rails alone. 

I'm adding a model now. The tutorial is talking about Contacts, but I want to think about the warranty information I had to track down this morning.  I carry around keys and coins and never really have trouble finding them because they are either in my pocket or dropped into a bowl on the nightstand. I admit, sometimes I leave them in my pocket and dig them out before throwing the clothes into the laundry.

ruby script/generate hobo_model_resource pocket name:string content:text

Wow, it really generates a lot of stuff. A RoR purist might say it is a bit much, but I don't know enough to be that picky. I migrate again, same method as before:

ruby script/generate hobo_migration

Cool. Now there's a new tab for Pockets, apparently with the CRUD interfaces bootstrapped for me. I create a new Pocket, call it Leapercan, and put some application maintenance details in it. Stuff someone would eventually ask about, if they were asked to support the application.

It just works. That's a very, very nice quality.

Did I mention how little I value debugging? Debugging other peoples' code is like trying to understand and have a discussion with another developer by relaying the messages through a stupid, more or less insane, and completely soulless being. I'm in awe of people who can do it, but I'm finding I have less and less tolerance for stuff that doesn't work as expected.

The tutorial mentions how Hobo works at this point, automagically adding or removing fields and tables, based directly upon what it finds or doesn't in the models. To delete a table, just delete its model and generate another migration. You'll be doing the hobo_migration dance a lot during early development.

On the other hand, rolling back to a previous version apparently involves editing of the migration files directly and a  rake db:migrate VERSION = version_no  

It isn't much, but I'll push it anyway. Nope... Heroku says I need to run bundler. Bundler says I don't. What gives?  It tells me to look at completely unhelpful advice... GoogleTime... looks like a common problem, but the advice offered doesn't work. Like, AT ALL.

git add Gemfile.lock
git commit -m "Added Gemfile.lock"

After several attempts at modifying the Gemfile, running bundler, and adding both the Gemfile and Gemfile.lock, git push leapercan master still craps out with that same error. Every Time. Even when I destroy and reinit the git repository.

Looks like Heroku is in the crapper at this point in time. It took me from a nearly seamless experience to an brick wall. Epic fail. Waiting, wondering, and - the thing I hate most of all - debugging someone else's code.

I'm starting to hate you, Heroku, and I hardly even know you.

So I start hacking, wildly guessing. I figure, something is lying to me, so I decide to do exactly the opposite of what it seems to be telling me. It says

   You have modified your Gemfile in development but did not check the resulting snapshot (Gemfile.lock) into version control

   You have deleted from the Gemfile:
   * version: 1.0.6

MISDIRECTION! I really wish that some programmers would learn to communicate better than brain damaged slugs.

Google had a lot of bad advice, utter nonsense, akin to cutting off a chicken's head and sprinkling its blood on the ground. The true reason for the problem is that Bundler records its version number in the METADATA section (which happens to be at version 1.0.6), and the bundler up on Heroku (version 1.0.3) apparently cannot deal with the fact that it has a slightly different revision level.  So I deleted the version number line from Gemfile.lock, and BAM, it just works.


Except... it didn't work. The command line says "yes" but the Web interface says something went drastically wrong. Wait. I forgot one more step: the Heroku database migration.

heroku rake db:migrate

Ah, such sweet release. All done.

The bundler version discrepancy reminds me of US EPA emissions requirements for commuter vehicles: not only do the requirements add to the cost and complexity of the auto, the emissions parts are directly the cause of most of the failures. How much difference is there between 1.0.3 and 1.0.6? Probably very little. Yet the version labels themselves completely HOSED the system. There's a lesson in there somewhere, about not enforcing something that doesn't really matter.

Rapid Rails with Hobo (Free from the Hobo site)

Sunday, November 21, 2010

Hobo on Heroku

Ok, so I'm toying with a Web application, code named "leapercan" because Leprechaun is not only unavailable as a domain name it is also difficult to spell.

Not that I claim to be especially proficient in Ruby or Rails, but I've been fortunate to help a really crack team of Ruby on Rails programmers for the past couple of months. I'm a dinosaur by comparison, but I'm picking up something along the way.

So I want to try something new, but RubyOnRails based. We've been using Rails 3 with all sorts of gems including RSpec, Steak, and Jasmine, and deploying with Capistrano. I'm looking for a solo app -- Hobo sounds interesting, and a free account on Heroku is an easy way to get started.

Here's what I've done and found so far.

Before anything else, note that I'm hanging back on versions so as to avoid having to deal with bugs at the bleeding-edge. My goal is to explore Hobo and Rails capabilities, not to debug them.

Debugging time is time mostly wasted.  Like an argument with your spouse once you've worked around the disagreement you generally forget why it was a problem in the first place.

First, I use RVM to manage my Ruby versions, but not the gemsets feature. So I install version 1.8.7 and set a .rvmrc up so that my work environment will default to rvm's global gemset for 1.8.7.

cd ~/workspace
mkdir leapercan
echo "rvm use 1.8.7@global" > leapercan/.rvmrc
cd leapercan

RVM now tells me that 1.8.7 is selected. Now, if I had other 1.8.7 apps on this machine, I might use a named gemset instead, to avoid polluting the global space; in that case, I would have used the gemset name instead of "global". Now that I think of it, that probably would have been a better idea...

I confirm it is using the right Ruby. As it happens, my system ruby is also 1.8.7, so I could have avoided the download. I check the version

which ruby


Next, I install the bundler, because it is just easier to list the right gems in a file than to 'member the nitty-gritty details in stream-of-consciousness mode.

gem install bundler

After that, I use my trusty MVIM to edit the Gemfile, and put in the gems we're expecting to use:

source ''

gem 'rails', '2.3.10'
gem 'hobo', '1.0.2'
gem 'heroku', '1.13.7'

I'm a freakin' idiot savant, to have come up with the version numbers, right? Wrong. I used the fact that provides a RESTful interface to look at the all kinds of information about a given gem, and just plugged and chugged until I figured out which versions I could probably use without too much more trouble.  The format I used was , where GEMNAME was one of rails, hobo, and heroku.

Write and quit the Gemfile, and run bundler:

bundle install

Gahk! It complains about

Could not find gem 'rails2.3.10 (>= 0, runtime)' in any of the gem sources listed in your Gemfile.
Well, that's not right. I had omitted a comma after the gem name and version number, and bundler just concatenated the two into one string.  I correct the mistake and continue. 

After a while of downloading and installing, you'll end up with a bunch of new gems in your rvm maintained gemset. You can list these with gem:

gem list

*** LOCAL GEMS ***

actionmailer (2.3.10)
actionpack (2.3.10)
activerecord (2.3.10)
activeresource (2.3.10)
activesupport (2.3.10)
bundler (1.0.6)
configuration (1.1.0)
heroku (1.13.7)
hobo (1.0.2)
hobofields (1.0.2)
hobosupport (1.0.2)
json_pure (1.4.6)
launchy (0.3.7)
mime-types (1.16)
rack (1.1.0)
rails (2.3.10)
rake (0.8.7)
rest-client (1.6.1)
will_paginate (2.3.15)

OK. So, by now I've also set up a free account on Heroku, gotten a link to activate the account, and logged in. Heroku says I need to add my public SSH key, so I do:

heroku keys:add

Enter your Heroku credentials.
Password: ********
Uploading ssh public key /Users/mamiano/.ssh/

(Note that I had used earlier used ssh-keygen to create my public and private keys as part of a GitHub account setup. You don't need a GitHub account to use Heroku, just git. Google it if you don't know how.)

You can use "heroku help" to list a quick reference to the commands. I won't repeat them here.

Heroku says I need to set up my working directory as a GIT repository, so I do:

git init
git add .

git commit -m "LeaperCan: gold at the end of the rainbow"
 4 files changed, 63 insertions(+), 0 deletions(-)
 create mode 100644 .bundle/config
 create mode 100644 .rvmrc
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock

Now we need to tell Heroku about the new application. A helpful blogger has already run into the problem of using a slightly newer version of Rails than is standard on Heroku, and pointed out the command line to use the "bamboo" stack instead, which has my version of Rails on it:

heroku create --stack bamboo-ree-1.8.7 --remote leapercan

Git remote leapercan added

So, at this point, I've gotten myself a live sandbox to play in... I'm ready to actually play with a Hobo application.

To Do: Play play play, edit edit edit, do stuff...

Now suppose we have played enough that we have something to deploy. According to Kiwiluv, it is as simple as doing two steps:

git push leapercan master


heroku rake db:migrate --app heroku-app-name

Unfortunately at the moment my family wants attention and I'm just about out of play time.
Sigh. Rather than forget what I've just done, I take what time I have left and dump it into my blog, along with the references.


Saturday, November 20, 2010

A Smattering of Design Guidelines

Use the metaphor of resources to determine consistent, implementable URL and URI patterns for your pages. Sketch your site's map. But only just sketch.  If you don't understand how this relates to your design, consider that "pages" is just a metaphor itself and the branches of site map don't necessarily mean "page". 

Lay out for substantive content first. 

Get specifications for the devices you expect to support for access to your information.  Generalize the specifications into a set of parameters characterizing a category of media, rather than device.  Create a style profile for each generalized category of media space. You might have a Desktop space, a high-definition smartphone space, a low-definition mobile space, a tablet space, etc.  Consider each profile a proxy for one of your audiences.

Define your profiles incrementally. Choose a grid or columnar layout, and flow content into place.

Apply a strategy using Occam's Razor to your code:
pluralitas non est ponenda sine necessitate 
Which is to say, don't use more markup than absolutely necessary to convey the meaning of the message. Use CSS for style. Don't use DIVs for positioning or include other gratuitous markup for layout tricks.  Don't rely upon the relative positions and parent/child relationships in the markup for style or layout effects beyond in-line layout.

Include a browser reset. That will eliminate browser-introduced pluralities. It is regrettable that as of the year 2010 CSS3 and HTML5 still make it difficult to follow the Occam's Razor principle. But even a critic can see the situation is improving.

Use Behavior Driven Development with scenarios to storyboard the site. Why is anyone looking? What do they need to do?

Friday, November 19, 2010

Joomla means carnage

Man oh man. I just got done futzing around with an XML RPC service plugin for Joomla. What a nightmare, like slogging up to your neck in feces for four hours.

Thing is, it isn't that complicated a problem, but trying to do things the "right" way is what makes it virtually impossible to accomplish.

First, there is little published information that is in any way self-consistent. Please don't tell me about the so-called "Master ..." book for Joomla. It is spotty at best. The information might be there, but it is so poorly organized that you have to jump around in the book to patch it together, making it that much more difficult to judge if you've gotten the pieces right.  Still, one can muddle through part of the way on that.

Second, how do you test it?  There is no admin side functionality for testing the RPC interfaces you enable. Isn't it a little bit mission critical to know if they work?

Third, none of the Joomla APIs appear to be very stable. Write something custom for it, and you're most  certainly guaranteed that custom code will break when you update. At least, you'll have to test it thoroughly before updating any production system that uses your code.

Fourth, debugging this stuff is one epic hack after another, just for the debug environment. I tried the PHP XMLRPC debugger and finally had to give up after being roadblocked in three completely different ways.

First, the xmlrpc feature had been left out of the "hardened" php test server.

Then the Javascript based debugger started firing off "OPTION" requests because the test server was running on the local network (The standards working group that came up with the rule of sending an OPTIONS header aught to be taken out back and stoned for that particular hack. At least, the browser should warn you it is deliberately ignoring the method of your request and pretending to be brain-dead.)

Then, when things didn't work, the debugger doesn't give you details, it just says "Didn't receive 200 OK from remote server. (send failed)". OK, um, DUH. What failed?

Well, best not to continue. Down that path lies madness.

Request for Proposal, or, Trying to Bypass Design

Consider what an RFP for a house might look like, were it to be written in the manner of an RFP for a Web site or software project:

Request For Proposal

1) Contractor shall construct one building shelter, to accommodate one (1) family including all bedrooms, a kitchen, dining room, and toilet(s).

2) All work performed must comply with industry standards.

3) Wood studs and gypsum drywall are acceptable materials for construction.

Proposals without detailed plans and estimates will not be accepted.

Do you think developers give you wildly varying proposals? Is your RFP process designed to get others to do design work for you for free? Then it masks your own lack of due diligence, and you will get every bit of design that you pay for.

Big Design Up Front is not necessary nor is it sufficient for a project's success. But you still need to take the process seriously. Such requests are a clear indication that the RFP writer is not at all serious about project success.

Personally, I think RFPs used to elicit design input without payment are unethical. The behavior is no better than asking one dentist to lay out a strategy for fixing your teeth, then paying another to follow the program without remuneration to the first.

Thursday, November 18, 2010

A Design Guideline

Use the metaphor of resources to determine consistent, implementable URL and URI patterns for your pages. Sketch your site's map. But only just sketch.  If you don't understand how this relates to your design, consider that "pages" is just a metaphor itself and the branches of site map don't necessarily mean "page". 

Lay out for substantive content first. 

Get specifications for the devices you expect to support for access to your information.  Generalize the specifications into a set of parameters characterizing a category of media, rather than device.  Create a style profile for each generalized category of media space. You might have a Desktop space, a high-definition smartphone space, a low-definition mobile space, a tablet space, etc.  Consider each profile a proxy for one of your audiences.

Define your profiles incrementally. Choose a grid or columnar layout, and flow content into place.

Follow Occam's Razor:
pluralitas non est ponenda sine necessitate 
Which is to say, don't use more markup than absolutely necessary to convey the meaning of the message. Use CSS for style. Don't use DIVs for positioning or include other gratuitous markup for layout tricks.  Don't rely upon the relative positions and parent/child relationships in the markup for style or layout effects beyond in-line layout.

Include a browser reset. That will eliminate browser-introduced pluralities. The Yahoo! UI library has one. Eric Meyer has another. There are plenty of examples.

Choose a dominant typeface family and style to fit the message, audience, medium, and purpose.  Use a san-serif font for body text, a serif font for headings. Align the sizing of both, since characters in two fonts will often differ in size. Use a font stack to specify the desired font, one or more fallback fonts, and a generic family as a stand-in. Carefully consider use of an OT/TTF or SVG Webfont with or without a foundry service like Typekit or Typotheque, or WOFF.

Choose a subordinate typeface for UI controls. Distinguish them with different colors or a different font family.

Determine word spacing, letter spacing, line spacing,

Use Em for relative sizes, but understand that one Em is equal to 100% of the font size property in effect within the context of the markup. So there is a cumulative effect of the settings.

Use proper glyphs for hyphen, en-dash, em-dash, and minus signs (I don't on my blog). Use the HTML entities for these and other special characters.  (See smartypants or typogrify.)

For text blocks and columns, use multiples of ems to set line width relative to multiples of characters. Aim for 10-15 words or 75-100 characters per line. Set line height with a unitless number so that it is based on the font size.

CSS3 may support hanging punctuation (quotes and parenthesis are hung in the margins.)

Check out,,

Wednesday, November 17, 2010

Points vs Pixels vs Percents vs Ems

There's a saying attributed to Mark Twain that one should never argue with a fool because onlookers may not be able to tell the difference. I've seen a lot of Web people arguing about accessibility, design, and typographic units, and I am forced to agree with Clemens.

I'd like to see some compelling arguments. There are none. Units are units, and whether the browsers actually do the right thing or not is quite irrelevant to the question of accessibility. A site cannot be made accessible by hacking it to coincidentally work around defects in specific browsers.

Accessibility to a building is not a property of the bricks and mortar that make it up, but an emergent condition stemming from the challenges a person faces when navigating the patterns present in the structure. We cannot design buildings to address every challenge, so instead we create building standards to guide the minimum architectural feature set.

Similarly, accessibility of a Web site is not a property of the bits, nor is it feasible to design them to address every challenge faced by users - instead we have nascent standards for building-in accessibility by proxy, as a set of architectural features.

When we build our town halls and commercial buildings to ADA standards, what we are saying is that we expect certain patterns and relationships to be exhibited in the resulting structure. What we are not saying is that the door frames were field modified to accommodate an Acme brand Model 68020 wheelchair.  Nor are we saying that the door frames were field modified because the doors were found to be constructed of defective alloys. The first case is too specific to one assistive device, and second case is clearly cause to demand a completely new set of standards-compliant doors.

Changing style sheets and muddling with markup in order to make something "accessible" for a specific set of browsers is ludicrous. It also smacks of being way too touchy-feely, relying upon subjective qualitative ideation rather than quantitative assessment.

Either we develop to standards, or we don't. Hand waving about pixels being inaccessible, points being "just for print," or percentages and ems being superior, is missing that argument entirely.  If some feature of the site doesn't work for you, to the extend it is specific to a given browser it is not an issue of accessibility but a defect in the product... and we will all be better served if we stop making accommodations to defective products.

Tuesday, November 16, 2010

I'm Enjoying Ruby on Rails and BDD

Nothing beats writing tests first with a truly integrated framework like Rails.  Steak and Jasmine make it practical, even if they have their oddities. FactoryGirl, I'm not so sure about, but once it is set up it seems to be pretty reliable.

Done correctly, things just work. Done incorrectly, especially with FactoryGirl, side-effects can really clobber you and steal precious development hours away.

The case for concrete sizing

What people have to say about "points" in Web typography. Points...
  • are a "standard method" for print typography
  • may be more legible in print, less legible on screen
  • and page resizing may not work consistently in certain browsers
  • are not relative to changes in base font-size (smallest, smaller, ... larger, largest) 
OK, so I'm seeing the real problem here: lots and lots of Web designers are mixing the metaphors of Web layout as a formatting process and Web layout as an interface specification. 

Don't do that. 

If you are going to design liquid layouts with relative sizes, by all means, go ahead and play. Your designs are going to be beautiful, but then again no design on the Web belongs to the author. A design is always the merging of the intentions of the author with the choices of the user, within the limitations of a browser. So all that pains-taking is going to look great, but we know that by design it is guaranteed to break. 

The thing is, points mean something objectively. In modern typography they have been defined to mean 1/72 of an inch. Yes, that's an English measure, the only widely used measurement system based upon human factors. Like our calendar it is entirely based upon the pragmatic considerations western civilization determined centuries ago. It is flawed and odd, but it is objective and well grounded in our experience.

So, tell me again, why do we want to measure fonts in pixels or percents, when we want our designs to be accessible to humans?

Incidentally, the argument against points on the basis that Web typography must deal with multiple device formats and layouts, is fundamentally flawed. The world of print typography has far more media formats than Web browsing devices can shake a stick at, ranging from huge to tiny, and on many different types of substrates. Points work precisely because they are an objective measure that can be directly multiplied by a unitless ratio for scaling, and thus do not need to be re-interpreted for each formatting context. 

Sunday, November 14, 2010

On the ideal of networking

Thinking about some of the finer points of the IndieConf, on the ideal strategy of choosing several people and being helpful over time with the goal of establishing numerous positive interactions, thus building trust and establishing relationships.

Don't assume that payback from that strategy is uniformly distributed. It is most definitely not.

It isn't random either.

Nor is the payback going to be from the people that seem to be the most friendly, or those for whom you've put yourself out for the most.  At least, not at the start.

What you'll find is that most people are leeches, willing to get but not to give back. Many more will undervalue anything offer that doesn't have a price attached to it. And a great number will just simply be prejudiced against something about you that has nothing to do with anything, but will prevent them from ever doing business with you.

There were some key things in this respect from the IndieConf speakers on the subject:
  1. Intentional Pursuit. They chose who to pursue, and those they chose to pursue are people around the industry in which they wish to work.
  2. Quick Selectivity. They made snap judgments to quickly eliminate disfavored prospects from their list.
  3. Overt Spying. They made lists, and profiled the people they were pursuing.
  4. Low Commitment. They did not over-invest their time, their reputations, or their other resources. 
An example of #4 is that most of them mentioned, as the "positive interaction", sending an email note with an article of potential interest to their target, once every 45 days or so. They would review a list of their prospects once or twice a week, and with them in mind glean articles from RSS feeds and the "help a reporter"  site. If they found something they'd push out a note. Very cheap, low outlay of time and no commitment, but it reminds the prospect that you are there.

Yet, people will still forget you, ignore you, or even get annoyed at you. If someone doesn't respond positively, don't obsess or fret... just move on. When you find someone who welcomes advice but never reciprocates or who actively works against you, strike them from the list and pick someone new to network with.

I've spent a lot of time pursuing connections at our local chamber, and in town, with the hope of getting business. Now I see that I've done several things wrong.
  • none of the chamber or town hall people are in fields in which I'd like to work, or express similar interests
  • my openness, tolerance, and patience have been extreme; in particular I was too slow to weed out poor connections
  • no tabs were kept on people, or other personal profiles, though I did stay in touch, and
  • the commitment of my time and emotional energy in volunteering, offering advice, and making other resources available, was substantial and interfered with me earning my keep elsewhere
There were people I admire, people I connect with, but I've been passed over twice for major business that I asked for, and on the whole it has become an un-enjoyable experience. Time to move on.

Stupid Blogger!!!!

I hate Web based applications. Always, I get fooled into spending time writing something, only to have some random keystroke navigate away from the page and into oblivion.


We need to put a stop to this crap. We use these freaking interfaces
 Why should they continue to be riddled with sucky design features. BACKSPACE causes you to lose all your writing? REALLY??????

OK, so, score one for Blogger. It saved the edit as a draft. (Insert begrudging Calvin-and-Hobbes grimace here.) It is still stupid to have backspace change the page. 

Another dump... old... from JS Camp...

 I didn't just want to leave this on my old laptop, but don't really have time to pick out the good parts, so here goes another dump...

HTML5 and JS APIs -, /pres/ncjs, /pres/ncjs/apps

Constraint Validation
- form validation
- hooked through JS
- el.willValidate, .setCustomValidity()...
- el.validity object can be probed for information
- Opera currently supports 100% automatically
- examples used the new W3C querySelector api to query the DOM; jQuery does this internally if possible
- but beware that the built-in validations may be naieve ; consider foo@cheeseburger which looks like an email but cheeseburger is not a valid top level domain
- HTML5's email regexp is deliberately broken to make it accept the crap found in the wild

Pattern based validations

regexps are part of the spec
- you can hook into onkey and set a trigger to call a function that changes the valdity properties

- 2D API for drawing bitmapped graphics
- 2.5D animated racecar example from Ajaxian
- Transformations, Compositing, Focus mgmt, Pixel Manipulation
- (painting)
- get drawing context, draw path, stroke; code looks like PostScript, or the bitblit from Win32
- higher level built-ins for common geometric shapes; strokeRect()...; or images drawImage(...), which can be manipulated through common transformations
- custom fonts loaded and drawable; some people are writing graphic editors in Canvas; bespin uses canvas text
- box shadows (which used to be in CSS3, not anymore)
- could Canvas kill "Flasturbation" ?
- "modernizer" does feature detection
- for IEn there is Google XCanvas for compatibility, using VML to emulate canvas
- Google working on a Flash replacement for XCanvas
- can save as a base64 encoded PNG or JPEG, for local storage or export
- cannot save images loaded into canvas if they were loaded across domain; pixels are tainted

- supported by iPhone, FF3(?), Opera10.5+)
- getCurrentPosition(successf, errorf, opts); watchPosition(sf,ef,opts)
- three options
- position.coords object gives detailed positioning information
- use to dump into Google Maps, get map of curr. loc
- always asks for explicit permission
- depends upon the device's means and algorithms used to determine its position; triangulation, phone gps, routers capabilities, etc

JQuery UI
Overview; draggable, droppable, drag-and-drop or revert; uses callback event triggers defined to watch events; resizeable, constrained dimention resizing; etc etc etc
- Most events should be cancellable; those which aren't are b/c of bugs
- they have a set of sample icons in their CSS framework
- autocomplete plugin; can bundle the original input along with the autocompleted value and rendered labels to avoid additional lookups
- behaviors of plugins is overridable by defining handlers for the events and returning false to block the default behavior.
- plugins generally use the static markup on the page and applies styles; button for instance can be applied to almost anything
- unsupported combobox plugin is also in the autocomplete demo
- Datepicker plugin allows i18n for calendar; also multiple calendars
- currrent discussion on-going for i18n across the entire library
- dialog plugin looks nicer, more controllable than alerts; can be applied to any element with any content; can make modal or non-modal dialogs;
- progress bar ; simple; has callback event triggered whenever value changed so listeners can pick up on status changes; animated backgrouns allowed - just use CSS and image trickery
- often features are really accomplished by using built-in style capabilities like overflow; jQuery avoids setting most CSS properties except for dimensions.
- they focus on high-value features which require considerable amount of code to implement, not on one-liners
- Position plugin coming in 1.8: relativistic positioning; !!! hot !!!; will not redraw, but if you bind to the window resize event, you can call to the positioing function again.
- "testswarm"?
- CSS stuff for JQuery done by "Filament Element"
- ARIA: jquery ui should be compliant by 2.0, partially now; with assistance from Fluid

Storage and MVC Applications
Claypool MVC framework; full app stack in JavaScript, HTML DOM
- well, sort of. Actually runs off Java app container; Jetty included
- data source can be client site via Gears or other offline api; FF, Chrome, Safari, IE8 may (modernizer.js will check); and HTML5 thing
- localStorage.setItem(id, jsonstring )
- ~.getItem(id)
- not a very formal query language, just a simple api; need to provide access methods which stringify and parse it; the model must manage the serialization of stored properties to and from strings in storage; note that changes to an array of ids via self.delete will cause reordering , so that the indexes returned in the array by this.ids() are invalidated.
- includes a debugging trace facility that need not be removed afterward
- crash and burn due to FF incompatibility with the storage api
- proxy (ruby)

Saturday, November 13, 2010

I reject you, Perl

So, I'm piddling with some tiny shell script, and decide to substitute in some perl instead.
'cause, I'm just a sucker for a language that looks like it was designed by a thousand drunken monkeys.

Well, so, anyway, I find out that this doesn't work as I'd expect:
perl -lne 'print $ARGV[0]' filename

When called with -e argument, $ARVG[0] doesn't equal the first argument to the script. Really?

It is supposed to be an array of command line arguments. Unlike every other language that uses an argv convention, Perl doesn't include the name of the command in the array, but I digress.

When you run Perl with the -e argument, it magically changes.

The rationalization for this design feature are no doubt tucked into some dusty corner of a list server, but who really cares?  It is different in a way that seems gratuitous and more than a little astonishing, so even though it was an ancient decision, it still seems rather stupid.

Everything needed could be done in shell. Anyway, other smarter and smaller languages exist. I have options.

So when I'm stupid enough to bother with a massively bloated interpreted language like Perl, and it decides to astonish me with a really poor implementation design decision and unexpected behavior, rather than blame myself and accommodate the idiocy of the language, I reject it.

Attending IndieConf

Wow, there are a lot of fat people here. I'm one of them. There must be a market to sell to here: health maintenance and improvement for independent workers!

I'm dumping notes here. Please see the conference site for links to the really good stuff.

Patrick O'Keefe - Marketing Yourself in online communities
- you can differentiate yourself much more easily than in a global space
- you get people who are self-selected as interested in a specific subject area
- those participating in online communities are much more influential in decision making, sharing advice

you have to be personable
be able to communicate well
not be resentful of authority but work well within the norms of the community
be able to not talk about yourself, post links to yourself
you need time, and keep plugging at it persistently on a scheduled basis
you should enjoy the topics of the community in which you participate
the community should allow you to fill out a profile, link to details about your business

Four categories
community of your peers, within your industry
an industry you want to reach, not your own, something specific
 - not in general, programmers
 - you can use this to stand above the rest and offer information
local business communities
 - local service businesses
small business communities

Becoming a member of the community
You have to enjoy it enough to participate for at least a half hour a week or more; if not, don't bother.
Pay attention to the guidelines and norms, and be respectful.
Fill out your profile; that is where you will get benefits; if it doesn't allow you to link to your own site, don't bother; make sure the site allows signatures and put your links there.

One of the attendees asks, how to recover from making a faux-pas in a discussion about a technical question? The answer comes back,  remember that any posts are to the entire community and will hang around potentially forever; don't get in nasty arguments but agree to disagree and decide if you want to to be a "know-everything" person.

Building a Reputation
"Do good, whatever that means for your brand."
Help people. Demonstrate knowledge by answering questions.
So that when they need your service, they will think of YOU.
Use Google to track for referrals from your signature links

Michael observes the effect of being considered a perpetual "newb" after starting by asking basic questions. How do you overcome that long term? "One idea might be to start a new profile" - not recommended - mainly because many communities consider multiple accounts as a bad thing.  Patrick doesn't think past posts will hurt in that respect, if you are continuing to participate and gain credibility.

What's the ROI of online community participation?
 - note that online conversations last for a long time, are seen by many people, and can be responded to long term
 - credibility
 - book deals
 - other peripheral benefits you could not foresee
 - association of you with a given service

"Anonymity is the enemy of a good online community... but it is not for business professionals... part of being a professional is putting your name [on what you do]...".

Patrick notes that he once bought 67 of his own book from Amazon, because it was cheaper than the publisher discount, and it pushed his ranking up to 200th place. Note: How to rank a book up on buy a few tens of copies of it.

Mital Patel - Legal issues -
(Mital is using, looks really neat.)

- leaping in; employment issues; noncompetition/non-solicitation agreements; intellectual property

Which form of business? Sole proprietorship, LLC, S Corp, C Corp; (need operating agreement articles of incorporation, bylaws, meeting minutes, EIN)
Tax differences: LLC is simpler to operate from a paperwork perspective, but there are differences in how taxes are done.

 - Payment terms: Retainer, Net 30 or Net 60; best to ask for a deposit for some fraction of the work; you will save yourself a hassle if client cash flow gets tight later.
 - Representations and warranties: underpromise, overdeliver
 - Subcontractors: employee vs independent contractor; always use "independent contractor" if that's what they are; don't use "1099 employee" too lightly.
 - Indemnification: limit your liabilities if things go wrong; guard yourself against what could happen if client provides incorrect data or misuses the software;
 - Choice of law; specify your home locale to use the "home court advantage".
 - IP: selling vs licensing; selling means the client owns everything and can bring someone else in to work on the software as a competitor to you; licensing indicates your client has terms to use it, but you may have the ultimate rights to it. Suggestion that licensing is the often the most advantageous model.
- Make sure IP is spelled out; the law doesn't say by default who owns code. Commonlaw copyright gives the author rights; you need to make sure those things are spelled out.

A question comes up about the enforceability of IP ownership agreements regarding work and product done in your own time/resources. The answer comes back, it depends on the state and agreement.

Forms of IP law
Copyright: written expression; "work for hire"; Photographer automatically owns the copyright; use the words "Work for Hire" and assure the copyright is assigned to you.
Trademarks: Name and brand symbols for your business; domain name alone is not a trademark use;  "likelihood of confusion" test; check state trademark registries; Also at federal: A commercial search will cost a few hundred dollars.
Patents: not as common for independent developers and designers
Nondisclosure Agreements (NDAs): avoid giving away your business model; venture capitalists and angel investors will get offended by them; hard to enforce but often having them in place keeps people in line.

Growing: hire slowly, fire fast, and use solid employee agreements: non-competition, non-solicitation; don't want employees jumping ship and taking your clients.

Brandon Eley - Effective Networking for Independent Contractors

"Networking gets a bad rep"
- Introversion is no excuse; people will attend conferences and not mix socially with people.
- Freelancers may consider networking events to be too time consuming.

His mom kept 3 ring profile binders on each customer, detailing every aspect of their lives; she'd use these to find customers to market to personally and proactively.

His initial network: calling parent's friends, relatives, and worked from there word of mouth.
Prerequisite: you need to maintain relationships with people, and keep up with them over years. Build relationships.

Basic principles
 -"emotional bank account" for each person you meet; you need to make deposits by helping them in some way; Goal in attending events should be to walk out with a new relationship.
- give first; at least five substantial times before you expect results from them and build trust
- give often; and consistently; pass on leads
- don't try to connect with everyone; people max out at about 200 people they can keep up with on a regular basis; look for the people you have common interest; invest your time in those that are really promising

Online communities
 - LinkedIn; puts everything he does professionally on his public profile; links to those he feels worth networking with; asks those who comment on his presentations to give referrals;
 - Facebook; a social networking antipattern; uses it only for personal social interactions, semi-privately; but you cannot rely upon it being private. Be Extremely Careful.
Pepper O. points out that for a female small business owner, not having a Facebook page is a serious omission.
 - pick niche communities related to topics that your intended customer base will want; forums; where are your perfect customers visiting?  Plaxo has many small executives; inside919 has many small businesses;

Offline communities
- Pick where to go; don't go to places you won't get valuable contacts or run by a referral group; target places with specific topics; ;, regional conferences;
- look to get 10 connections and try to keep up connections with those people over time
- go into a conference with a friend, someone who knows different people than you, and introduce each other
- don't "pitch" your stuff; ask and listen more than you talk
- don't be a business card ninja; only keep cards if someone wants to keep in touch; it is just annoying
- AVOID referral groups, as if your life depended on it; you need to build relationships instead
- don't hang around with your nose in a phone or a laptop; put the smartphone away when you're in the hallway; talk to people; smartphone as a pacifier.
- FOLLOW UP. Number one thing he expects is that 95% of the people will never contact him. The only thing worse is people who spam him before he gets back from the conference; like monthly newsletters
- DO NOT SPAM. that's like overdrawing your account

Keeping in touch to build a long term relationship
- Connect > Followup > Provide Value > Keep in touch
- Sends hand-printed note on a card to people;
  - carries a space pen to write on glossy business card to jot down how he met a person;
  - just write a few words to trigger
  - Sends an email as an alternative; if you don't have the address or it is not quite appropriate to send a card
- Follow up: (mentioned sending a client note at a rate of 4 articles over 6 months) works with a pool of about 10 people and scans feeds about once or twice a week to see if there is anything of interest to someone in that pool; might also use a CRM system and tag the prospect with their interests;
- Provide value:
  - see articles written in their industry, send them on with a quick personal note;
  - maintain practice over a period of time; send consistently
  - "" - sends out notes periodically on different industries; send to clients; copy and paste a link
- After you have established a relationship, ask for business; call up and ask to talk over coffee; ask if you can show them what you have to offer; ask for leads

Use Software to leverage and extend your memory
Uses "Highrise" CRM; keeps track of profiles by bcc of any email you send to the client;
Zoho and SugarCRM are more advanced.

 Stop looking at yourself as a salesperson, and look at it as building a relationship with people.



Doug Foster: Convince ME!

Think like the buyer. Don't think like a seller.
- Ask yourself, "Why should I buy what you are selling?"
- WII-FM: What's In It For Me? Make you Money? Save you money? A need or a want? Leverage? Security? Why are you looking at it?

As a buyer, I expect you to know
- My industry; My business; My pain

How do you sell? A process:  -> Foster-> Find -> Educate -> Close ->
Closing is really just asking for the business. Don't be afraid to ask.

 - Talk; whenever you get the opportunity, share what you do,
 - Hang Out at watering holes, meetups,
 - Network ; check out Triangle interactive marketing association TIMA
 - Subscribe: RSS, MailChimp
 - Get social

Educate. Once you have a prospect, take them on a trip: tell your story; show proof; try it; satisfy completely

 - deciding is logical but buying is emotional
 - "I" will convince me;
 - No buyer's remorse; don't badger and box the prospect in to buying something they don't want. You don't want the client to feel like they had no choice.

(Show's Johnson Automotive Badger commercial as an anti-pattern.)

 - Ask a lot of questions after you complete the deal
 - Listen to the answers completely
 - FYI - send out notes every now and then to remind prospect that you are thinking of their needs, something that is of value to them
 - Deliver and manage expectations; get the cycle down to do less selling and do more delivery
 - Fix; don't be afraid to admit when things go wrong and jump onto a fix for it.

Plan the Trip
- "If you don't know where you're going, you're going to wind up somewhere else" - Yogi Bera
- Know Me, Know my story, Know my backstory
- Who/What/When/Where/How/Why/How much
- Ask, "Why should I make this trip" metaphorically. What will I see? Do you know my points of interest, and will we pass them along the way? Who else is along for the ride?
- I only have so much money and time.
- Are we going down the street or around the world? Are we there yet?

Tell the story
- Scenarios; a way to predict possible alternate outcomes; "The Art of the Long View" by Peter Schwartz; how might the sale go?
 - Plan alternate routes for roadblocks and shortcuts... if they say "go", then close and move on
- Short Stories that Sell; innately, we love flawed characters;
- Our brains are wired for stories (and pictures)
- "The back of the napkin" Dan Roam; brain wired to process at different levels who/what, how much, where, when, how, why

What works better, on the phone or face to face? If you know the person, phone is fine; otherwise if you can get a face to face meeting jump at the chance. You can't beat a face to face.

- I want to know "your" story as a buyer. It should be unlike anyone else's story.
  - Your story aught to overlap, so it becomes (y)our story.
  - Fit the story to the location and situation.

Speaker says "My story is, 'I help people sell'"
A good story:
 - invokes emotion
 - memorable
 - length, width, depth
 - truthful - what is just an idea? what works now?
Goal is to start a conversation, threaded with other stories; nobody likes a monolog.

7 layers of how to tell a story (The OSI model)
Application Purpose, conversation
Session Media, audio, video
Transport Delivery: best effort or guaranteed?

(Bank of America story, 160k IP phones in 10 minutes)

Show proof: why should I believe you?
- buyer may be smarter than you
- be honest; assume you are the dumbest person in the room
- build trust with repeated truth telling
(speaker going too fast here)
- demonstrate
- pull out a success story; 1st hand best; 2nd hand good; make it viral

- if seeing is believing, trying is buying
- make it an engaging experience; make it real; make it a WOW
Dance or watch, watch or try
- "Good" a crowd experience of a random gathering
- "Better" a community of interest experiencing, concert or conference
- "Best" a personal experience

- Questions are good; good conversations have questions, even tough ones
- it is the start of a conversation;
- Concerns are a great thing
- where can buyer go to learn more?
Ask me, listen to me, respond to me directly

Only 2 questions count for buyers: did I buy? Would I buy again?
What if the buyer is not satisfied? Some people are never satisfied.

A customer that is satisfied and remorseless, will be your best seller.
- Slides are up on slideshare.

Rebecca Murphy - Git and Tickets
"tools for getting better paying work"
"tools for getting better customers"

"I can't work without them anymore"

(complicated email thread with two or more tasks emerging from it)
- had learned to tolerate terribleness and accept whatever was thrown
- morass of emails, downloads, labeling, everything mixed up in the inbox

(describes clumsy process using zip files and many overwritten files, no ticketing system until late in the process, and no version control)

Lesson learned:
- email is evil: a ticketing system brings sanity to client requests
- mentions "assembla" as a ticketing system
- no context switching is required when using the ticketing system; whereas emails presents very many distracting emails vying for attention; narrowly focused to one client needs
- you can assign priorities to tickets (* but: some clients think everything is high priority)
- you can propose a new status, and requires sign-off by a client
- you can assign tickets to a client, and you can see where bottlenecks are
- you can see who might be overloaded with tasks
- can be integrated with GIT/Mercurial/SVN
- email based entry

"I really don't like working remotely anymore, at least with a team of developers; I want to be able to show a client -- I'm done with my stuff"

"Ticketing systems are not rocket science"

Version control is non-negotiable
- either the client needs to set it up or set one up yourself
- server is not necessary for setting it up
(* important to note - .git lives under the directory, so a remote repository is the best way to protect the source from a "rm -rf")

"Learn to use the freakin' command-line"

- you can see what you just changed before pushing it!

- you've basically made a snapshot
- you can undo the change
- you can combine two commits into a single commit, reorder commits
- we have a snapshot that we can roll back to
- replay the history of what you did
- use the tool to get the changes up to the server

git tag -a v1.3
- tags with a version label, so you can do
git checkout v1.3
- or rapidly roll back
git checkout v1.2

"I will not FTP anymore, because this is how it should work."

git bisect start
git bisect good v1.2
- marks v1.2 as a good snapshot
git bisect bad master
- mark the current code as bad in some way
- work through commits to check; mark each either good or bad until you get to the commit that broke
- identify the change that broke the system

git branch (* IMHO, branches are evil)
- work on your new feature and commit as normal but commits will not touch the "master"
- work on experimental changes without breaking the stable code
- pull master back into branch
"The most amazingly trivial thing to do... you'll start to do it for little things, because it is so easy"

git-add --patch
- select which of your changes to add
git-commit -v
- see your diff when writing your commit message
git stash/ stash pop
- kind of like a mini branch
git rebase -i master~10
- edit (!) the last 10 commits

"Having the power to do this sort of stuff in your day to day work is wonderful"

GUI Tools
- gitx (doesn't recommend it for doing the command line stuff)

How to get clients to do this stuff
1) Fire bad clients. Srsly.
Tell them up front that you require Git/SVN, Net 30 terms, a ticketing system or project management system, access to a hosted dev environment or setup on local machine
2) Do it without their permission or involvement
3) Use Github, follow instructions; setup ssh keys; find a project and clone it.
4) Use a ticketing system like assembla; there are lots of other options

Links on , /t:workflow/

Matthew Bass - Homesteading for freelancers

"Not the construction kind... the kind you do with software"

- hated being tied down all day in corporate work
- as a freelancer, you have time flexibility but you are still tied down
- as freelancers, you fall under the "self employed" category; but there is an advantage to being a business owner, to build products that people pay for;
- stop trading time for money and start diversifying your sources of income

How-To of Building Your Own Product - what's worked for me

Setting Goals can be challenging
- some people set no goals
- some people set goals but they are the same as everyone else's goals
  - "College" expectation and earn a degree: what he found was that the degree didn't really help him.
- we want to set goals unique to our circumstances and talents, and where we feel we are being led, not because everyone else is doing it

Homesteading (re: Nathaniel Talbot)
- self-sufficiency and creating thinking
- may be out in the middle of nowhere,  isolated, alone;
- starting from very little and building it from there
- everyone else expects venture funding, too lofty goals
  - small initial investment, get small amount of income

"You gain strength, courage, and confidence by every experience in which you really stop to look fear in the face... Do the thing you think you cannot do."
- Eleanor Roosevelt

 - and various other philosophical questions
 - problem to be solved: how do home-schoolers get a transcript to present to colleges?
 - proposed solution: a web service for home-school families to get a PDF

"Getting Real" - free online book by 37signals
- Build less
- Stay lean
- Manage debt

Minimal viable product
 - be very careful only to put in necessary features
 - keep "to do" comments and unfleshed out tests to a minimum; set a threshold to avoid technical debts

Release features immediately, get feedback immediately, better motivation to keep working on the product

Catch an idea
- find a target niche

  - Teascript has 5600 subscribers already, despite the crudeness of the interface; there simply aren't any Web based alternatives out there. It is a true niche application so the bar is a little lower.
  - People saw the app and that it worked well, and stuck with it

- pick something easy
 - creating a single PDF was not a hard thing to do; a full-blown planner would have been much more difficult
- solve ONE problem

Taking off
- scope out the competition
- create a skeleton app
- post a tease page with a form
  - you can collect emails of people interested in beta testing the app
  - got over a 50% participation of initial beta tester
- Be selective with what feedback you get from your customers
  - file away features for reference
  - people will use an app even if you don't think it has all the features you think it should have had

Build what they need
- beta testing
- be willing to change

Build what you need
- dashboard / charts
- automation
- watch how people are using the system
- private schools started using the service; totally unexpected b/c pricing structure is oriented toward families, not toward schools
- built an admin back-end to view users, stats, export data
- certain things got to be a drain on his time, managing it; automation helped eliminate that

When to stop
- minimal viable product
- don't get sidetracked
- we are never truly "done"

- VPS vs shared
- Original apache proxying Mongrel
"Like, I just want to build applications."
- now running on Phusion Passenger
- Capistrano, baby! (Definitely recommended; can be used with PHP or anything else...)
- shared hosting had issues; migrated to Slicehost but then we had to do everything from scratch
  - it was painful, but worth it
  - lasted for years

- email / blogging
- let other "spam" for you
- speaking for fun and profit, to your audience
- Google AdWords (generating steady traffic for about $30/month, perhaps b/c it is a niche application)
- didn't like doing marketing, but it didn't sell itself;
- but a good idea and implementation will be spread by those who like it
- Speaking can be scary -- very scary -- but it can be worth it ; check out toastmasters
"Speaking can give you some leverage."

- a/b testing
- customer development
- strategic alliances
- "Everyone in the crowd knew what it was but no one was actually doing it"
- about a/b testing for rails developers: "Vanity" gem for ruby on rails developers
  - statistically prove that users do or don't like it;
  - present two different forms and feeds them at random, and measures the success rate
  - you get a page showing which one converted more users
    - screencast got 9% more results; longer form got 16% more results!
- there is already an "organizer" product, which he could explore alliance with, cross-registering users, etc

- the FAQ; direct people to the FAQ before it happens
- timely replies; people appreciate it; they appreciate that you care and are frustrated otherwise
  - always tries to respond in 24 hours if not sooner
- refunds?
  - maintains a pretty liberal policy on refunds if there is a bug he can't fix or feature he can't implement
- seen some really stupid stuff; add questions to the FAQ otherwise

The buck starts here
- payment systems
  - checks, credit card payment gateway;
- subscription based vs one-time
  - accepting credit cards is often the most challenging piece
  - had paypal, but wasn't very good
  - uses Spreedly now with paypal as the merchant account (Spreedly Nathanial Talbot's api for accessing gateways and auto-renewal, refunds, etc; Spreedly charges a percentage off each transaction.)
 - monetizing using adds was just not worth the time
 - switched to a monthly model; may switch to a fee to print the transcript; used to have a yearly fee instead;
- tracking expenses

Incorporated as an S-Corp; "Adeptware".

Set some goals; stake out some land; work, work, rest; relax - it's only ones and zeros!
"If you are building for a niche and it has value, then people should be willing to pay for it."

(* note that at the base rate, it is about $28k of income if everyone was a paying customer).
Read More

Conference Wrap-up

Sign up to to keep up with what is going on.

Raffle give away
1) Carrboro co-working 1 month givaway
2) 2 weeks office space at DesignBox
3) two more "Money" books
4) Pearson Vue Books

Wow. Loved the conference Michael!

Thursday, November 11, 2010

Accessibility as a subjective experience

Listening to a British intro to an accessibility standard, words such as "might" and "could" sprinkle the narrative. So much so, that one wonders whether or not people realize just how much verbal hand-waving they are doing.

The video is here on YouTube.

Do you want accessibility? Then set up objective tests with a real, live testing framework. Don't rely upon the subjective ideations of a Web Designer.

No design process can serve every audience equally well at the moment a site is released, let alone as it degrades over time. An incremental regression testing process is the only way to practically achieve and maintain accessibility over time.

Wednesday, November 3, 2010

Web Technology Needs to be Rebooted

I'm working on a little drawing applet, and try to put what should be some simple things into it.

First, I use :before and :after generated text content styles:

#text_xy_anchor::before { content: "(";} /* doesn't work !!! */
#text_xy_anchor::after { content: ")"; } /* doesn't work !!! */

I'm working in Chrome, and yes, I tried the original CSS2 syntax too. Neither works to put the generated content around the text input "text_xy_anchor".

Next, I added an "aside" next to a "section", the latter of which contains the canvas I've been working with. Now the canvas points are all offset.

Sigh. The problem with Web Browser based technologies is that so many shortcuts were taken over the years that EVERYTHING in the browser is about working around the side-effects.

A test case for this can be found here.

Tuesday, November 2, 2010

That is why you fail.

I recently picked up the 3rd edition of "Web Style Guide: Basic Design Principles for Creating Web Sites," and noticed a glaring omission right in the second paragraph of chapter 1.

For the benefit of the non-technical lay person, the paragraph follows, along with my suggested addition:

Planning a web ite is a two-part [change to] three-part process: first you gather your development team, analyze your needs and goals, and work through the development process outlined here to refine your plans. Next, you create a project charter document that details what you intend to do and why, what technology and content you'll need, how long the process will take, what you will spend to do it, and how you will assess the results of your efforts. The project charter document is crucial to creating a successful site: it is both the blueprint for your process and the touchstone you'll use to keep the project focused on the agreed-on goals and deliverables. [additions follow] Finally you realize with a sickening feeling that you will have to cancel the project. Having burned over twice the budget initially allocated without having created anything of substance, your development team will spit and curse you for wasting their time in meetings just to produce a vague and misleading document that no one will ever read again.

I don't believe it. - Apprentice Luke Skywalker
That is why you fail. - Jedi Master Yoda

Monday, November 1, 2010

HTML Semantics are Meaningless

There is a metaphor used by developers to convey when they intuit that something is seriously wrong with the manner in which a bit of code is written:

This Code Smells Bad

I'm coding up a small application page in HTML5, and trying to figure out the best way to express what it is I mean, directly. You just can't do that in HTML.

I'm quite appalled by the fact that Web designers have accepted a language that forces them to speak in baby talk, backwards speak, and utter gibberish in a vain attempt to convey what they mean.

Let's face it: HTML5 doesn't even come close to allowing you to directly express what you mean.

Those who are ignorant of history are doomed to repeat it. Web developers, hardly the least ignorant demographic in the world, regularly posit multiple pluralities by overloading tag names, imposing second-order classifications via class attributes, and making gratuitous inferences from arbitrary structural relationships.

We find horrid examples of such ignorance that predates the Web: PostScript's Document Structuring Comments; the (ab)use of special characters in Perl; the intractable admixture of formatting instructions and content structure in any TeX based file.

Today, we have leading designers telling us to use ordered lists for navigational menus, promiscuously overused DIV tags instead of tables, and rampant use of interacting side-effects in the CSS based HTML formatting to make up for huge gaps in expressiveness.

The thing people just don't get is that markup is not about the most ephemeral aspects of document layout, but about conveying the most enduring meaning of the content. HTML fell into the formatting-first hole from the very start, and just keeps digging the ditch deeper with every version.

Our documents should say what we mean, and mean what we say, no more, no less, without gratuitous markup. If HTML5 still doesn't accomplish that role of a markup language, why bother with it at all?

Let's jettison the straw-man markup syntax altogether and adopt a CSS3 based formatting semantic model for generalized markup. If I can say that a SECTION acts like a TABLE-CELL, then it makes sense to say that my drawing-surface is a CANVAS.