Friday, December 26, 2008

Reboot America

You know what the trouble is? We used to make shit in this country, build shit. Now we just put our hand in the next guy's pocket..

Bottom line is the only thing that produces real wealth anymore is investing in science and engineering that will create new technologies that improve real people's lives. Anything else is an economic dead-end.

I fear for a world that neglects investing in the education of its populace in favor of vacuous diversions and populist short term public policies.

Thursday, December 25, 2008

How to construct a healthy diet

Eat food. Or how the gaming of nutrient intake, through misguided politics, science, and commercialism, is making us unhealthy.

Wednesday, December 24, 2008

6kg Bonito


Thursday, December 18, 2008

Saturday, December 13, 2008

Tuesday, December 2, 2008

Sunday, November 23, 2008

Working Girl

Just another day behind the scenes at the photo shoot.







Thursday, November 20, 2008

Graphical Evidence of the Evil of Gay Marriage

Oh GEAR DOD, noes!!1eleventy

Please do not offer my god a peanut.

Thank you and come again.

Tuesday, November 4, 2008

Postcards from the North Pole

I thought I'd update with some pictures from Oulu that I took on a Saturday stroll after the first snow of the year last week.










Tuesday, October 28, 2008

Thursday, October 23, 2008

Teh funnay

What excuse do those voting McCain/Palin make?

Saturday, October 11, 2008

A voice from history

An apology from a nation ruined by corrupt banking practices.

Friday, September 19, 2008

"Left" and "Right"

Interesting to see research shedding light on something I have considered from an intuitive point of view before.

"Their research, published in the journal Science, indicates that people who are sensitive to fear or threat are likely to support a right wing agenda.

Those who perceived less danger in a series of images and sounds were more inclined to support liberal policies.
" --

Monday, September 15, 2008

Get the ____ out you' throat and go vote.

If you are bored and disgusted by politics and don't bother to vote, you are in effect voting for the entrenched Establishments of the two major parties, who please rest assured are not dumb, and who are keenly aware that it is in their interests to keep you disgusted and bored and cynical and to give you every possible reason to stay at home doing one-hitters and watching MTV on primary day. By all means stay home if you want, but don't bullshit yourself that you're not voting. In reality, there is no such thing as not voting: you either vote by voting, or you vote by staying home and tacitly doubling the value of some Diehard's vote. --

Tuesday, September 9, 2008

Happy Birthday L.

This should have been posted yesterday, but I spent all of yesterday playing with L. Her party is booked tomorrow with cake and everything.



Try to ignore the fool behind the camera.

Thursday, August 28, 2008

Distributed Identity in Virtual Worlds

Thinking about managing identity across various distributed grids of virtual worlds, I am of course drawn immediately to OpenID as the current preeminent solution to that problem. Let me explain the problem a little bit, and discuss how OpenID might fit in.

The Problem


VWs suffer from the same problem as website with regard to multiple sign-on. However due to the central role Identity makes in VWs, the problem is much magnified in its implications. Having single identities for each website you visit is merely a clerical annoyance -- remembering each user name and password -- and one that can be quite acceptably fixed with a smart enough user agent keeping track of each password, as Firefox now does.

However in a VW, having a new Identity for each grid of VW means having to recreate yourself each time you change worlds. You have to redesign your avatar appearance, rebuild your inventory, rebuild your social network, etc. An unacceptably large burden that turns the "metaverse" into a series of "walled gardens".

What we need is a means of

  1. asserting a unique identity agreed to by all observers
  2. mapping of that identity to a common specification for appearance, inventory, etc.


For this post, we will only be considering how to enable item 1.

Thinking about solutions

The obvious means of asserting identity, at least for those of us who have followed any cryptographic developments within the past decade, is for the user agent in question to generate a asymmetric key pair, and use it to pass to the VW a digital signature.

However as we well know, an endpoint directly asserting a signature without a public third-party is vulnerable to a man-in-the-middle attack. However if there was a public third party from which he could receive your public key, then that could be avoided (so long as the third party is actually publicly trusted).

Also, the tools for generating, maintaining, and using an asymmetric key set are far from ubiquitous and user friendly. If we really want it to be something that everyone can agree on and use, is has to be practicable for the average computer user. If we wanted to use PKI directly, we would have to create a standard protocol for use in VWs, write a standard implementation, then convince everyone to use it. Otherwise we'd have nothing more than cryptographically secure walled gardens.

The simplest way to take the burden off the end-user from maintaining his own identity is to outsource it a third party as much as possible. Also we can increase the odds that various VWs might standardize on something third party.

An interesting security property of having a 3-way negotiation, is that if any one party feels that they might be being lied to by one other party, they can always verify with the third. So it takes two parties collaborating with each other to create a deception.

With special consideration towards having a protocol that could be standardized on, and already has existing implementations, we look at OpenID to see how it measures up to our criteria, and what flaws it possesses.

OpenID Protocol

I recommend you read for yourself here and here, however I will provide a brief overview of how it works.

Let us define:

User Agent: The end user's Web browser, which we will denote AliceFox.

Relying Party: A Web application that wants proof that the end user controls an Identifier, which we will denote BobBlog.

OpenID Provider: An OpenID Authentication server on which a Relying Party relies for an assertion of identity, which we will call CarolCert.

Identity: A URI that represents an identity that AliceFox will assert, and and CarolCert will corroborate. Notice that this identity is "for" AliceFox, but cannot exist outside the context of CarolCert. The two are inextricably tied. We will denote AliceFox's identity with CarolCert as alice.carolcert.com.

Protocol:

AliceFox (A) wishes to assert her identity alice.carolcert.com (I) to BobBlog.com/comment.cgi (B) for the purpose of submitting a comment under that identity. She POSTs I to B through the comment form.

B GETs the URL I, which includes a "link" tag which points to carolcert.com/id.cgi (C). B redirects A to C, passing a "return to" parameter (R) and nonce (N) to C as GET parameters.

A and C confer amongst themselves is a manner undefined by the protocol in order to verify that A is in fact the entity known as I.

When C is satisfied of this fact, it prepares a reply to B by creating a secret key (K), a "handle" (H) that publicly identifies that secret key, and signs certain fields to ensure detection of tampering (S). C redirects A back to B with H and S attached as GET parameters.

If B carries state, B can negotiate (out of band??) the exchange of K with C using Diffie-Hellman key exchange, and use K to verify S.

If B is stateless, he merely echos A's message back to C to verify that A did not tamper with it en-route.

When B or C verifies S, B considers the identity successfully asserted, and associates A with I for the duration of the session.

What does OpenID Give

With that understanding in mind, what can we say about A and B, and what does I really mean to them?

It's important to point this out: all OpenID says from B's perspective is "A is an entity known to C as I". The delimiting context here is important to understand. A could have any multiple of identities with C, or any other OpenID provider. Moreover C could be anyone at all, even an untrustworthy party. OpenID says nothing about trust.

However, it is easy to create a trust-based system if one was to white list OpenID providers based on public reputation. It's certainly trivial to create a black list of known untrustworthy providers. This is certainly enough for our purposes as a distributed VW authentication system.

That said OpenID gives us much more. As we said above, its not hard to create our own simpler (and probably more secure) protocol. However that would entail writing an implementation, drafting a standard, ensuring it was practically deployable in working systems, and building critical mass for its adoption by all VW players. OpenID lets us skip that work, because its done already for us, and get straight to solving our own domain specific problems.

What does OpenID not Give

There is a well-known flaw in OpenID that can be used for phishing. If B is malicious, he can redirect A to his own copy-cat OpenID provider C', and if the user doesn't notice, C' can possibly steal A's credentials and allow a malicious party A' to impersonate A.

There are other means of misdirection as well. While a computer would always be able to tell that I and I' are different identities, humans might be confused if A and C are sufficiently similar looking to A' and C'.

The only solution to this is to white list known providers.

Another known problem with OpenID is the common reliance on passwords as a means of validating A with C. While that is no different from the password schemes currently in use on VWs or websites, I am sure a digital signature based protocol would be vastly superior from a technical standpoint.

My humble alternative protocol

Often the best way to judge a design is to consider how you would do it yourself, if you were tasked with making an alternative. I am happy to say that while what I started out with was quite different from OpenID, as I improved my protocol, I noticed that my decisions became more and more like those taken by OpenID, which is a good sign.

Warning: I am neither a security nor web expert, nor do I claim to be. Be gentle with your corrections.

This design also relies on cookies from one site being inaccessible from another. I have no idea how true this is in practice.

When A registers an identity I with C, A downloads an implementation of an asymmetric cipher in JavaScript that writes the private key K in a cookie, and the public key P in C's database.

A asserts identity I to B. Like OpenID, this is a URL that ties A to C, such as alice.carol.com.

Like OpenID, I contains a link to C, which B redirects A to, sending a return-to R and nonce N as GET parameters. Unlike OpenID, I also contains a link to P, which B downloads and associates with N.

C delivers to A a JavaScript program which opens K, encrypts N into a digital signature DS, then creates a message signature S to detect tampering. C then redirects A back to B, with N, DS, and S as GET parameters.

B verifies S, uses P to decrypt DS and verify it is the same as N. If so, B considers I successfully asserted.

Essentially C is nothing more than a repository for 1) public keys, 2) trusted JavaScript implementation of cryptographic algorithms.

Thoughts?

Thursday, August 21, 2008

Disruptive Products, or Disruptive Technology doesn't apply to Software

Disruptive Technology

For a long time I've heard people use the phrase "Disruptive Technology" in conjunction with one idea or another, as if the invocation of the phrase was supposed lend some weight to the discussion I never quite fathomed. The people who tended to use the phrase also tended to be the sort of people who often used those kind of phrases in such a manner as to render them meaningless, so I never really paid much attention to exactly what it was that they meant -- because strangely enough, it turned out that whether declared "disruptive" or not, it made no difference as far as I could tell!

I've heard half-coherent explanations of the phrase, but I always took it to mean "technology that makes managers and business-types no longer understand how to make money", which I thought was nothing special considering I assume that most business types don't understand technology anyways, and their understanding of how to make money with it was always suspect in the first place.

However after Clayton Christensen's "The Innovators Dilemma" made its way to the bookshelf at work, I thought I would see just what it was I was missing the whole time. Turns out there is far more to the idea than the throngs of excessive catch-phrase users would imply.

Firstly, I object to the use of the phrase "Disruptive Technology", since that implies to me there is something inherent in the engineering or science that causes a technology to become "disruptive", which is just not the case. The things labeled disruptive technologies often have traits in common, but those traits are really all about how a market perceives them, and have nothing to do with technology itself. I prefer "Disruptive Products", because that captures the fact that this is a book about Business Management, not Engineering. The idea of "disruptive technology" as presented by Christensen cannot be separated from the fact that is is a product destined to be sold on a market.

I recommend you read the entire book yourself, because there are lots of noteworthy ideas for anyone interested the business of technology, but I will give a brief summary of the major themes as I saw them herein.

The author uses his extensive research into a collection of industries where certain technological innovations happened, which he characterizes as either "sustaining" or "disruptive", and how the affected the health of the businesses in that industry.

A Sustaining Technology is one where the market for the products made with the technology is well known, and the firm in question can use the technology to increase its profit margin by adding new features which increase the products performance in the market.

Higher profit margins mean the company can further grow, and invest that growth in tuning the entire operation of the firm to servicing the high-margin market. In many ways the firm becomes captive to its high-margin customers, because failing to invest in sustaining the growth in performance of the products, as its existing customers demand, will cause it to hamper its own growth in profit, and lose market position. The author notes that a firm's quest for continued growth, forces it to "trend upward" from the low-end low-margin area of the market, to the high-end high-margin, and that trend is essentially inevitable if a firm wants to satisfy its investors.

Disruptive Technology
is one where there the technology has no proven market at the time of development, but eventually will develop a market outside the expectation of its developers.

That in and of itself is hardly surprising. The interesting thing about the book is that Christensen does his research, and finds there is a historical trend in disruptive technologies, that if known, can help businesses manage and succeed in turning disruptive technologies into profitable, and often industry changing, products.

He discovered that DTs have common traits, and the following traits serve as a definition of a DT

  • DT often appear as an innovation stemming from an existing industry.
  • DT provide value in areas that the current market places no value in. Historically this means they are low-performing and low-cost, but provide benefits such as reduced size, or improved flexibility.
  • DT, due their perceived lack of value in the existing market, begin their life as a product by taking the low end of the market, left under served as established firms climb to the high-end in pursuit of growth.
  • Existing firms are completely unable to capitalize on DTs because their high-end cost structure means they cannot grow with low margins, and thus development of DT into products for the emerging market is left entirely to small firms.
  • DT improve in performance in traditional metrics over time, as well as retaining the benefits that gave it access to its first emerging market, and thus begins to move into the high-end and cannibalize the previous market (for which it initially appeared ill-suited), and the existing firms, caught flat footed, find them selves in serious trouble.

To make that more concrete, the classic example used throughout the book is the hard drive industry. The story there is
  1. market demands higher capacity and speed for their existing computers, which existing well-managed firms deliver, and thus grow and move upscale
  2. someone develops a smaller form factor drive, with dramatically reduced capacity, and the existing market soundly rejects is as unsuitable for their needs
  3. new markets emerge for smaller computers (mainframe -> minicomputer -> pc -> notebook -> appliance (ipod, car-navi)), which find the smaller form factor indispensable
  4. density on the small form factor drives increase to the point where it cannibalizes the market for large high-margin drives, and the once small companies who were able to market the small drives grow larger and displace the incumbents
  5. repeat (14 -> 8 -> 5.25 -> 3.5 -> 2.5 -> 1.8 etc inch drives)

Disruptive Products

However while reading the book, I kept trying to see how the concepts there applied to what I was doing, which is programming in the software industry. I couldn't help but come to believe that this analysis was a little bit dated, being published in 1997, and only seemed to apply hardware products.

Hardware products have a easily quantifiable manufacturing and distribution costs, and thus have a clear relationship between price and profit. That is expensive hardware is expensive because the physical bits involved in making it are expensive, and the overhead of moving those bits to market is expensive.

Software however, has no fixed costs except programmer salary (among which programmer talent and pay can vary widely), and some minor managerial overhead. For a shrink wrapped software product, you could charge $1000 one day and $1 the next, and it would cost you nothing but your profit margin to do.

And here is the controversial point coming up:

I don't believe that, ultimately, software is really a product at all. It's a service. The days of being able to hand over an application in exchange for $X will soon be gone for good.

Ultimately, there will be two models for commerce in the software industry:
1. Custom whole application development
2. Customization of existing open source solutions to emerging, specific, business needs

Although the first case you might assume that since there is an integrated deliverable, you might consider it a "product", I would assert that what the developer is being paid for is to solve a problem, and so the compensation is proportional to the problem, not to the cost of manufacturing the good.

I foresee that so long as there exist new and different niche businesses, there will always be a demand for new and niche software; things not complete serviced by any pre-existing software package, and have to be built from scratch.

The second case makes a lot of assumptions in excluding proprietary software from the picture. Let me try to follow the history of open source in the software industry, and use that to justify my extrapolation.

  • Most open source projects are born out of existing industries, either because the a firm needed some software for its core business, and found that once completed it was valueless to keep it secret, or because engineers trained in an industry felt like putting their skills to use outside of a corporate setting.
  • Open source solutions at first held no value for anyone outside hobbyist and hackers. It was hard to use, poorly supported, and lacking important features. However the one value proposition it did provide, access to the source code, gave it flexibility that made it absolutely indispensable for certain applications such as research or highly customized niche applications, where the code would have to be heavily modified, but there was no justification for starting entirely from scratch.
  • Due to the perceived inappropriateness of open source for business or personal use, open source use often started out as skunkworks style projects running under the radar of management, in small low-end roles where other existing solutions were inappropriate.
  • Existing firms software firms, Apple, MS, Adobe, etc, at first treated open source with derision, then fear, and tried to ignore it for the longest time, because their dependence on high-margin software sales could never allow it to move downscale and compete with something that was free. It would be corporate suicide. This allowed smaller shops to capitalize on the commercialization of open source.
  • While at first constrained to only the low end, open source has been on a trend of steadily increasing quality over time, and is now at the point where MacOS has significant open source portions, Adobe is open sourcing the basis for its strategic Flash platform, and Linux is seen as a credible alternative for Windows on low end machines.
  • I predict this trend will continue to the point where open source has so complete dominated the software world, from the bottom up, that firms like Apple are constrained to sell their OS as value-added perks on top of a mostly open OS for their hardware, Adobe becomes a seller of boutique software, and MS becomes a systems integrator and software as a service provider.

Open Source is a Disruptive Product

Surely, I'm not the first person to think of this...

Sunday, August 10, 2008

The Next Chapter

While I was at 3Di I had the pleasure of working with many real and potential partner companies from across the globe. Many times I succeeded only in embarrassing myself professionally; but I always tried to hold true to a sense of professional competence, ethics, and behaviour that stood for the kind of person I want to be. Not unselfishly, I hoped to be seen as a stand out guy, even if only to serve my own conceited self image.

Part of my professional ethic is that companies, as abstract entities, with no more life than that which the whim of its investors endow it, deserve no great respect or loyalty in and of themselves. Companies demand obedience, whether it be to laws or directives from superiors; but it's people that deserve respect and loyalty. And many times it's people outside your company, who's respect you've cultivated and earned, who go furthest in helping you accomplish your goals.

I hope that doesn't sound too shocking, because superficially it appears to be a contradictory to the notions of belonging and identity that most people hold. However if you look closer you might find merely a different definition of the same.

The purpose for someone like me to join a company, it's never about getting rich, it's always about creating something larger that yourself. Money is just a means to play the game, not the game in and of itself. On the other hand, for many people, joining a company is about keeping your head down so you can continue to earn a wage to fund whatever it is you'd rather be doing. People like that aren't going to join you in building new things.

I am happy to say that the result of my connections was several strong relationships with people from many different companies, industries, and backgrounds. Some of whom I haven't even ever met in person yet. When I informed those people that I would no longer be able to act as a liaison with 3Di due to my decision to leave, I was impressed with the level of interest in continuing working with me after 3Di. It didn't take very long for someone to offer me a job, but I am somewhat surprised at the quality of opportunity I have been given a shot at.

I have tentatively accept a role as senior engineer with RealXtend, an emerging leader in open 3D virtual worlds, to work with them directly in Oulu Finland. I will likely be involved in working with the open source community, general programming, and helping plot technical direction using the knowledge and insight I've cultivated during my short but eventful career in virtual worlds.

That means picking up the family and heading down to the equivalent of a small town to the north of Edmonton. While Oulu is quite a bit smaller than the some 35M people in the greater Tokyo area, I am actually relishing a chance to leave this mass of humanity behind for a while. I needed a new direction, under leadership that I can respect, and quite frankly, I am impressed beyond words at the professionalism and attitude that realxtend has shown in their work to get me over to Finland. These guys are great guys, and as I said to start out, it's the people there that have earned my respect and loyalty.

Saturday, July 26, 2008

Bonus Track



Bonus points if you can tell me where that was shot.

Belated Happy L. Day, and other such Joyous News!


I know my blog entries have become scarce. There is a fair amount of change happening in my world, and what free time I do have generally goes to L., who demands it most insistently.

For those that don't know, I am finally leaving 3Di after over a year. The final incident that decided the matter was a bit of a much-ado-about-nothing due to political and cultural issues, and I finally realized that what I was doing wasn't rewarding enough to justify that degree of continued frustration. I told the management that something had to change or I would leave; and they sat on their thumbs, and said nothing, as they are wont to do, until I resigned as I said I must. And thus it was decided.

My entire career at 3Di might be considered one of trying to "fix things from the inside", but in the end it must be said that I have failed almost entirely. I don't blame myself for it, though I am hardly blameless -- no doubt my frequent lack of tact when complaining of systematic incompetence throughout the company lead to a situation where after a while no one would hear anything I had to say any more. However simply ignoring a rather insistent complaint doesn't make the root disease vanish, and so it's management's failure to own up to their own ... um failures and implement some real improvement, that was the ultimate ... ah failure. Fail.

That said I cherish my time at 3Di, as it has taught me a lot about technology, business, management, and myself. I am very glad that I joined this rollercoaster, and would do it again.

Where to go from here is a little unclear yet, but one thing I am fairly certain of, I don't wish to work for any Japanese capitalized/managed companies any more. I've had my share, and it's taught me that outside of some superstar companies like Toyota or Sony, (current?) Japanese business culture rewards mediocrity, hides incompetence, and punishes excellence. It obscures clear, precise communication, and is generally ill-suited for business outside of Japan. (This is a whole rant in and of itself!)

I am looking at western companies in Tokyo, a handful of foreign companies related to my work at 3Di, various companies back in Canada and the US. I am also considering taking some of my ideas from working at 3Di and seeing if anyone wants to do some research with me. Particularly I wish to study Scalability, Security, and Identity in Virtual Worlds (OpenSim).

And now time for something completely different.

Thursday, June 19, 2008

Every thing you need to know about a Programmer, you can learn from having them explain their own code to you.

I've been doing interviewing and hiring at our technology startup for almost a year now. When we began hiring, I found that I was basically the only person who would do it -- partly because I was the only person who displayed any sort of natural aptitude at judging another Engineer's technical and personal abilities.

It didn't take me long to create my own system which I thought was both fair to the interviewee (whom I empathized with, having been one for so long), and gave me a decent understanding of the candidate's qualities. With a little bit of intuition, and some trial-and-error, I evolved my system.

As the people I had interviewed and hired began to join me in the interviewing process, I got to notice how other people handled going from interviewee to interviewers, and how their outlook on a candidate's performance differed from mine.

This evolutionary process has lead me to solidify the following as my Golden Laws (tm) of hiring. Most people who are experienced with interviewing will not be surprised I think, but when a new person joins our team, I find that I need to explain these rules each time anew, so I thought I'd write them down.

1. Hiring is the single most important thing a company can do because it directly affects all other things that are done thereafter.

2. Hire only people you completely trust to fulfil a given role. Then completely trust those people.

3. Your job as an interviewer is NOT to hire "good" people -- that's an undecidable problem. Your job as interviewer is to REJECT substandard people.

4. The most critical personality trait to look for in a candidate is Honesty. All other important properties flow from that font. Dishonesty in an interview is the Kiss-of-Death.

5. Every thing you need to know about an Programmer, you can learn from having them explain their own code to you.

(And lastly, the Green Interviewer's Trap: Hiring is not a popularity contest. Most interviewees are a nice people.You are not required to hire nice people just because they're nice.)

The last law is the title of this entry because its perhaps the most controversial item. Yet I hold it to be the most essential truth I have discovered about hiring Programmers. So much so, I am going to let you in to my entire technical review process, and how it is centred around item 5:

The Sample

After reviewing the candidate's resume, and mentally making note of potential strengths and weaknesses, I always request a code sample from the candidate, in the following order of preference:

1. Open Source or otherwise Publicly Available Source

Open source is the best way to possibly find out how good a programmer is. A public SCM server has all history and contribution information regarding that project. You can graph a programmer's entire history with that code base to the most minute detail.

Mailing lists have discussions of technical matters, and help show how well the candidate gets along with other people.

Open Source is usually a work of passion, and outside the corrupting influence of bad company management, so you have already factored out the naked element of talent.

2. Redacted Source code taken from a company project (without violating any applicable laws, be careful)

Proprietary (but redacted in order to comply with confidentiality laws) source code is good because it shows what the candidate produces when given a real-world problem in real-world circumstances. Particularly it shows if they tend cut corners to meet deadlines or other practical constraints.

3. School Coursework (if a semi-recent graduate)

School coursework, if not too dated, is good because it shows what the candidate can do when asked to really apply their intellect to a serious problem. It's also an opportunity for the candidate to explain how his coding style has evolved over time, and why he would make different decisions today.

4. Toy Project selected by Candidate

Candidate-selected toy project is good because it shows what interest the candidate has if someone is not over their shoulder telling them what to do.

Do they choose something just difficult enough to meet your requirements? Do they choose something way too hard to complete in a reasonable amount of time? Do they report enjoying the exercise?

5. Toy Project selected by Me

One reason why I neglect this option to the last is that one must be respectful that candidates often are busy people, and they can and will turn down the interview because they feel they have better things to do than jump through your recruiting hoops.

6. Source written by Me

This is fun for showing off your work, and is realistic in the sense that programmers are routinely asked to do exactly that, however its rarely under such pressure situations. It's too easy to have a flustered programmer get thrown off by some minor detail, and thus you end up with incomplete reading of their true ability.

Either way, it is absolutely critical that the code is either hand-written by the candidate (or in cases where external code sources were used, clearly attributed as belonging to someone else), because we are going to ask them to explain its working to us. Clear attribution is critical because it is an unalterable part of our standard of honesty.

The Interview Prep

Once you have a sample of their code, you can of course review the code before the Interview to look at issues of Style, Correctness, Performance, Good Design. This is important. However the real purpose of reviewing the code is to generate questions for the candidate once he arrives to the interview. Ask yourself, "why did this person choose to make these decisions when writing the code?"

The Interview

When the Candidate arrives, I open the interview with a stupid joke or sarcasm. Partly because I often am as nervous as the candidate, and I want to break the ice. I also tell him that there are no "Right" answers in this interview, and no trick questions. It is important for the dignity of both parties to keep the interview cooperative, and to make it understood that you are both on the same side -- after you hire the candidate, you certainly will be counting on their cooperation and good will then!

Next I have a short list of simple, no-nonsense, general questions that I ask every candidate. For example "We are in the technology field, and as we both know, technology changes at a staggering rate. What methods do you use to keep on top of that change? Please be specific."

Next I have the list of questions generated from their sample code with me, and I move across the table to sit beside to the candidate with my laptop. I open their source code opened in a text editor (their preferred on if possible).

I ask the candidate to pretend that I am a Junior Engineer, and he must explain his code to me. As a curious person, I will stop them at various points to clarify the concerns I compiled during the Interview Prep, and put to rest any questions that happen to come into my mind as they are speaking.

What an observer can gather from this simple exercise is essentially everything you'll ever need to know about that person as a Programmer.

- A person who remembers even very old code is a person that was paying close attention when they wrote it, and understood the nuance of every line.

People who have trouble recalling what they wrote either didn't write it, or never understood it clearly when the wrote it.

- A person who speaks confidently and at a decent pace is a person at ease with their code and the decisions that code embodies. Even if the code is bad, a good programmer can justify their compromises in a rational manner.

People who speak in broad generalities, ramble incoherently, or carry off on tangents are more than just disorganized. They are trying to distract you from the fact that they don't know what they are talking about by burrying you in an avalache of verbage.

- A person who identifies their own mistakes and errors is more than just aware of their own mistakes, they are showing an honesty and desire to learn and improve. Similarly, people admit their don't know or understand some facet of the system.

A person who steadfastly insists on issues where you know him to be mistaken are not capable working with others, and should be rejected immediately.

- A person that can turn a complicated algorithm or technical trick into something easily understood by any simple engineer has not just a gift for teaching, but likely a deep and intuitive understanding of domain.

People who cannot relate technical matter without speaking entirely above your level may be brilliant, but could prove problematic if they have to work with others.

That said, even simple body language can tell you a lot about a candidate. One of the most dependable Engineers I've ever worked with failed horribly in trying to understand some source code I had written (possibly because I hadn't written it nearly as well as I thought I had!). Every time I asked him what a certain peice of code was doing, he politely answered "I don't know". What impressed me was the way in which he studied my code so closely, determined to fathom out my design through force of will. To this day his tenacity to reason through a problem completely is the hallmark of his good work with our company.

The wind-down

If I have come to a negative conclusion about the candidate, and decided not to continue, I ask the if he has any questions, then thank the person for their time, and ask them to leave.

If I have finished my walk-through on a positive note, I wrap the interview up with a brief explanation of my company, then invite the candidate to ask his own questions of us in a reversal of the interview process.

A complete and incisive set of questions for me to answer is a sign of a good candidate.

If I conclude that a person is technically competent, the next round of interviews include various members of our team, and are mostly about making sure that personalities match well, and that company culture is maintained.

If any one interviewer registers a "refuse" vote, then the candidate is refused.

Thursday, May 29, 2008

Coming Home

I should have posted this a very long time ago, but I've been rather busy with work and life.

It seems that since I got back from NY in April I've been running around doing something, or just being plain run down. I had my friend Anand in town, and we had a good time about Tokyo. Now Deifante has come, and we'll be off to the Virtual World Conference and Expo here in Tokyo. The reason D. is in town is because we are kicking off a new project that I am ostensibly leading, and D. is contracting to work with us on it.

However, I am now planning to pack up my family and head back to Canada for the first time in over 2 years. It will be L.'s first trip on an airplane, and my family's first time seeing L. in person.

If anyone I know in Calgary would like to meet me or M. or L., please drop me an email, and I will do my best to arrange it. :)

Tuesday, May 6, 2008

If I had a wedding, and I had tried this line at it, I think I would have lost exactly everyone

[Reads]


You that choose not by the view,
Chance as fair and choose as true!
Since this fortune falls to you,
Be content and seek no new,
If you be well pleased with this
And hold your fortune for your bliss,
Turn you where your lady is
And claim her with a loving kiss.

A gentle scroll. Fair lady, by your leave;
I come by note, to give and to receive.
Like one of two contending in a prize,
That thinks he hath done well in people's eyes,
Hearing applause and universal shout,
Giddy in spirit, still gazing in a doubt
Whether these pearls of praise be his or no;
So, thrice fair lady, stand I, even so;
As doubtful whether what I see be true,
Until confirm'd, sign'd, ratified by you.


-- BASSANIO, SCENE II. Belmont. A room in PORTIA'S house.

Thursday, May 1, 2008

So this is what my Degree comes to...

After many years of study, it comes down to solving logarithms in your head while you're trying to get to sleep.

How many rounds of Russian Roulette does it take before you have 50-50 or worse odds of surviving?

If we assume there is 1 bullet in a 6 chambered revolver, you have a 1/5 chance of having your wig pushed back, and 5/6 chance of taking another breath. The problem is that every time you play (and survive to play again), you're taking another trial with 5/6 odds, which gives you (5/6)^n probability of surviving after n rounds.

Problem is that when you multiply a number less than 1, you always get something smaller than what you started with. That means one day, you will bite the bullet. The question is, after how many tries?

We wish to solve the following for n:


(5/6)^n = 1/2
=> lg (5/6)^n = lg (1/2)
=> n * lg (5/6) = lg (1/2)
=> n * (lg(5) - lg(6)) = lg(1) - lg(2)
=> n * (lg(5) - lg(2) - lg(3)) = -1


Now here we reason that since lg() is a continuous, monotonically increasing function, by the intermediate value theorem:


2 < 3 < 4 < 5
=> lg(2) < lg(3) < lg(4) < lg(5)
= 1 < lg(3) < 2 < lg(5)


That gives us a tight enough bound for lg(3) ~ 1.5, considering the precision we need only to the nearest whole number, but the bound on lg(5) is pretty loose, so we'll need to do better.

We know that we can approximate an analytic function, as lg() certainly is, about a point "a" using its derivative:


lg(x) ~ lg(a) + lg'(x) * (x-a)


We also know that
 
lg'(x) = 1/(x * ln2)

where e ~ 2.7, so we take ln2 ~ 1.

Together this gives:

lg(5)
~ lg(4) + 1/5 * (5-4)
= 2 + 1.5 = 2.2


Going back to the original equation:

n * (lg(5) - lg(2) - lg(3)) = -1
=> n * (2.2 - 1 - 1.5) = -1
=> n = 1 / 0.3 = 3.3


Lets verify that we haven't wandered completely off-base by checking our calculation:

(5/6)^3 = 125 / 216 > 125 / 250 = 1/2
=> (5/6)^3 > 1/2

(5/6)^4 = (125 * 5) / (216 * 6) = 625 / 1296 < 1250 = 1/2
=> (5/6)^4 < 1/2


So there you have it: 3 rounds of everyone's favorite pastime gives you better than 50-50 odds, and 4 rounds give you worse than 50-50 odds. Running it through the calculator the next morning, you have a 57% chance of surviving 3 rounds, and 48% after 4.

Now, play a game of Russian Roulette and have a blast.

Monday, April 21, 2008

Asterisk Realtime Architecture

Like any machine tinkered with heavily over time, Asterisk has a lot of exposed configuration points in a lot of places, and it can be hard to know how or why what you want to do isn't working because you neglected to set some variable that became necessary since the last time the module was documented.

I've fallen into this situation for the past couple days, and having finally found the right thing to tweak, let me write down how to use ODBC to access Asterisk's configuration files, including the dial plan, from a real-time database.

First thing: go read the official book by O'Reilly, and read the chapter on ARA.

Once you have downloaded Asterisk, as we did here, run ./configure, then make menuselect and ensure res_odbc, res_config_odbc, and all *_realtime modules are set
to be built. If they have a 'XXX' beside their name, it means that you need to install some dependencies. Search your package installer for "ODBC" and a database that supplies an ODBC driver, such as PostgreSQL or MySQL. You may also need the "-devel" version of those packages.

To make the tutorial complete, we'll pick a DB for the examples, so we choose PostgreSQL.

1. Setting Up the Database

As the DB's (not the system's) root user create a new role and database for Asterisk to use:
createuser -SRdP asterisk-role
createdb --owner=asterisk-role asterisk-db

Then restart the database.

2. Setting Up ODBC

Ensure that /etc/odbcinst.ini exists and contains something like the following:
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib/libodbcpsql.so
Setup = /usr/lib/libodbcpsqlS.so
FileUsage = 1

Ensure that /etc/odbcinst.ini exists and contains something like the following:
[asterisk-postgres-connector]
Description = PostgreSQL connection to 'asterisk' database
Driver = PostgreSQL
Database = asterisk-db
Servername = localhost
UserName = asterisk-role
Password = 123456

Then verify that the connection works using the following command:
echo "select 1" | isql -v asterisk-postgres-connector

3. Setting Up a Basic Asterisk Configuration

extconfig.conf
[settings]
sipusers => odbc,asterisk-postgres-connector,sip_table
sippeers => odbc,asterisk-postgres-connector,sip_table
extensions => odbc,asterisk-postgres-connector,extensions_table

extensions.conf
[general]
[default-sip]
switch => Realtime/@

modules.conf
[modules]
autoload=yes
preload => res_odbc.so
preload => res_config_odbc.so

res_odbc.conf
[ENV]

[asterisk-postgres-connector]
enabled => yes
dsn => asterisk-postgres-connector
username => asterisk-role
password => 123456
pre-connect => yes

sip.conf
[general]

4. Setting up Dialplan and Sip User/Peer Tables

This is perhaps the most mysterious point. The ARA requires a number of columns to be set within the table, and if they aren't it will silently fail. The SIP table in particular. Nearest I can tell, the only source of documentation is here.

Run the following SQL code as the asterisk-role:

CREATE TABLE extensions_table
(
"id" serial,
"context" varchar(20) NOT NULL default '',
"exten" varchar(36) NOT NULL default '',
"priority" smallint NOT NULL default '0',
"app" varchar(20) NOT NULL default '',
"appdata" varchar(128) NOT NULL default '',

PRIMARY KEY (id)
) WITHOUT OIDS;

CREATE TABLE sip_table
(
"id" serial,
"name" varchar(80) NOT NULL default '',
"host" varchar(31) NOT NULL default 'dynamic',
"nat" varchar(5) NOT NULL default 'route',
"type" varchar(6) check (type in ('user','peer','friend')) NOT NULL default 'friend',
"accountcode" varchar(20) default NULL,
"amaflags" varchar(13) default NULL,
"callgroup" varchar(10) default NULL,
"callerid" varchar(80) default NULL,
"call-limit" int NOT NULL default '0',
"cancallforward" char(3) default 'no',
"canreinvite" char(3) default 'no',
"context" varchar(80) default 'default-sip',
"defaultip" varchar(15) default NULL,
"dtmfmode" varchar(7) default NULL,
"fromuser" varchar(80) default NULL,
"fromdomain" varchar(80) default NULL,
"insecure" varchar(4) default NULL,
"language" char(2) default NULL,
"mailbox" varchar(50) default NULL,
"md5secret" varchar(80) default NULL,
"deny" varchar(95) default NULL,
"permit" varchar(95) default NULL,
"mask" varchar(95) default NULL,
"musiconhold" varchar(100) default NULL,
"pickupgroup" varchar(10) default NULL,
"qualify" char(3) default NULL,
"regexten" varchar(80) default NULL,
"restrictcid" char(3) default NULL,
"rtptimeout" char(3) default NULL,
"rtpholdtimeout" char(3) default NULL,
"secret" varchar(80) default NULL,
"setvar" varchar(100) default NULL,
"disallow" varchar(100) default '',
"allow" varchar(100) default '',
"fullcontact" varchar(80) NOT NULL default '',
"ipaddr" varchar(15) NOT NULL default '',
"port" smallint NOT NULL default '0',
"regserver" varchar(100) default NULL,
"regseconds" int NOT NULL default '0',
"username" varchar(80) NOT NULL default '',
"delay" int NOT NULL default '0',
"sortorder" int NOT NULL default '1',
PRIMARY KEY (id),
UNIQUE (name)
) WITHOUT OIDS;

GRANT ALL ON sip_table TO asterisk;
GRANT ALL ON extensions_table TO asterisk;

INSERT INTO extensions_table (context, exten, priority, app, appdata) VALUES ('default-sip', 'sip-extn', 1, 'Answer', '');
INSERT INTO extensions_table (context, exten, priority, app, appdata) VALUES ('default-sip', 'sip-extn', 2, 'Wait', '2');
INSERT INTO extensions_table (context, exten, priority, app, appdata) VALUES ('default-sip', 'sip-extn', 3, 'Playback', 'hello-world');
INSERT INTO extensions_table (context, exten, priority, app, appdata) VALUES ('default-sip', 'sip-extn', 4, 'Wait', '2');
INSERT INTO extensions_table (context, exten, priority, app, appdata) VALUES ('default-sip', 'sip-extn', 5, 'Hangup', '');

INSERT INTO sip_table (name, context, host, type) VALUES ('sip-user', 'default-sip', 'dynamic', 'friend');

5. Test the setup

Run Asterisk on the console, and verify the ODBC connection is working by issuing the command odbc show.

Don't bother trying to run dialplan show or similar, as this will not display what we inserted in the previous step. Instead we need to make a call to test: in your soft-phone, dial sip:sip-extn@asterisk.example.com, and you should hear a voice say "hello world".

Thursday, April 17, 2008

Working with Asterisk

Recently I have been working on some VoIP based solutions using Asterisk.

I've found it a bit hard to work on, partly because Asterisk appears to suffer from some ad-hoc growth over time, and not only is the design somewhat dated, but more importantly the documentation left around the web appears to be tied to past versions such that working with the newest versions can leave you scratching you head why what one guy did, and what you're doing don't seem to match up. Even when you manage to get the example working you're never quite sure which flag you twiddled happened to do the trick.

(Aside: there seems to be a lot of consulting business around Asterisk. Partly this is due to the inherently Enterprise-related nature of a PBX. However I have to wonder if these consultants don't have a vested interest in keeping Asterisk opaque. Certainly they'd have more clients than if the community spent time making it easier to use.)

First thing one needs to do when learning a system is to make some small examples. The easiest way to test your examples, lacking the sort of hardware one might have if they owned a real Enterprise phone system, is to use software phones. The most common kind of software phone is one that uses SIP to set up an audio stream (over RTP) for voice communication.

To obtain a working Asterisk server, download either the source, or a pre-compiled binary from your favorite location. If you're working a lot with Asterisk it makes sense to build the source yourself, since it's rather easy to build.

After you have completed the install, your /etc/asterisk/ directory should be full of a wild assortment of configuration files, each over-teeming with tweak-worth options. However just to set up a simple call, we don't need such complexity. Copy those files to a safe place, and consider the minimal files below:

modules.conf
As far as I can tell, this is all you'll ever need from modules.conf, under any situation.

[modules]
autoload=yes

This means that as Asterisk looks for .conf files (which we have mostly removed), and processes its internal and external dependencies, it will automatically load the binary files in /usr/lib/asterisk/modules.

sip.conf
This file controls the SIP input "channel", from which any session created from
sip:a-sip-user@example.com to sip:somewhere@asterisk.example.com, must pass first on its way through an Asterisk system. The call from a-sip-user is assigned a "context" which is where in the "dialplan" the call should be routed. ("user" means that the call is in-bound only, and "dynamic" means the server should look up the user's IP address dynamically)

[a-sip-user]
context=my-sip-context
type=user
host=dynamic

This means that anyone who call into Asterisk, and declares themselves to be "a-sip-user" via their SIP URI (such as sip:a-sip-user@somewhere.example.com), is given a dial plan context of "my-sip-context".

extensions.conf
This is the "dial plan", the place where the routing logic of a PBX is stored. It consists of a number of named contexts, under which a series of sequential functions are called. It will appear odd to a modern programmer, but if one considers the evolution of old-fashioned hardware based PBXs, it makes more sense.

Basically there is first an "extension", which is related to the old extension numbers you would have to dial over an old-fashioned system. However with software based PBXs, those extensions can now easily be human-readable strings.

A call is brought in to the dial plan from a channel. The only channel we are considering now is a SIP-based VoIP call. That channel attached a context to the call, and starting from the named context, the dial plan attempts to match an extension pattern to the one specified in a call.

In the case of a SIP call, where the URI is
sip:my-destination@asterisk.example.com, the extension is considered to be "my-destination".

[my-sip-context]
exten => sip-extn,1,Answer()
exten => sip-extn,n,Wait(2)
exten => sip-extn,n,Playback(hello-world)
exten => sip-extn,n,Wait(2)
exten => sip-extn,n,Hangup()

This means that when dropped in the "my-sip-context" context, Asterisk will attempt to match the extension against "sip-extn". The first action to be taken is to answer the call. The steps with priority marked "n" proceed sequentially from each other.

In the example above, the soft-phone must dial the following URI:
sip:sip-extn@asterisk.example.com as the user designated sip:a-sip-user@somewhere.example.com. Upon doing so, they should hear a female voice saying "hello world!"

If you are using ekiga as your soft-phone, go to Edit->Accounts, and then add a new one. The name can be any thing you like, however the registrar must be asterisk.example.com (that is the name or IP address of the machine running Asterisk), and the user must be a-sip-user. The password is empty because we have not required password protection in sip.conf.

Click OK and confirm that the Status indicates that it is registered with the server. If registration fails, check that the server's firewall is not blocking port 5060, and that you are not using the soft-phone from the same machine that Asterisk is running on since port numbers will conflict.

In the top-most address bar, enter the URI sip:sip-extn@asterisk.example.com and click enter. You should now hear the words "hello world!"

The version of Asterisk I used was 1.6.

Sunday, April 13, 2008

Thursday, April 10, 2008

How do you use your shell?

[ryanm@3Di0021d ~]$ history | awk '{a[$2]++ } END{for(i in a){print a[i] " " i}}'|sort -rn|head
177 make
144 ll
96 git
77 cd
59 grep
59 gvim
40 cp
38 git-svn
32 ./secondlife
30 svn

Sunday, March 30, 2008

Friday, March 28, 2008

Wednesday, March 26, 2008

Wednesday, March 12, 2008

Saturday, March 8, 2008

"Heroes" is true

People doing things thought to be physically impossible. Is it coincidence they all claim the use of meditation enables it.

http://abcnews.go.com/Health/story?id=4393377&page=1
http://www.youtube.com/watch?v=kLMRYm0xLiw&feature=related
http://www.youtube.com/watch?v=T6UTGkC73GE
http://www.youtube.com/watch?v=RAAB0dbc3Es

Lest anyone misinterpret me again, I hold that nothing is "true" until it passes scientific scrutiny.

What Ive been up to at work

So the entire executive team has been replaced with a far more experienced and professional team.

Since the change I have been very busy getting work done, and trying to march towards getting products out the door, and money back in.

Monday, February 18, 2008

More Cuteness

Video of L. getting her first solid food.

Goodbye Jiku

Enjoy your time at HiPiHi. I wish you the best of luck in your new venture.

Wednesday, February 13, 2008

Hello Jiku!

I'm flattered and impressed you subscribe to my blog!

While what I say here is indeed a matter of public record, I'm a little disappointed that you would choose to take issue with its contents, not by beginning a 2-way dialogue with me by email -- or heck, or in person, since you sit all of 5 meters away from me -- but rather by relaying your misunderstanding of its contents to our boss(es?) without clearing it by me first. Its a little surreal to come to work and be told that "everyone knows" the supposed contents of your personal blog.

Not a very professional or, I dare say, adult thing to do. I would prefer to have this conversation by email, however since you have refused to do so on nearly ever single occasion I've asked, I'm forced to resort to this.

However, please take comfort in knowing your communication issues are now a matter of public record. You're famous!

ps. I would also like to ask you to send me a link to your blog, where you chronicle your personal thoughts and feelings, so as to allow the people you love to stay connected to you. If the only way you know how to have an honest conversation surreptitious blog reading, then its what I'll have to settle for.

Grand Unified Theory of Parenting

I came up with this nugget a while ago, but I thought I'd dump it from my brain.

You might call it a Unified Theory of Properties All Successful Human Beings Must Have, but thats a bit over-pretentious.

In a person's life there are countless lessons, great and small, that one must learn. Ideally we could just tell each other what they are and be done with it, but unfortunately it seems that people just don't learn from sermons -- they only seem to truly comprehend when they experience the truth of the matter directly.

This poses a dilemma for parents. How do we set our children up for a happy successful life, if they're determined to repeat our mistakes?

My theory is you only need to teach a few basic pillars, and all other lessons follow naturally from those basic premises. They follow in order of importance.

1. The Foundation of All Society: Empathy -- the ability to feel what other living things feel.

Without this pillar, human society, and therefore civilization could not exist.

Having empathy means that you cannot do things to others that you would not do to yourself. This is the Golden Rule, and from the Golden Rule all morality follows.

2. The Foundation of Human Intellect: Curiosity -- the desire to understand the working of the world around you.

Without this pillar, human technology would not have progressed beyond the ability to hunt or gather enough food to just survive, and therefore civilization could not exist.

Having curiosity means that you start by questioning what you observe around you -- how? why? It also means that you must move past the question, and start interacting with your environment in order to begin searching out the answers.

This is Learning, specifically the essence of what we call the Scientific Method. And it is only from science that all objective knowledge can follow. (In the past humans have had pseudo-sciences from which they derived knowledge, but they have all eventually proven to be mistaken.)

3. The Foundation of Human Psychology: Self-Honesty -- the desire to resist the natural human tendency to accept an illusory perception of reality.

The study of adult psychology is essentially founded on the myriad set of biases built into our brain which plague human beings and cause untold misunderstanding. Without a drive to avoid these natural biases, we are constantly mis-interpreting our interactions with the world, especially other human beings, and left confused and hurt as to why we seem to always find ourselves in a position of conflict.

Having self-honesty means more than just a clear perception of bias -- more importantly it leads to a state of mind that finds it difficult, and a waste of time, to be dishonest with others.

Self honest people must naturally lead to all honesty, and honesty is the essence of communication. Honesty is more than just the absence of lies, it is the presence of truth. It means that what you say is an accurate description of your environment, and that will lead people to trust and listen to what you say.

4. The Foundation of Personal Success: Effort -- the desire to continue to face difficulty until it is overcome.

The natural order of life is a continuous process of challenge. We are creatures that resulted from the ego-less life-and-death process of Evolution. There is no cease, just a constant march towards improvement, like slinky walking down an infinite case of stairs. When we accept this process, and not see it as tiring or unfair, we can find the will to continue with our struggles.

Without effort in our actions, most of them would fail immediately, and all success in this world would be a result of mere luck. Every time we pick up after failure, we give ourselves improved odds of succeeding the next time.

...

Starting from only the above lessons, I feel it is possible for any person to naturally directly deduce the entire set of life lessons.

Do you feel anything has been left out?

(Note: religion and dogmatic philosophical interpretations have been intentionally left out, either because I think they are wrong, or they are right, but could be extrapolated from the above. If you disagree, I am happy to hear, and likely challenge, your opinion.)

Sunday, February 10, 2008

Cooking with Food (TM)

Two easy to make condiments every cook should have in their repertoire to make meals more interesting, nutritious and less dependent on animal flesh.

Both are high in protein, unsaturated fats, and tastiousness.

Preparation: buy a cheap food processor. Now.

Tzatziki

- 1/3 cucumber, peeled
- 1/2 lemon, juiced
- 1 cup thick or firm yoghurt
- 1/2 cup olive oil
- 1 teaspoon garlic paste
- 1 teaspoon oregano
- 1 teaspoon salt

1. Puree cucumber, mix ingredients in a bowl, adjust proportions to taste
2. Chill in the fridge

Hummus

- 1 can chickpeas (garbanzo beans)
- 1 table spoon sesame paste (tahini)
- 1/2 lemon, juiced
- 1/2 cup olive oil
- 1 tablespoon garlic paste
- 1 tablespoon spice (cumin, coriander, paprika)

1. puree ingredients, adjust proportions to taste
2. Chill in fridge

Any good cook should be able to adjust and substitute the recipe depending on what is available upon opening the fridge.

Thursday, February 7, 2008

Tuesday, January 22, 2008

I HATE filling out those custom CV forms on job sites

My ideal job is anywhere where I can:

1. Learn and improve myself as a technician and human
2. Improve the world around me through my skills as an engineer and leader
3. Enjoy the passion and comradery of a truly unique group of people

In more concrete terms I find that the kind of workplaces that foster such an environment tend to be those in R&D, academic, or Free Software companies. I think what I consider to be an ideal company, right down to the details, is already well known and commonly held among serious professional programmers, the kind of people my ideal company staffs itself with.

I want to be exposed to a large breadth and depth of technologies, and given a chance to challenge myself. I want to work together as a team to accomplish things I could have never done alone.

I consider life to be a marathon race until death, not a sprint until twenty or thirty years old.
I want to die a great man in the judgment of the people who are closest to me.
And I realize that the only path to where I want to go is one with daily dedication to learning and growing just a little bit more than yesterday -- from this moment, until the time when the world passes me by.

Its in this way that I take my work, my life, seriously; but no more serious than I take the rising sun, or my daughter's smile. As it should be.

My idea workplace would be one where people understand, and agree, and walk with me down this road.

I have a dream

I'm not big into politics, especially American politics, but I think it is the perfect timing for rare moment when someone brings a message that brings out the very best in our human nature.

Saturday, January 19, 2008

(Haskell) Monads for Imperative Peeps

Warning, since I am still learning Monads, it's quite possible the following is partially or even entirely wrong.

Why Monads


Functional programming languages have the constraint that their functions cannot have any side-effects. A function cannot do anything except produce a return value which is strictly dependent on its input values.

This is done for many good reasons. One such reason is to allow allowing some pretty mean performance optimizations: specifically allowing each individual "pure" function to run on their own processor core, since by definition each function is dependent on its input only, and can run efficiently this way.

However this constraint effectively eliminates entire sub-sets of useful and essential operations. Most notably IO operations such as printing or reading from the console.

A monad is a abstract idea that allows functional languages to stay theoretically coherent by encapsulating side-effect producing operations within themselves. Monadic functions can then be separated from the remaining pure functions when optimizing.

Monads are also extremely useful for encapsulating entire classes of behavior by type. For example a monad for functions that print or read from an OS provided data source is called IO. For functions that print or read strings from the console, the embedded type for IO would be String, and thus their type would be String -> IO String.

What are Monads


In programming languages, monads are meta-types that embed other types.

A monad has 3 parts:
1. A type construction, which defines how to embed a type in the monad
2. A unit function, which explains how to place a value of a type into a value of the monad, "as is"
3. A binding operation, which explains how pull out a value of a type from the monad, apply a pure function to it, and return the result to the monad

As an example we will construct a monad called Maybe that defines a type who's values are either invalid, or from a valid range:

1. data Maybe t = Just t | Nothing

Which says that the monadic type Maybe with parameter type t is a type who's values are of type "Just t" or "Nothing". Nothing is the type of invalid values.

2. return x = Just x

Which defines a function that wraps any value in the identity type Just, and thus embeds it the monad Maybe by our definition in 1.

3. (Just x) >>= f = f x
Nothing >>= f = Nothing

Which says that any function f can be applied to the type Just x as a normal, every-day function call; but any value of the Nothing type always yields Nothing. This means that whenever an invalid value is encountered, all functions from that point on are also invalid.

Tuesday, January 15, 2008

It's Ironic

They flee from me that sometime did me seek
With naked foot, stalking in my chamber.
I have seen them gentle, tame, and meek,
That now are wild and do not remember
That sometime they put themself in danger
To take bread at my hand; and now they range,
Busily seeking with a continual change.

Thanked be fortune it hath been otherwise
Twenty times better; but once in special,
In thin array after a pleasant guise,
When her loose gown from her shoulders did fall,
And she me caught in her arms long and small;
Therewithall sweetly did me kiss
And softly said, "dear heart, how like you this?"

It was no dream: I lay broad waking.
But all is turned thorough my gentleness
Into a strange fashion of forsaking;
And I have leave to go of her goodness,
And she also, to use newfangleness.
But since that I so kindly am served
I would fain know what she hath deserved.

--

Friday, January 11, 2008

Always Plotting Something...

An amazing source for a tool I always found hard to figure out: gnuplot.

Saturday, January 5, 2008

Friday, January 4, 2008

Thinking in git

"git" is a distributed source code management tool that is gaining a lot of interest from many corners of the international software development community due to its incredible flexibility and power. I like to compare it to powerful text editors like Vim or Emacs: it has a steep learning curve, but once you pick it up it will increase your productivity immensely, and if you are a professional programmer who takes himself seriously, you owe it to yourself to learn it fully.

However, using this new power-tool, like all specialized tools, requires readjusting you way of thinking about how you work before you can take advantage of the benefits.


1. Your local clone is also a repository in its own right



A repository is a .git directory. Every functional instance of a .git directory represents a full-featured repository, regardless how you came to possess it.

Its a deceptively simple but profound change in perspective. Ponder the implications fully.


2. All repositories are created equal



There is no inherent security policy in git (you have to piggy-back on SSH or Apache for that), and there is no sense of hierarchy among repositories that you do not define yourself through external policy.

Once you clone a branch from a remote repository, the originating branch is technically no more authoritative than yours is. The only technical constraint on branching and merging across repositories is that all branches must have a coherent history.

If two branches across repositories grow apart over time, and it is desired to reunite them into a common public branch, anyone attempting merge the two must reconcile the histories is such a way that other repositories are able to recognize the history as either a common ancestor of a local branch, or reachable future given their current state.


3. Branch everything



Branching and merging is the bread and butter of a SCM, so it hopefully goes without saying that branches are trivial, and merges are as smart as possible for a machine, so use them.

Branch to test out a idea. Branch to test out a merge. Branch to impress your friends at cocktail parties.


4. Git is a low-level tool



Git, from the beginning, was designed to be a low-level storage format for a Distributed SCM, and its only recently that git has included within itself some high-level commands for the kind of basic operations that programmers care most about. If you take the time to understand the basic representation that git uses, you will find it harder to get confused about why the high-level commands do things you didn't expect them to do.

Git assumes very little about a programmer's workflow, and converts your commands to into rather simplistic and literal manipulations upon the basic data structures within the .git directory, so it pays to take a look inside the internal representation once and a while to verify your assumptions.


5. You can break your own repository, and others'



Since git makes almost no assumptions about your work flow, contains no inherent security policy, and has no concept of repository hierarchy, it is very easy to do something that can seriously ruin anyone's repository.

Git tries hard to be non-destructive when making changes, but it will always do exactly what you ask of it. And while an experienced git user can likely recover from a whole host of mistakes, there is no guarantee that you can.

While learning git, always back up your working source and .git directory regularly. Always make new branches to test out your actions before you proceed on important branches. And finally, take care when pushing/pulling changes to/from someone else's repository.


6. Every commit is a change, uniquely identified by a SHA-1 hash number



The basic currency of git is a set of changes to the .git data structure represented by a commit, and every commit is uniquely identified by a SHA-1 number.


7. A repository is a directed acyclic graph of commits, with named branches



As commits succeed commits, a linear history is built within the .git directory. When a branch is made it is given a name, and when a commit follows, the history becomes a tree and thus non-linear. When a merge happens, the two histories are joined together under one of the named branches.

Since history only proceeds in one direction, the graph is acyclic.


8. Commits and branches exist in your .git directory, not your working directory



Git stores the above DAG compressed in data structures in your .git directory. The files that appear in your working copy is only a decompressed representation of those structures, after they have been processed by your git commands.

If files appear to be out of place or missing, consult the git command line tools to inspect the .git repository first.

Culture Clash

I often find myself complaining internally about all the things I find broken about Japanese culture, and why it needs to change before it can join the ranks of modern societies. However instead of being so negative, I thought I'd turn things around and talk about how Japanese handle certain kinds of problems and how their backwardness is wisdom in disguise -- something they have discovered that the rest of the world, especially Americans, really need to figure out before they can be called civilized:

While ignoring a problem will never make it go away, many times turning a blind eye to a problem really is simply the best choice among worse alternatives: Attempting to fight against a tide that is not ready to change will only make things worse, and the best option you have available is to just ride it out.

Its tempting to look at Japanese who are ignoring a glaring problem by putting their head in the sand as childish and irresponsible, and take the position that our western tendency to leap on problems as obstacles to be overcome through a vigorous response, is clearly the progressive and adult way to handle our difficulties.

However if we take the position that we must clearly examine the real-world results of both active and passive responses, we will find that the reality is that our desire to interfere in things we cannot actually control often only makes things worse. And the so the "foolish" course of ignoring problems allows conditions beyond our control to work themselves out in time; without requiring our personal intervention, and thus actually turns out to be the only method of reaching a positive outcome.

So often our ethnocentrism is just not justified in practice. And with a change of perspective we find ourselves viewing our actions not as being proactive and adult-like, rather childishly self centered, impulsive, and obstinate (-- as Japanese view them).