How to be a Programmer (chapter 4 and glossary)
Chapter 4. Advanced Technological Judgment How to Tell the Hard From the Impossible It is our job to do the hard and discern the impossible. From the point of view of most wor...
To use this functions you must log in. If you have not account yet, use Create account button.
Place this code, and your visitors will be able to read this article directly from your site.
Chapter 4. Advanced
How to Tell the Hard From the Impossible
It is our job to do the hard and discern the impossible. From the point of view of most working programmers, something is impossible if either it cannot be grown from a simple system or it cannot be estimated. By this definition what is called research is impossible. A large volume of mere work is hard, but not necessarily impossible.
The distinction is not facetious because you may very well be asked to do what is practically impossible, either from a scientific point of view or a software engineering point of view. It then becomes your job to help the entrepreneur find a reasonable solution which is merely hard and gets most of what they wanted. A solution is merely hard when it can be confidently scheduled and the risks are understood.
It is impossible to satisfy a vague requirement, such as ‘Build a system that will compute the most attractive hair style and color for any person.’ If the requirement can be made more crisp, it will often become merely hard, such as ‘Build a system to compute an attractive hair style and color for a person, allow them to preview it and make changes, and have the customer satisfaction based on the original styling be so great that we make a lot of money.’ If there is not crisp definition of success, you will not succeed.
How to Utilize Embedded Languages
Embedding a programming language into a system has an almost erotic fascination to a programmer. It is one of the most creative acts that can be performed. It makes the system tremendously powerful. It allows you to exercise her most creative and Promethean skills. It makes the system into your friend.
The best text editors in the world all have embedded languages. This can be used to the extent that the intended audience can master the language. Of course, use of the language can be made optional, as it is in text editors, so that initiates can use it and no one else has to.
I and many other programmers have fallen into the trap of creating special purpose embedded languages. I fell into it twice. There already exist many languages designed specifically to be embedded languages. You should think twice before creating a new one.
The real question to ask oneself before embedding a language is: Does this work with or against the culture of my audience? If you intended audience is exclusively non-programmers, how will it help? If your intended audience is exclusively programmers, would they prefer an applications programmers interface (API)? And what language will it be? Programmers don't want to learn a new language that is narrowly used; but if it meshes with their culture they will not have to spend much time learning it. It is a joy to create a new language. But we should not let that blind us to the needs of the user. Unless you have some truly original needs and ideas, why not use an existing language so that you can leverage the familiarity users already have with it?
The solitary programmer that loves his work (a hacker) can choose the best language for the task. Most working programmers have very little control of the language they will use. Generally, this issue is dictated by pointy-haired bosses who are making a political decision, rather than a technological decision, and lack the courage to promote an unconventional tool even when they know, often with firsthand knowledge, that the less accepted tool is best. In other cases the very real benefit of unity among the team, and to some extent with a larger community, precludes choice on the part of the individual. Often managers are driven by the need to be able to hire programmers with experience in a given language. No doubt they are serving what they perceive to be the best interests of the project or company, and must be respected for that. However, I personally believe this the most wasteful and erroneous common practice you are likely to encounter.
But of course, things are never one-dimensional. Even if a core language is mandated and beyond your control, it is often the case that tools and other programs can and should be written in a different language. If a language is to be embedded (and you should always consider it!) the choice of language will depend a lot on the culture of the users. One should take advantage of this to serve your company or project by using the best language for the job, and in so doing make work more interesting.
Programming languages should really be called notations in that learning one is not at all as difficult as learning a natural language. To beginners and to some outsiders ``learning a new language'' seems a daunting task; but after you have three under your belt it's really just a question of becoming familiar with the available libraries. One tends to think of a large system that has components in three or four languages as a messy hodgepodge; but I argue that such a system is in many cases stronger than a one-language system in several ways:
There is necessarily loose coupling between the components that are written in different notations (though maybe not clean interfaces),
You can evolve to a new language/platform easily by rewriting each component individually,
Its possible that some of the modules are actually up-to-date.
Some of these effects may only be psychological; but psychology matters. In the end the costs of language tyranny outweigh any advantage that it provides.
How to Fight Schedule Pressure
Time-to-market pressure is the pressure to deliver a good product quickly. It is good because it reflects a financial reality, and is healthy up to a point. Schedule pressure is the pressure to deliver something faster than it can be delivered and it is wasteful, unhealthy, and all too common.
Schedule pressure exists for several reasons. The people who task programmers do not fully appreciate what a strong work ethic we have and how much fun it is to be a programmer. Perhaps because they project their own behavior onto us, they believe that asking for it sooner will make us work harder to get it there sooner. This is probably actually true, but the effect is very small, and the damage is very great. Additionally, they have no visibility into what it really takes to produce software. Not being able to see it, and not be able to create it themselves, the only thing they can do is see time-to-market pressure and fuss at programmers about it.
The key to fighting schedule pressure is simply to turn it into time-to-market pressure. The way to do this to give visibility into the relationship between the available labor and the product. Producing an honest, detailed, and most of all, understandable estimate of all the labor involved is the best way to do this. It has the added advantage of allowing good management decisions to be made about possible functionality tradeoffs.
The key insight that the estimate must make plain is that labor is an almost incompressible fluid. You can't pack more into a span of time anymore than you can pack more water into a container over and above that container's volume. In a sense, a programmer should never say ‘no’, but rather to say ‘What will you give up to get that thing you want?’ The effect of producing clear estimates will be to increase the respect for programmers. This is how other professionals behave. Programmers' hard work will be visible. Setting an unrealistic schedule will also be painfully obvious to everyone. Programmers cannot be hoodwinked. It is disrespectful and demoralizing to ask them to do something unrealistic. Extreme Programming amplifies this and builds a process around it; I hope that every reader will be lucky enough to use it.
How to Understand the User
It is your duty to understand the user, and to help your boss understand the user. Because the user is not as intimately involved in the creation of your product as you are, they behave a little differently:
The user generally makes short pronouncements.
The user has their own job; they will mainly think of small improvements in your product, not big improvements.
The user can't have a vision that represents the complete body of your product users.
It is your duty to give them what they really want, not what they say they want. It is however, better to propose it to them and get them to agree that your proposal is what they really want before you begin, but they may not have the vision to do this. Your confidence in your own ideas about this should vary. You must guard against both arrogance and false modesty in terms of knowing what the customer really wants. Programmers are trained to design and create. Market researchers are trained to figure out what people want. These two kinds of people, or two modes of thought in the same person, working harmoniously together give the best chance of formulating the correct vision.
The more time you spend with users the better you will be able to understand what will really be successful. You should try to test your ideas against them as much as you can. You should eat and drink with them if you can.
Guy Kawasaki[Rules] has emphasized the importance of watching what your users do in addition to listening to them.
I believe contractors and consultants often have tremendous problems getting their clients to clarify in their own minds what they really want. If you intend to be a consultant, I suggest you choose your clients based on their clear-headedness as well as their pocketbooks.
To be promoted to a role, act out that role first.
To get promoted to a title, find out what is expected of that title and do that.
To get a pay raise, negotiate armed with information.
If you feel like you are past due for a promotion, talk to your boss about it. Ask them explicitly what you need to do to get promoted, and try to do it. This sounds trite, but often times your perception of what you need to do will differ considerably from your boss's. Also this will pin your boss down in some ways.
Most programmers probably have an exaggerated sense of their relative abilities in some ways---after all, we can't all be in the top 10%! However, I have seem some people who were seriously unappreciated. One cannot expect everyone's evaluation to perfectly match reality at all times, but I think people are generally moderately fair, with one caveat: you cannot be appreciated without visibility into your work. Sometimes, do to happenstance or personal habits, someone will not be noticed much. Working from home a lot or being geographically separated from your team and boss makes this especially difficult.
Nietschze exaggerated when he said[Stronger]:
What does not destroy me, makes me stronger.
Your greatest responsibility is to your team. You should know each of them well. You should stretch your team, but not overburden them. You should usually talk to them about the way they are being stretched. If they buy in to it, they will be well motivated. On each project, or every other project, try to stretch them in both a way that they suggest and a way that you think will be good for them. Stretch them not by giving them more work, but by giving them a new skill or better yet a new role to play on the team.
You should allow people (including yourself) to fail occasionally and should plan for some failure in your schedule. If there is never any failure, there can be no sense of adventure. If there are not occasional failures, you are not trying hard enough. When someone fails, you should be as gentle as you can with them while not treating them as though they had succeeded.
Try to get each team member to buy in and be well motivated. Ask each of them explicitly what they need to be well-motivated if they are not. You may have to leave them dissatisfied, but you should know what everybody desires.
You can't give up on someone who is intentionally not carrying their share of the load because of low morale or dissatisfaction and just let them be slack. You must try to get them well-motivated and productive. As long as you have the patience, keep this up. When your patience is exhausted, fire them. You cannot allow someone who is intentionally working below their level to remain on the team, since it is not fair to the team.
Make it clear to the strong members of your team that you think they are strong by saying so in public. Praise should be public and criticism private.
The strong members of the team will naturally have more difficult tasks than the weak members of the team. This is perfectly natural and nobody will be bothered by it as long as everyone works hard.
It is an odd fact that is not reflected in salaries that a good programmer is more productive than 10 bad programmers. This creates a strange situation. It will often be true that you could move faster if your weak programmers would just get out of the way. If you did this you would in fact make more progress in the short term. However, your tribe would lose some important benefits, namely the training of the weaker members, the spreading of tribal knowledge, and the ability to recover from the loss of the strong members. The strong must be gentle in this regard and consider the issue from all angles.
You can often give the stronger team members challenging, but carefully delineated, tasks.
How to Choose What to Work On
You balance your personal needs against the needs of the team in choosing what aspect of a project to work on. You should do what you are best at, but try to find a way to stretch yourself not by taking on more work but by exercising a new skill. Leadership and communication skills are more important than technical skills. If you are very strong, take on the hardest or riskiest task, and do it as early as possible in the project to decrease risk.
How to Get the Most From Your Teammates
To get the most from your teammates, develop a good team spirit and try to keep every individual both personally challenged and personally engaged.
To develop team spirit, corny stuff like logoized clothing and parties are good, but not as good as personal respect. If everyone respects everyone else, nobody will want to let anybody down. Team spirit is created when people make sacrifices for the team and think in terms of the good of the team before their own personal good. As a leader, you can't ask for more than you give yourself in this respect.
One of the keys to team leadership is to facilitate consensus so that everyone has buy in. This occasionally means allowing your teammates to be wrong. That is, if it does not harm the project too much, you must let some of your team do things their own way, based on consensus, even if you believe with great confidence it is the wrong thing to do. When this happens, don't agree, simply disagree openly and accept the consensus. Don't sound hurt, or like you're being forced into it, simply state that you disagree but think the consensus of the team is more important. This will often cause them to backtrack. Don't insist that they go through with their initial plan if they do backtrack.
If there is an individual who will not consent after you have discussed the issues from all appropriate sides, simply assert that you have to make a decision and that is what your decision is. If there is a way to judge if your decision will be wrong or if it is later shown to be wrong, switch as quickly as you can and recognize the persons who were right.
Ask your team, both as a group and individually, what they think would create team spirit and make for an effective team.
Praise frequently rather than lavishly. Especially praise those who disagree with you when they are praiseworthy. Praise in public and criticize in private; with one exception: sometimes growth or the correction of a fault can't be praised without drawing embarrassing attention to the original fault, so that growth should be praised in private.
How to Divide Problems Up
It's fun to take a software project and divide it up into tasks that will be performed by individuals. This should be done early. Sometimes managers like to think that an estimate can be made without consideration of the individuals that will perform the work. This is impossible since the productivity of individuals varies so widely. Who has particular knowledge about a component also constantly changes and can have an order of magnitude effect on performance.
Just as a composer considers the timbre of the instrument that will play a part or the coach of an athletic team considers the strengths of each player, the experienced team leader will not usually be able to separate the division of the project into tasks from the team members to which they will be assigned. This is part of the reason that a high-performing team should not be broken up.
There is a certain danger in this given that people will become bored as they build upon their strengths and never improve their weaknesses or learn new skills. However, specialization is a very useful productivity tool when not overused.
How to Handle Boring Tasks
Sometimes it is not possible to avoid boring tasks that are critical to the success of the company or the project. These tasks can really hurt the morale of those that have to do them. The best technique for dealing with this is to invoke or promote Larry Wall's programmer's virtue of Laziness. Try to find some way to get the computer to do the task for you or to help your teammates do this. Working for a week on a program to do a task that will take a week to do by hand has the great advantage of being more educational and sometimes more repeatable.
If all else fails, apologize to those who have to do the boring task, but under no circumstances allow them to do it alone. At a minimum assign a team of two to do the work and promote healthy teamwork to get the task done.
How to Gather Support for a Project
To gather support for a project, create and communicate a vision that demonstrates real value to the organization as a whole. Attempt to let others share in your vision creation. This gives them a reason to support you and gives you the benefit of their ideas. Individually recruit key supporters for your project. Wherever possible, show, don't tell. If possible, construct a prototype or a mockup to demonstrate your ideas. A prototype is always powerful but in software it is far superior to any written description.
The seed of a tree contains the idea of the adult but does not fully realize the form and potency of the adult. The embryo grows. It becomes larger. It looks more like the adult and has more of the uses. Eventually it bears fruit. Later, it dies and its body feeds other organisms.
We have the luxury of treating software like that. A bridge is not like that; there is never a baby bridge, but merely an unfinished bridge. Bridges are a lot simpler than software.
It is good to think of software as growing, because it allows us to make useful progress before we have a perfect mental image. We can get feedback from users and use that to correct the growth. Pruning off weak limbs is healthful.
The programmer must design a finished system that can be delivered and used. But the advanced programmer must do more. You must design a growth path that ends in the finished system. It is your job to take a germ of an idea and build a path that takes it as smoothly as possible into a useful artifact.
To do this, you must visualize the end result and communicate it in a way that the engineering team can get excited about. But you must also communicate to them a path that goes from wherever they are now to where they want to be with no large leaps. The tree must stay alive the whole time; it cannot be dead at one point and resurrected later.
This approach is captured in spiral development. Milestones that are never too far apart are used to mark progress along the path. In the ultra-competitive environment of business, it is best if the milestones can be released and make money as early as possible, even if they are far away from a well-designed endpoint. One of the programmer's jobs is to balance the immediate payoff against future payoff by wisely choosing a growth path expressed in milestones.
The advanced programmer has the triple responsibility of growing software, teams, and persons.
A reader, Rob Hafernik, sent in this comment on this section that I can do no better than to quote in full:
I think you under-emphasize the importance here. It's not just systems, but algorithms, user interfaces, data models, and so on. It's absolutely vital as you work on a large system to have measurable progress toward intermediate goals. Nothing is as bad as the special horror of getting down to the end and discovering that the whole thing just isn't going to work (look at the recent debacle of the Voter News System). I would even go further and state it as a law of nature: no large, complex system can be implemented from scratch, it can only be evolved from a simple system to a complex system in a series of intentional steps.
To which one can only reply Fiat lux!
To communicate well, you have to recognize how hard it is. It is a skill unto itself. It is made harder by the fact that the persons with whom you have to communicate are flawed. They do not work hard at understanding you. They speak poorly and write poorly. They are often overworked or bored, and, at a minimum, somewhat focused on their own work rather than the larger issues you may be addressing. One of the advantages of taking classes and practicing writing, public speaking, and listening is that if you become good at it you can more readily see where problems lie and how to correct them.
The programmer is a social animal whose survival depends on communication with her team. The advanced programmer is a social animal whose satisfaction depends on communication with people outside her team.
The programmer brings order out of chaos. One interesting way to do this is to initiate a proposal of some kind outside the team. This can be done in a strawman or white-paper format or just verbally. This leadership has the tremendous advantage of setting the terms of the debate. It also exposes you to criticism, and worse, rejection and neglect. The advanced programmer must be prepared to accept this, because she has a unique power and therefore a unique responsibility. Entrepreneurs who are not programmers need programmers to provide leadership in some ways. Programmers are the part of the bridge between ideas and reality that rests on reality.
I haven't mastered communicating well, but what I'm currently trying is what I think of a four-pronged approach: After I have my ideas in order and am fully prepared, I try to speak verbally, hand people a white-paper (on real paper, as well as electronically) show them a demo, and then patiently repeat this process. I think a lot of times we are not patient enough in this kind of difficult communication. You should not be disheartened if your ideas are not immediately accepted. If you have invested energy in there preparation, no one will think poorly of you for it.
How to Tell People Things They Don't Want to Hear
You will often have to tell people things that will make them uncomfortable. Remember that you are doing this for a reason. Even if nothing can be done about the problem, you are telling them as early as possible so they will be well-informed.
The best way to tell someone about a problem is to offer a solution at the same time. The second best way is to appeal to them for help with the problem. If there is a danger that you won't be believed, you should gather some support for your assertion.
One of the most unpleasant and common things you will have to say is, ‘The schedule will have to slip.’ The conscientious programmer hates to say this, but must say it as early as possible. There is nothing worse than postponing action when a milestone slips, even if the only action is to inform everyone. In doing this, it is better to do it as a team, at least in spirit, if not physically. You will want your team's input on both where you stand and what can be done about it, and the team will have to face the consequences with you.
How to Deal with Managerial Myths
The word myth sometimes means fiction. But it has a deeper connotation. It also means a story of religious significance that explains the universe and mankind's relationship to it. Managers tend to forget what they learned as programmers and believe in certain myths. It would be as rude and unsuccessful to try to convince them these myths are false as to try to disillusion a devoutly religious person of their beliefs. For that reason, you should recognize these beliefs as myths:
More documentation is always better. (They want it, but they don't want you to spend any time on it.)
Programmers can be equated. (Programmers vary by an order of magnitude.)
Resources can be added to a late project to speed it. (The cost of communication with the new persons is almost always more taxing than helpful.)
It is possible to estimate software development reliably. (It is not even theoretically possible.)
Programmers' productivity can be measured in terms of some simple metric, like lines of code. (If succinctness is power, lines of code are bad, not good.)
If you have an opportunity, you can try to explain these things, but don't feel bad if you have no success and don't damage your reputation by confronting these myths belligerently. Each of these myths reinforces the manager's idea that they have some actual control over what is going on. The truth is that managers facilitate if they are good, and impede if they are bad.
How to Deal with Organizational Chaos
There are often brief periods of great organizational chaos, such as layoffs, buyouts, ipos, firings, new hirings, and so on. These are unsettling to everyone, but perhaps a little less unsettling to the programmer whose personal self-esteem is founded in capacity rather than in position. Organizational chaos is a great opportunity for programmers to exercise their magic power. I've saved this for last because it is a deep tribal secret. If you are not a programmer, please stop reading now.
Engineers have the power to create and sustain.
Non-engineers can order people around but, in a typical software company, can create and sustain nothing without engineers, just as engineers typically cannot sell a product or manage a business effectively. This power is proof against almost all of the problems associated with temporary organizational mayhem. When you have it you should ignore the chaos completely and carry on as if nothing is happening. You may, of course, get fired, but if that happens you can probably get a new job because of the magic power. More commonly, some stressed-out person who does not have the magic power will come into your cube and tell you to do something stupid. If you are really sure that it is stupid, it is best to smile and nod until they go away and then carry on doing what you know is best for the company.
If you are a leader, tell your people to do the same thing and tell them to ignore what anybody else tells them. This course of action is the best for you personally, and is the best for your company or project.
This is a glossary of terms as used in this essay. These do not necessarily have a standardized meaning to other people. Eric S. Raymond has compiled a massive and informative glossary[HackerDict] that rather surprisingly can pleasurably be read cover-to-cover once you can appreciate a fraction of it.
Slang for unknown-unknown. Problems that cannot presently even be conceptualized that will steal time away from the project and wreck the schedule.
The person or entity that gives you tasks. In some cases this may be the public at large.
The insertion of statements into a program on a strictly temporary basis that output information about the execution of the program for the purpose of debugging.
The practice of writing a program so that it can produce a configurable output log describing its execution.
- divide and conquer
A technique of top-down design and, importantly, of debugging that is the subdivision of a problem or a mystery into progressively smaller problems or mysteries.
Illusionary and often deceptive promises of software that is not yet for sale and, as often as not, will never materialize into anything solid.
The person who sets your tasks. In some cases, the user is the boss.
The people with whom you share loyalty to a common goal.
- low-hanging fruit
Big improvements that cost little.
The initiator of projects.
Objects that are no longer needed that hold memory.
A group of people organized for making money.
A group of people organized for making money.
A group of people you share cultural affinity and loyalty with.
- scroll blindness
The effect of being unable to find information you need because it is buried in too much other, less interesting information.
Actually time as measured by a clock on a wall, as opposed to CPU time.
The most important limitation in the performance of a system. A constriction that limits performance.
A unique piece of information from which all cached copies are derived that serves as the official definition of that data.
- heap allocated
Memory can be said to be heap allocated whenever the mechanism for freeing it is complicated.
Allocated memory that no longer has any useful meaning.
- garbage collector
A system for recycling garbage.
- memory leak
The unwanted collection of references to objects that prevents garbage collection (or a bug in the garbage collector or memory management system!) that causes the program to gradually increase its memory demands over time.
- Extreme Programming
A style of programming emphasizing communication with the customer and automated testing.
- hitting the wall
To run out of a specific resource causing performance to degrade sharply rather than gradually.
- speculative programming
Producing a feature before it is really known if that feature will be useful.
- information hiding
A design principle that seeks to keep things independent and decoupled by using interfaces that expose as little information as possible.
- object-oriented programming
An programming style emphasizing the the management of state inside objects.
- communication languages
A language designed primarily for standardization rather than execution.
- boxes and arrows
A loose, informal style of making diagrams consiting of boxes and arrows drawn between those boxes to show the relationships. This contrast with formal diagram methodologies, such as UML.
- lingua franca
A language so popular as to be a de facto standard for its field, as French was for international diplomacy at one time.
- buy vs. build
An adjective describing a choice between spending money for software or writing it your self.
- mere work
Work that requires little creativity and entails little risk. Mere work can be estimated easily.
- programming notation
A synonym for programming language that emphasizes the mathematical nature of programming language and their relative simplicity compared to natural languages.
A document meant to be the starting point of a technical discussion. A strawman may lead to a stickman, tinman, woodman, ironman, etc.
An informative document that is often meant to explain or sell a product or idea to an audience different than the programmers of that product or idea.
[Rules00] 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services.
[RDev96] 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules.
[CodeC93] 1993. Microsoft Press. Redmond, Wash. Code Complete.
[XP99] 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change.
[PlanXP00] 2000. 0201710919. Addison-Wesley. Planning Extreme Programming.
[Prag99] 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master.
[Stronger] 1889. Twilight of the Idols, "Maxims and Arrows", section 8..
[PGSite] 2002. Articles on his website: http://www.paulgraham.com/articles.html. All of them, but especially "Beating the Averages".
[Hacker] 2003. How to Become a Hacker. http://www.catb.org/~esr/faqs/hacker-howto.html.
[HackDict] 2003. The New Hacker Dictionary. http://catb.org/esr/jargon/jargon.html.
[ExpCS] 1986. How Experimental is Computing Science?. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF.
[Knife] 1984. On a Cultural Gap. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF .
Appendix B. History (As Of February, 2003)
Request for Feedback or Extension
Please send me any comments you may have on this essay. I consider all suggestions, many of which have already improved this essay.
I have placed this essay under the GNU Free Documentation License. This license is not specifically designed for essays. Essays are usually intended to be coherent and convincing arguments that are writtien from a single point of view in a single voice. I hope this essay is a short and pleasant read.
I also hope that it is instructive. Although not a textbook, it is broken into many small sections to which new sections can be freely added. If so inclined, you are encouraged to expand upon this essay as you see fit, subject to the provisions of the License.
It may be arrogance to imagine that this document is worthy of extension; but hope springs eternal. I would be joyous if it were extended in the following ways:
The addition of a comprehensive reading list to each section,
The addition of more and better sections,
Translation into other languages, even if only on a subsection-by-subsection basis, and/or
Criticism or commentary in-lined into the text.
The ability to build into different formats, such as palm formats and better HTML.
If you inform me of your work, I will consider it and may include it in subsequent versions that I produce, subject to the provisions of the License. You may of course produce your own versions of this document without my knowledge, as explained in the License.
Robert L. Read
The original version of this document was begun by Robert L. Read in the year 2000 and first published electronically at Samizdat Press(http://Samizdat.mines.edu) in 2002. It is dedicated to the programmers of Hire.com.
After this article was mentioned on Slashdot in 2003, about 75 people sent me email with suggestions and errata. I appreciate them all. There was a lot of duplication, but the following people either made major suggestions or were the first to find a bug that I fixed: Morgan McGuire, David Mason, Tom Moertel, Ninja Programmer (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark Howe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, Andrew Wu, David Jeschke, and Tom Corcoran.
Finally I would like to thank Christina Vallery, whose editing and proofreading greatly improved the second draft, and Wayne Allen, who encouraged me to initiate this.
Robert L. Read lives in Austin, Texas, with his wife and two children. He is currently a Principal Engineer at Hire.com, where he has worked for four years. Prior to that he founded 4R Technology, which made a scanner-based image analysis quality control tool for the paper industry.
Rob received a PhD from the University of Texas at Austin in 1995 in Computer Science related to database theory. In 1987 he received a BA in Computer Science from Rice University. He has been a paid programmer since the age of 16.
This work is licensed under the GNU Free Documentation License.
The original version of this document was written by Robert L.
Rekomendowany: 0 razy
Visitors on-line: 1
Publication rules in text
We've got 1 400 000 visits by month!