Website Credibility

1. Make it easy to verify the accuracy of the information on your site.

You can build web site credibility by providing third-party support (citations, references, source material) for information you present, especially if you link to this evidence. Even if people don’t follow these links, you’ve shown confidence in your material.

2. Show that there’s a real organization behind your site.

Showing that your web site is for a legitimate organization will boost the site’s credibility. The easiest way to do this is by listing a physical address. Other features can also help, such as posting a photo of your offices or listing a membership with the chamber of commerce.

3. Highlight the expertise in your organization and in the content and services you provide.

Do you have experts on your team? Are your contributors or service providers authorities? Be sure to give their credentials. Are you affiliated with a respected organization? Make that clear. Conversely, don’t link to outside sites that are not credible. Your site becomes less credible by association.

4. Show that honest and trustworthy people stand behind your site.

The first part of this guideline is to show there are real people behind the site and in the organization. Next, find a way to convey their trustworthiness through images or text. For example, some sites post employee bios that tell about family or hobbies.

5. Make it easy to contact you.

A simple way to boost your site’s credibility is by making your contact information clear: phone number, physical address, and email address.

6. Design your site so it looks professional (or is appropriate for your purpose).

We find that people quickly evaluate a site by visual design alone. When designing your site, pay attention to layout, typography, images, consistency issues, and more. Of course, not all sites gain credibility by looking like The visual design should match the site’s purpose.

7. Make your site easy to use – and useful.

We’re squeezing two guidelines into one here. Our research shows that sites win credibility points by being both easy to use and useful. Some site operators forget about users when they cater to their own company’s ego or try to show the dazzling things they can do with web technology.

8. Update your site’s content often (at least show it’s been reviewed recently).

People assign more credibility to sites that show they have been recently updated or reviewed.

9. Use restraint with any promotional content (e.g., ads, offers).

If possible, avoid having ads on your site. If you must have ads, clearly distinguish the sponsored content from your own. Avoid pop-up ads, unless you don’t mind annoying users and losing credibility. As for writing style, try to be clear, direct, and sincere.

10. Avoid errors of all types, no matter how small they seem.

Typographical errors and broken links hurt a site’s credibility more than most people imagine. It’s also important to keep your site up and running.

  1. Website Credibility by Stanford

PHP: a fractal of bad design


I’m cranky. I complain about a lot of things. There’s a lot in the world of technology I don’t like, and that’s really to be expected—programming is a hilariously young discipline, and none of us have the slightest clue what we’re doing. Combine with Sturgeon’s Law, and I have a lifetime’s worth of stuff to gripe about.

This is not the same. PHP is not merely awkward to use, or ill-suited for what I want, or suboptimal, or against my religion. I can tell you all manner of good things about languages I avoid, and all manner of bad things about languages I enjoy. Go on, ask! It makes for interesting conversation.

PHP is the lone exception. Virtually every feature in PHP is broken somehow. The language, the framework, the ecosystem, are all just bad. And I can’t even point out any single damning thing, because the damage is so systemic. Every time I try to compile a list of PHP gripes, I get stuck in this depth-first search discovering more and more appalling trivia. (Hence, fractal.)

PHP is an embarrassment, a blight upon my craft. It’s so broken, but so lauded by every empowered amateur who’s yet to learn anything else, as to be maddening. It has paltry few redeeming qualities and I would prefer to forget it exists at all.

But I’ve got to get this out of my system. So here goes, one last try.

An analogy

I just blurted this out to Mel to explain my frustration and she insisted that I reproduce it here.

I can’t even say what’s wrong with PHP, because— okay. Imagine you have uh, a toolbox. A set of tools. Looks okay, standard stuff in there.

You pull out a screwdriver, and you see it’s one of those weird tri-headed things. Okay, well, that’s not very useful to you, but you guess it comes in handy sometimes.

You pull out the hammer, but to your dismay, it has the claw part on both sides. Still serviceable though, I mean, you can hit nails with the middle of the head holding it sideways.

You pull out the pliers, but they don’t have those serrated surfaces; it’s flat and smooth. That’s less useful, but it still turns bolts well enough, so whatever.

And on you go. Everything in the box is kind of weird and quirky, but maybe not enough to make it completely worthless. And there’s no clear problem with the set as a whole; it still has all the tools.

Now imagine you meet millions of carpenters using this toolbox who tell you “well hey what’s the problem with these tools? They’re all I’ve ever used and they work fine!” And the carpenters show you the houses they’ve built, where every room is a pentagon and the roof is upside-down. And you knock on the front door and it just collapses inwards and they all yell at you for breaking their door.

That’s what’s wrong with PHP.


I assert that the following qualities are important for making a language productive and useful, and PHP violates them with wild abandon. If you can’t agree that these are crucial, well, I can’t imagine how we’ll ever agree on much.

  • A language must be predictable. It’s a medium for expressing human ideas and having a computer execute them, so it’s critical that a human’s understanding of a program actually be correct.
  • A language must be consistent. Similar things should look similar, different things different. Knowing part of the language should aid in learning and understanding the rest.
  • A language must be concise. New languages exist to reduce the boilerplate inherent in old languages. (We could all write machine code.) A language must thus strive to avoid introducing new boilerplate of its own.
  • A language must be reliable. Languages are tools for solving problems; they should minimize any new problems they introduce. Any “gotchas” are massive distractions.
  • A language must be debuggable. When something goes wrong, the programmer has to fix it, and we need all the help we can get.

My position is thus:

  • PHP is full of surprises: mysql_real_escape_string, E_ALL
  • PHP is inconsistent: strpos, str_rot13
  • PHP requires boilerplate: error-checking around C API calls, ===
  • PHP is flaky: ==, foreach ($foo as &$bar)
  • PHP is opaque: no stack traces by default or for fatals, complex error reporting

I can’t provide a paragraph of commentary for every single issue explaining why it falls into these categories, or this would be endless. I trust the reader to, like, think.

Don’t comment with these things

I’ve been in PHP arguments a lot. I hear a lot of very generic counter-arguments that are really only designed to halt the conversation immediately. Don’t pull these on me, please. 🙁

  • Do not tell me that “good developers can write good code in any language”, or bad developers blah blah. That doesn’t mean anything. A good carpenter can drive in a nail with either a rock or a hammer, but how many carpenters do you see bashing stuff with rocks? Part of what makes a good developer is the ability to choose the tools that work best.
  • Do not tell me that it’s the developer’s responsibility to memorize a thousand strange exceptions and surprising behaviors. Yes, this is necessary in any system, because computers suck. That doesn’t mean there’s no upper limit for how much zaniness is acceptable in a system. PHP is nothing but exceptions, and it is not okay when wrestling the language takes more effort than actually writing your program. My tools should not create net positive work for me to do.
  • Do not tell me “that’s how the C API works”. What on Earth is the point of using a high-level language if all it provides are some string helpers and a ton of verbatim C wrappers? Just write C! Here, there’s even a CGI library for it.
  • Do not tell me “that’s what you get for doing weird things”. If two features exist, someday, someone will find a reason to use them together. And again, this isn’t C; there’s no spec, there’s no need for “undefined behavior”.
  • Do not tell me that Facebook and Wikipedia are built in PHP. I’m aware! They could also be written in Brainfuck, but as long as there are smart enough people wrangling the things, they can overcome problems with the platform. For all we know, development time could be halved or doubled if these products were written in some other language; this data point alone means nothing.
  • Ideally, don’t tell me anything! This is my one big shot; if this list doesn’t hurt your opinion of PHP, nothing ever will, so stop arguing with some dude on the Internet and go make a cool website in record time to prove me wrong 🙂

Side observation: I loooove Python. I will also happily talk your ear off complaining about it, if you really want me to. I don’t claim it’s perfect; I’ve just weighed its benefits against its problems and concluded it’s the best fit for things I want to do.

And I have never met a PHP developer who can do the same with PHP. But I’ve bumped into plenty who are quick to apologize for anything and everything PHP does. That mindset is terrifying.


Core language

CPAN has been called the “standard library of Perl”. That doesn’t say much about Perl’s standard library, but it makes the point that a solid core can build great things.


  • PHP was originally designed explicitly for non-programmers (and, reading between the lines, non-programs); it has not well escaped its roots. A choice quote from the PHP 2.0 documentation, regarding + and friends doing type conversion:

    Once you start having separate operators for each type you start making the language much more complex. ie. you can’t use ‘==’ for stings [sic], you now would use ‘eq’. I don’t see the point, especially for something like PHP where most of the scripts will be rather simple and in most cases written by non-programmers who want a language with a basic logical syntax that doesn’t have too high a learning curve.

  • PHP is built to keep chugging along at all costs. When faced with either doing something nonsensical or aborting with an error, it will do something nonsensical. Anything is better than nothing.
  • There’s no clear design philosophy. Early PHP was inspired by Perl; the huge stdlib with “out” params is from C; the OO parts are designed like C++ and Java.
  • PHP takes vast amounts of inspiration from other languages, yet still manages to be incomprehensible to anyone who knows those languages. (int) looks like C, but int doesn’t exist. Namespaces use \. The new array syntax results in [key => value], unique among every language with hash literals.
  • Weak typing (i.e., silent automatic conversion between strings/numbers/et al) is so complex that whatever minor programmer effort is saved is by no means worth it.
  • Little new functionality is implemented as new syntax; most of it is done with functions or things that look like functions. Except for class support, which deserved a slew of new operators and keywords.
  • Some of the problems listed on this page do have first-party solutions—if you’re willing to pay Zend for fixes to their open-source programming language.
  • There is a whole lot of action at a distance. Consider this code, taken from the PHP docs somewhere.
    @fopen('', 'r');

    What will it do?

    • If PHP was compiled with --disable-url-fopen-wrapper, it won’t work. (Docs don’t say what “won’t work” means; returns null, throws exception?) Note that this flag was removed in PHP 5.2.5.
    • If allow_url_fopen is disabled in php.ini, this still won’t work. (How? No idea.)
    • Because of the @, the warning about the non-existent file won’t be printed.
    • But it will be printed if scream.enabled is set in php.ini.
    • Or if scream.enabled is set manually with ini_set.
    • But not if the right error_reporting level isn’t set.
    • If it is printed, exactly where it goes depends on display_errors, again in php.ini. Or ini_set.

    I can’t tell how this innocuous function call will behave without consulting compile-time flags, server-wide configuration, and configuration done in my program. And this is all built in behavior.

  • The language is full of global and implicit state. mbstring uses a global character set. func_get_arg and friends look like regular functions, but operate on the currently-executing function. Error/exception handling have global defaults. register_tick_function sets a global function to run every tick—what?!
  • There is no threading support whatsoever. (Not surprising, given the above.) Combined with the lack of built-in fork (mentioned below), this makes parallel programming extremely difficult.
  • Parts of PHP are practically designed to produce buggy code.
    • json_decode returns null for invalid input, even though null is also a perfectly valid object for JSON to decode to—this function is completely unreliable unless you also call json_last_error every time you use it.
    • array_search, strpos, and similar functions return 0 if they find the needle at position zero, but false if they don’t find it at all.

    Let me expand on that last part a bit.

    In C, functions like strpos return -1 if the item isn’t found. If you don’t check for that case and try to use that as an index, you’ll hit junk memory and your program will blow up. (Probably. It’s C. Who the fuck knows. I’m sure there are tools for this, at least.)

    In, say, Python, the equivalent .index methods will raise an exception if the item isn’t found. If you don’t check for that case, your program will blow up.

    In PHP, these functions return false. If you use FALSE as an index, or do much of anything with it except compare with ===, PHP will silently convert it to 0 for you. Your program will not blow up; it will, instead, do the wrong thing with no warning, unless you remember to include the right boilerplate around every place you use strpos and certain other functions.

    This is bad! Programming languages are tools; they’re supposed to work with me. Here, PHP has actively created a subtle trap for me to fall into, and I have to be vigilant even with such mundane things as string operations and equality comparison. PHP is a minefield.

I have heard a great many stories about the PHP interpreter and its developers from a great many places. These are from people who have worked on the PHP core, debugged PHP core, interacted with core developers. Not a single tale has been a compliment.

So I have to fit this in here, because it bears repeating: PHP is a community of amateurs. Very few people designing it, working on it, or writing code in it seem to know what they’re doing. (Oh, dear reader, you are of course a rare exception!) Those who do grow a clue tend to drift away to other platforms, reducing the average competence of the whole. This, right here, is the biggest problem with PHP: it is absolutely the blind leading the blind.

Okay, back to facts.


  • == is useless.
    • It’s not transitive. "foo" == TRUE, and "foo" == 0… but, of course, TRUE != 0.
    • == converts to numbers when possible (123 == "123foo"… although "123" != "123foo"), which means it converts to floats when possible. So large hex strings (like, say, password hashes) may occasionally compare true when they’re not. Even JavaScript doesn’t do this.
    • For the same reason, "6" == " 6", "4.2" == "4.20", and "133" == "0133". But note that 133 != 0133, because 0133 is octal. But "0x10" == "16" and "1e3" == "1000"!
    • === compares values and type… except with objects, where === is only true if both operands are actually the same object! For objects, == compares both value (of every attribute) and type, which is what === does for every other type. What.
  • Comparison isn’t much better.
    • It’s not even consistent: NULL < -1, and NULL == 0. Sorting is thus nondeterministic; it depends on the order in which the sort algorithm happens to compare elements.
    • The comparison operators try to sort arrays, two different ways: first by length, then by elements. If they have the same number of elements but different sets of keys, though, they are uncomparable.
    • Objects compare as greater than anything else… except other objects, which they are neither less than nor greater than.
    • For a more type-safe ==, we have ===. For a more type-safe <, we have… nothing. "123" < "0124", always, no matter what you do. Casting doesn’t help, either.
  • Despite the craziness above, and the explicit rejection of Perl’s pairs of string and numeric operators, PHP does not overload +. + is always addition, and . is always concatenation.
  • The [] indexing operator can also be spelled {}.
  • [] can be used on any variable, not just strings and arrays. It returns null and issues no warning.
  • [] cannot slice; it only retrieves individual elements.
  • foo()[0] is a syntax error. (Fixed in PHP 5.4.)
  • Unlike (literally!) every other language with a similar operator, ?: is left associative. So this:
    $arg = 'T';
    $vehicle = ( ( $arg == 'B' ) ? 'bus' :
                 ( $arg == 'A' ) ? 'airplane' :
                 ( $arg == 'T' ) ? 'train' :
                 ( $arg == 'C' ) ? 'car' :
                 ( $arg == 'H' ) ? 'horse' :
                 'feet' );
    echo $vehicle;

    prints horse.


  • There is no way to declare a variable. Variables that don’t exist are created with a null value when first used.
  • Global variables need a global declaration before they can be used. This is a natural consequence of the above, so it would be perfectly reasonable, except that globals can’t even be read without an explicit declaration—PHP will quietly create a local with the same name, instead. I’m not aware of another language with similar scoping issues.
  • There are no references. What PHP calls references are really aliases; there’s nothing that’s a step back, like Perl’s references, and there’s no pass-by-object identity like in Python.
  • Referenceness” infects a variable unlike anything else in the language. PHP is dynamically-typed, so variables generally have no type… except references, which adorn function definitions, variable syntax, and assignment. Once a variable is made a reference (which can happen anywhere), it’s stuck as a reference. There’s no obvious way to detect this and un-referencing requires nuking the variable entirely.
  • Okay, I lied. There are “SPL types” which also infect variables: $x = new SplBool(true); $x = "foo"; will fail. This is like static typing, you see.
  • A reference can be taken to a key that doesn’t exist within an undefined variable (which becomes an array). Using a non-existent array normally issues a notice, but this does not.
  • Constants are defined by a function call taking a string; before that, they don’t exist. (This may actually be a copy of Perl’s use constant behavior.)
  • Variable names are case-sensitive. Function and class names are not. This includes method names, which makes camelCase a strange choice for naming.


  • array() and a few dozen similar constructs are not functions. array on its own means nothing, $func = "array"; $func(); doesn’t work.
  • Array unpacking can be done with the list($a, $b) = ... operation. list() is function-like syntax just like array. I don’t know why this wasn’t given real dedicated syntax, or why the name is so obviously confusing.
  • (int) is obviously designed to look like C, but it’s a single token; there’s nothing called int in the language. Try it: not only does var_dump(int) not work, it throws a parse error because the argument looks like the cast operator.
  • (integer) is a synonym for (int). There’s also (bool)/(boolean) and (float)/(double)/(real).
  • There’s an (array) operator for casting to array and an (object) for casting to object. That sounds nuts, but there’s almost a use: you can use (array) to have a function argument that’s either a single item or a list, and treat it identically. Except you can’t do that reliably, because if someone passes a single object, casting it to an array will actually produce an array containing that object’s attributes. (Casting to object performs the reverse operation.)
  • include() and friends are basically C’s #include: they dump another source file into yours. There is no module system, even for PHP code.
  • There’s no such thing as a nested or locally-scoped function or class. They’re only global. Including a file dumps its variables into the current function’s scope (and gives the file access to your variables), but dumps functions and classes into global scope.
  • Appending to an array is done with $foo[] = $bar.
  • echo is a statement-y kind of thing, not a function.
  • empty($var) is so extremely not-a-function that anything but a variable, e.g. empty($var || $var2), is a parse error. Why on Earth does the parser need to know about empty? (Fixed in 5.5.)
  • There’s redundant syntax for blocks: if (...): ... endif;, etc.

Error handling

  • PHP’s one unique operator is @ (actually borrowed from DOS), which silences errors.
  • PHP errors don’t provide stack traces. You have to install a handler to generate them. (But you can’t for fatal errors—see below.)
  • PHP parse errors generally just spew the parse state and nothing more, making a forgotten quote terrible to debug.
  • PHP’s parser refers to e.g. :: internally as T_PAAMAYIM_NEKUDOTAYIM, and the << operator as T_SL. I say “internally”, but as above, this is what’s shown to the programmer when :: or << appears in the wrong place.
  • Most error handling is in the form of printing a line to a server log nobody reads and carrying on.
  • E_STRICT is a thing, but it doesn’t seem to actually prevent much and there’s no documentation on what it actually does.
  • E_ALL includes all error categories—except E_STRICT. (Fixed in 5.4.)
  • Weirdly inconsistent about what’s allowed and what isn’t. I don’t know how E_STRICT applies here, but these things are okay:
    • Trying to access a non-existent object property, i.e., $foo->x. (warning)
    • Using a variable as a function name, or variable name, or class name. (silent)
    • Trying to use an undefined constant. (notice)
    • Trying to access a property of something that isn’t an object. (notice)
    • Trying to use a variable name that doesn’t exist. (notice)
    • 2 < "foo" (silent)
    • foreach (2 as $foo); (warning)

    And these things are not:

    • Trying to access a non-existent class constant, i.e., $foo::x. (fatal error)
    • Using a constant string as a function name, or variable name, or class name. (parse error)
    • Trying to call an undefined function. (fatal error)
    • Leaving off a semicolon on the last statement in a block or file. (parse error)
    • Using list and various other quasi-builtins as method names. (parse error)
    • Subscripting the return value of a function, i.e., foo()[0]. (parse error; okay in 5.4, see above)

    There are a good few examples of other weird parse errors elsewhere in this list.

  • The __toString method can’t throw exceptions. If you try, PHP will… er, throw an exception. (Actually a fatal error, which would be passable, except…)
  • PHP errors and PHP exceptions are completely different beasts. They don’t seem to interact at all.
    • PHP errors (internal ones, and calls to trigger_error) cannot be caught with try/catch.
    • Likewise, exceptions do not trigger error handlers installed by set_error_handler.
    • Instead, there’s a separate set_exception_handler which handles uncaught exceptions, because wrapping your program’s entry point in a try block is impossible in the mod_php model.
    • Fatal errors (e.g., new ClassDoesntExist()) can’t be caught by anything. A lot of fairly innocuous things throw fatal errors, forcibly ending your program for questionable reasons. Shutdown functions still run, but they can’t get a stack trace (they run at top-level), and they can’t easily tell if the program exited due to an error or running to completion.
    • Trying to throw an object that isn’t an Exception results in… a fatal error, not an exception.
  • There is no finally construct, making wrapper code (set handler, run code, unset handler; monkeypatch, run a test, unmonkeypatch) tedious and difficult to write. Despite that OO and exceptions were largely copied from Java, this is deliberate, because finally doesn’t make much sense in the context of PHP”. Huh? (Fixed in 5.5.)


  • Function calls are apparently rather expensive.
  • Some built-in functions interact with reference-returning functions in, er, a strange way.
  • As mentioned elsewhere, a lot of things that look like functions or look like they should be functions are actually language constructs, so nothing that works with functions will work with them.
  • Function arguments can have “type hints”, which are basically just static typing. But you can’t require that an argument be an int or string or object or other “core” type, even though every builtin function uses this kind of typing, probably because int is not a thing in PHP. (See above about (int).) You also can’t use the special pseudo-type decorations used heavily by builtin functions: mixed, number, or callback. (callable is allowed as of PHP 5.4.)
    • As a result, this:
      function foo(string $s) {}
      foo("hello world");

      produces the error:

      PHP Catchable fatal error:  Argument 1 passed to foo() must be an instance of string, string given, called in...
    • You may notice that the “type hint” given doesn’t actually have to exist; there is no string class in this program. If you try to use ReflectionParameter::getClass() to examine the type hint dynamically, then it will balk that the class doesn’t exist, making it impossible to actually retrieve the class name.
    • A function’s return value can’t be hinted.
    • Passing the current function’s arguments to another function (dispatch, not uncommon) is done by call_user_func_array('other_function', func_get_args()). But func_get_args throws a fatal error at runtime, complaining that it can’t be a function parameter. How and why is this even a type of error? (Fixed in PHP 5.3.)
    • Closures require explicitly naming every variable to be closed-over. Why can’t the interpreter figure this out? Kind of hamstrings the whole feature. (Okay, it’s because using a variable ever, at all, creates it unless explicitly told otherwise.)
    • Closed-over variables are “passed” by the same semantics as other function arguments. That is, arrays and strings etc. will be “passed” to the closure by value. Unless you use &.
    • Because closed-over variables are effectively automatically-passed arguments and there are no nested scopes, a closure can’t refer to private methods, even if it’s defined inside a class. (Possibly fixed in 5.4? Unclear.)
    • No named arguments to functions. Actually explicitly rejected by the devs because it “makes for messier code”.
    • Function arguments with defaults can appear before function arguments without, even though the documentation points out that this is both weird and useless. (So why allow it?)
    • Extra arguments to a function are ignored (except with builtin functions, which raise an error). Missing arguments are assumed null.
    • Variadic” functions require faffing about with func_num_args, func_get_arg, and func_get_args. There’s no syntax for such a thing.


  • The procedural parts of PHP are designed like C, but the objectional (ho ho) parts are designed like Java. I cannot overemphasize how jarring this is. The class system is designed around the lower-level Java language which is naturally and deliberately more limited than PHP’s contemporaries, and I am baffled.
    • I’ve yet to find a global function that even has a capital letter in its name, yet important built-in classes use camelCase method names and have getFoo Java-style accessors.
    • Perl, Python, and Ruby all have some concept of “property” access via code; PHP has only the clunky __get and friends. (The documentation inexplicably refers to such special methods as “overloading”.)
    • Classes have something like variable declaration (var and const) for class attributes, whereas the procedural part of the language does not.
    • Despite the heavy influence from C++/Java, where objects are fairly opaque, PHP often treats objects like fancy hashes—for example, the default behavior of foreach ($obj as $key => $value) is to iterate over every accessible attribute of the object.
  • Classes are not objects. Any metaprogramming has to refer to them by string name, just like functions.
  • Built-in types are not objects and (unlike Perl) can in no way be made to look like objects.
  • instanceof is an operator, despite that classes were a late addition and most of the language is built on functions and function-ish syntax. Java influence? Classes not first-class? (I don’t know if they are.)
    • But there is an is_a function. With an optional argument specifying whether to allow the object to actually be a string naming a class.
    • get_class is a function; there’s no typeof operator. Likewise is_subclass_of.
    • This doesn’t work on builtin types, though (again, int is not a thing). For that, you need is_int etc.
    • Also the right-hand side has to be a variable or literal string; it can’t be an expression. That causes… a parse error.
  • clone is an operator?!
  • Object attributes are $obj->foo, but class attributes are Class::$foo. ($obj::$foo will try to stringify $obj and use it as a class name.) Class attributes can’t be accessed via objects; the namespaces are completely separate, making class attributes completely useless for polymorphism. Class methods, of course, are exempt from this rule and can be called like any other method. (I am told C++ also does this. C++ is not a good example of fine OO.)
  • Also, an instance method can still be called statically (Class::method()). If done so from another method, this is treated like a regular method call on the current $this. I think.
  • new, private, public, protected, static, etc. Trying to win over Java developers? I’m aware this is more personal taste, but I don’t know why this stuff is necessary in a dynamic language—in C++ most of it’s about compilation and compile-time name resolution.
  • PHP has first-class support for “abstract classes”, which are classes that cannot be instantiated. Code in similar languages achieves this by throwing an exception in the constructor.
  • Subclasses cannot override private methods. Subclass overrides of public methods can’t even see, let alone call, the superclass’s private methods. Problematic for, say, test mocks.
  • Methods cannot be named e.g. “list”, because list() is special syntax (not a function) and the parser gets confused. There’s no reason this should be ambiguous, and monkeypatching the class works fine. ($foo->list() is not a syntax error.)
  • If an exception is thrown while evaluating a constructor’s arguments (e.g., new Foo(bar()) and bar() throws), the constructor won’t be called, but the destructor will be. (This is fixed in PHP 5.3.)
  • Exceptions in __autoload and destructors cause fatal errors. (Fixed in PHP 5.3.6. So now a destructor might throw an exception literally anywhere, since it’s called the moment the refcount drops the zero. Hmm.)
  • There are no constructors or destructors. __construct is an initializer, like Python’s __init__. There is no method you can call on a class to allocate memory and create an object.
  • There is no default initializer. Calling parent::__construct() if the superclass doesn’t define its own __construct is a fatal error.
  • OO brings with it an iterator interface that parts of the language (e.g., respect, but nothing built-in (like arrays) actually implements the interface. If you want an array iterator, you have to wrap it in an ArrayIterator. There are no built-in ways to chain or slice or otherwise work with iterators as first-class objects.
  • Interfaces like Iterator reserve a good few unprefixed method names. If you want your class to be iterable (without the default behavior of iterating all of its attributes), but want to use a common method name like key or next or current, well, too bad.
  • Classes can overload how they convert to strings and how they act when called, but not how they convert to numbers or any other builtin type.
  • Strings, numbers, and arrays all have a string conversion; the language relies heavily on this. Functions and classes are strings. Yet trying to convert a built-in or user-defined object (even a Closure) to a string causes an error if it doesn’t define __toString. Even echo becomes potentially error-prone.
  • There is no overloading for equality or ordering.
  • Static variables inside instance methods are global; they share the same value across all instances of the class.

Standard library

Perl is “some assembly required”. Python is “batteries included”. PHP is “kitchen sink, but it’s from Canada and both faucets are labeled C“.


  • There is no module system. You can compile PHP extensions, but which ones are loaded is specified by php.ini, and your options are for an extension to exist (and inject its contents into your global namespace) or not.
  • As namespaces are a recent feature, the standard library isn’t broken up at all. There are thousands of functions in the global namespace.
  • Chunks of the library are wildly inconsistent from one another.
    • Underscore versus not: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/get_class
    • to” versus 2: ascii2ebcdic, bin2hex, deg2rad, strtolower, strtotime
    • Object+verb versus verb+object: base64_decode, str_shuffle, var_dump versus create_function, recode_string
    • Argument order: array_filter($input, $callback) versus array_map($callback, $input), strpos($haystack, $needle) versus array_search($needle, $haystack)
    • Prefix confusion: usleep versus microtime
    • Case insensitive functions vary on where the i goes in the name.
    • About half the array functions actually start with array_. The others do not.
    • htmlentities and html_entity_decode are inverses of each other, with completely different naming conventions.
  • Kitchen sink. The library includes:
    • Bindings to ImageMagick, bindings to GraphicsMagick (which is a fork of ImageMagick), and a handful of functions for inspecting EXIF data (which ImageMagick can already do).
    • Functions for parsing bbcode, a very specific kind of markup used by a handful of particular forum packages.
    • Way too many XML packages. DOM (OO), DOM XML (not), libxml, SimpleXML, “XML Parser”, XMLReader/XMLWriter, and half a dozen more acronyms I can’t identify. There’s surely some kind of difference between these things and you are free to go figure out what that is.
    • Bindings for two particular credit card processors, SPPLUS and MCVE. What?
    • Three ways to access a MySQL database: mysql, mysqli, and the PDO abstraction thing.

C influence

This deserves its own bullet point, because it’s so absurd yet permeates the language. PHP is a high-level, dynamically-typed programming language. Yet a massive portion of the standard library is still very thin wrappers around C APIs, with the following results:

  • Out” parameters, even though PHP can return ad-hoc hashes or multiple arguments with little effort.
  • At least a dozen functions for getting the last error from a particular subsystem (see below), even though PHP has had exceptions for eight years.
  • Warts like mysql_real_escape_string, even though it has the same arguments as the broken mysql_escape_string, just because it’s part of the MySQL C API.
  • Global behavior for non-global functionality (like MySQL). Using multiple MySQL connections apparently requires passing a connection handle on every function call.
  • The wrappers are really, really, really thin. For example, calling dba_nextkey without calling dba_firstkey will segfault.
  • The wrappers are often platform-specific: fopen(directory, "r") works on Linux but returns false and generates a warning on Windows.
  • There’s a set of ctype_* functions (e.g. ctype_alnum) that map to the C character-class detection functions of similar names, rather than, say, isupper.


There is none. If a function might need to do two slightly different things, PHP just has two functions.

How do you sort backwards? In Perl, you might do sort { $b <=> $a }. In Python, you might do .sort(reverse=True). In PHP, there’s a separate function called rsort().

  • Functions that look up a C error: curl_error, json_last_error, openssl_error_string, imap_errors, mysql_error, xml_get_error_code, bzerror, date_get_last_errors, others?
  • Functions that sort: array_multisort, arsort, asort, ksort, krsort, natsort, natcasesort, sort, rsort, uasort, uksort, usort
  • Functions that find text: ereg, eregi, mb_ereg, mb_eregi, preg_match, strstr, strchr, stristr, strrchr, strpos, stripos, strrpos, strripos, mb_strpos, mb_strrpos, plus the variations that do replacements
  • There are a lot of aliases as well, which certainly doesn’t help matters: strstr/strchr, is_int/is_integer/is_long, is_float/is_double, pos/current, sizeof/count, chop/rtrim, implode/join, die/exit, trigger_error/user_error, diskfreespace/disk_free_space
  • scandir returns a list of files within a given directory. Rather than (potentially usefully) return them in directory order, the function returns the files already sorted. And there’s an optional argument to get them in reverse alphabetical order. There were not, apparently, enough sort functions. (PHP 5.4 adds a third value for the sort-direction argument that will disable sorting.)
  • str_split breaks a string into chunks of equal length. chunk_split breaks a string into chunks of equal length, then joins them together with a delimiter.
  • Reading archives requires a separate set of functions depending on the format. There are six separate groups of such functions, all with different APIs, for bzip2, LZF, phar, rar, zip, and gzip/zlib.
  • Because calling a function with an array as its arguments is so awkward (call_user_func_array), there are some pairings like printf/vprintf and sprintf/vsprintf. These do the same things, but one function takes arguments and the other takes an array of arguments.


  • preg_replace with the /e (eval) flag will do a string replace of the matches into the replacement string, then eval it.
  • strtok is apparently designed after the equivalent C function, which is already a bad idea for various reasons. Nevermind that PHP can easily return an array (whereas this is awkward in C), or that the very hack strtok(3) uses (modifying the string in-place) isn’t used here.
  • parse_str parses a query string, with no indication of this in the name. Also it acts just like register_globals and dumps the query into your local scope as variables, unless you pass it an array to populate. (It returns nothing, of course.)
  • explode refuses to split with an empty/missing delimiter. Every other string split implementation anywhere does some useful default in this case; PHP instead has a totally separate function, confusingly called str_split and described as “converting a string to an array”.
  • For formatting dates, there’s strftime, which acts like the C API and respects locale. There’s also date, which has a completely different syntax and only works with English.
  • gzgetss — Get line from gz-file pointer and strip HTML tags.” I’m dying to know the series of circumstances that led to this function’s conception.
  • mbstring
    • It’s all about “multi-byte”, when the problem is character sets.
    • Still operates on regular strings. Has a single global “default” character set. Some functions allow specifying charset, but then it applies to all arguments and the return value.
    • Provides ereg_* functions, but those are deprecated. preg_* are out of luck, though they can understand UTF-8 by feeding them some PCRE-specific flag.

System and reflection

  • There are, in general, a whole lot of functions that blur the line between text and variables. compact and extract are just the tip of the iceberg.
  • There are several ways to actually be dynamic in PHP, and at a glance there are no obvious differences or relative benefits. classkit can modify user-defined classes; runkit supersedes it and can modify user-defined anything; the Reflection* classes can reflect on most parts of the language; there are a great many individual functions for reporting properties of functions and classes. Are these subsystems independent, related, redundant?
  • get_class($obj) returns the object’s class name. get_class() returns the name of the class the function is being called in. Setting aside that this one function does two radically different things: get_class(null)… acts like the latter. So you can’t trust it on an arbitrary value. Surprise!
  • The stream_* classes allow for implementing custom stream objects for use with fopen and other fileish builtins. “tell” cannot be implemented for internal reasons. (Also there are A LOT of functions involved with this system.)
  • register_tick_function will accept a closure object. unregister_tick_function will not; instead it throws an error complaining that the closure couldn’t be converted to a string.
  • php_uname tells you about the current OS. Unless PHP can’t tell what it’s running on; then it tells you about the OS it was built on. It doesn’t tell you if this has happened.
  • fork and exec are not built in. They come with the pcntl extension, but that isn’t included by default. popen doesn’t provide a pid.
  • stats return value is cached.
  • session_decode is for reading an arbitrary PHP session string, but it only works if there’s an active session already. And it dumps the result into $_SESSION, rather than returning it.


  • curl_multi_exec doesn’t change curl_errno on error, but it does change curl_error.
  • mktimes arguments are, in order: hour, minute, second, month, day, year.

Data manipulation

Programs are nothing more than big machines that chew up data and spit out more data. A great many languages are designed around the kinds of data they manipulate, from awk to Prolog to C. If a language can’t handle data, it can’t do anything.


  • Integers are signed and 32-bit on 32-bit platforms. Unlike all of PHP’s contemporaries, there is no automatic bigint promotion. So you can end up with surprises like negative file sizes, and your math might work differently based on CPU architecture. Your only option for larger integers is to use the GMP or BC wrapper functions. (The developers have proposed adding a new, separate, 64-bit type. This is crazy.)
  • PHP supports octal syntax with a leading 0, so e.g. 012 will be the number ten. However, 08 becomes the number zero. The 8 (or 9) and any following digits disappear. 01c is a syntax error.
  • 0x0+2 produces 4. The parser considers the 2 as both part of the hex literal and a separate decimal literal, treating this as 0x002 + 2. 0x0+0x2 displays the same problem. Strangely, 0x0 +2 is still 4, but 0x0+ 2 is correctly 2. (This is fixed in PHP 5.4. But it’s also re-broken in PHP 5.4, with the new 0b literal prefix: 0b0+1 produces 2.)
  • pi is a function. Or there’s a constant, M_PI.
  • There is no exponentiation operator, only the pow function.


  • No Unicode support. Only ASCII will work reliably, really. There’s the mbstring extension, mentioned above, but it kinda blows.
  • Which means that using the builtin string functions on UTF-8 text risks corrupting it.
  • Similarly, there’s no concept of e.g. case comparisons outside of ASCII. Despite the proliferation of case-insensitive versions of functions, not one of them will consider é equal to É.
  • You can’t quote keys in variable interpolation, i.e., "$foo['key']" is a syntax error. You can unquote it (which would generate a warning anywhere else!), or use ${...}/{$...}.
  • "${foo[0]}" is okay. "${foo[0][0]}" is a syntax error. Putting the $ on the inside is fine with both. Bad copy of similar Perl syntax (with radically different semantics)?


Oh, man.

  • This one datatype acts as a list, ordered hash, ordered set, sparse list, and occasionally some strange combination of those. How does it perform? What kind of memory use will there be? Who knows? Not like I have other options, anyway.
  • => isn’t an operator. It’s a special construct that only exists inside array(...) and the foreach construct.
  • Negative indexing doesn’t work, since -1 is just as valid a key as 0.
  • Despite that this is the language’s only data structure, there is no shortcut syntax for it; array(...) is shortcut syntax. (PHP 5.4 is bringing “literals”, [...].)
  • Similarly baffling, arrays stringify to Array with an E_NOTICE.
  • The => construct is based on Perl, which allows foo => 1 without quoting. (That is, in fact, why it exists in Perl; otherwise it’s just a comma.) In PHP, you can’t do this without getting a warning; it’s the only language in its niche that has no vetted way to create a hash without quoting string keys.
  • Array functions often have confusing or inconsistent behavior because they have to operate on lists, hashes, or maybe a combination of the two. Consider array_diff, which “computers the difference of arrays”.
    $first  = array("foo" => 123, "bar" => 456);
    $second = array("foo" => 456, "bar" => 123);
    echo var_dump(array_diff($first, $second));

    What will this code do? If array_diff treats its arguments as hashes, then obviously these are different; the same keys have different values. If it treats them as lists, then they’re still different; the values are in the wrong order.

    In fact array_diff considers these equal, because it treats them like sets: it compares only values, and ignores order.

  • In a similar vein, array_rand has the strange behavior of selecting random keys, which is not that helpful for the most common case of needing to pick from a list of choices.
  • Despite how heavily PHP code relies on preserving key order:
    array("foo", "bar") != array("bar", "foo")
    array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1)

    I leave it to the reader to figure out what happens if the arrays are mixed. (I don’t know.)

  • array_fill cannot create zero-length arrays; instead it will issue a warning and return false.
  • All of the (many…) sort functions operate in-place and return nothing. There is no way to create a new sorted copy; you have to copy the array yourself, then sort it, then use the array.
  • But array_reverse returns a new array.
  • A list of ordered things and some mapping of keys to values sounds kind of like a great way to handle function arguments, but no.

Not arrays

  • The standard library includes “Quickhash”, an OO implementation of “specific strongly-typed classes” for implementing hashes. And, indeed, there are four classes, each dealing with a different combination of key and value types. It’s unclear why the builtin array implementation can’t optimize for these extremely common cases, or what the relative performance is.
  • There’s an ArrayObject class (which implements five different interfaces) that can wrap an array and have it act like an object. User classes can implement the same interfaces. But it only has a handful of methods, half of which don’t resemble built-in array functions, and built-in array functions don’t know how to operate on an ArrayObject or other array-like class.


  • Functions are not data. Closures are actually objects, but regular functions are not. You can’t even refer to them with their bare names; var_dump(strstr) issues a warning and assumes you mean the literal string, "strstr". There is no way to discern between an arbitrary string and a function “reference”.
  • create_function is basically a wrapper around eval. It creates a function with a regular name and installs it globally (so it will never be garbage collected—don’t use in a loop!). It doesn’t actually know anything about the current scope, so it’s not a closure. The name contains a NUL byte so it can never conflict with a regular function (because PHP’s parser fails if there’s a NUL in a file anywhere).
  • Declaring a function named __lambda_func will break create_function—the actual implementation is to eval-create the function named __lambda_func, then internally rename it to the broken name. If __lambda_func already exists, the first part will throw a fatal error.


  • Incrementing (++) a NULL produces 1. Decrementing (--) a NULL produces NULL. Decrementing a string likewise leaves it unchanged.
  • There are no generators. (Fixed in 5.5. Wow. They basically cloned the entire Python generator API, too. Impressive. Somehow, though, $foo = yield $bar; is a syntax error; it has to be $foo = (yield $bar). Sigh.)

Web framework


  • A single shared file, php.ini, controls massive parts of PHP’s functionality and introduces complex rules regarding what overrides what and when. PHP software that expects to be deployed on arbitrary machines has to override settings anyway to normalize its environment, which largely defeats the use of a mechanism like php.ini anyway.
    • PHP looks for php.ini in a variety of places, so it may (or may not…) be possible to override your host’s. Only one such file will ever be parsed, though, so you can’t just override a couple settings and call it a day.
  • PHP basically runs as CGI. Every time a page is hit, PHP recompiles the whole thing before executing it. Even dev servers for Python toy frameworks don’t act like this.This has led to a whole market of “PHP accelerators” that just compile once, accelerating PHP all the way to any other language. Zend, the company behind PHP, has made this part of their business model.
  • For quite a long time, PHP errors went to the client by default—I guess to help during development. I don’t think this is true any more, but I still see the occasional mysql error spew at the top of a page.
  • PHP is full of strange “easter eggs” like producing the PHP logo with the right query argument. Not only is this completely irrelevant to building your application, but it allows detecting whether you’re using PHP (and perhaps roughly guessing what version), regardless of how much mod_rewrite, FastCGI, reverse proxying, or Server: configuration you’re doing.
  • Blank lines before or after the <?php ... ?> tags, even in libraries, count as literal text and is interpolated into the response (or causes “headers already sent” errors). Your options are to either strictly avoid extra blank lines at the end of every file (the one after the ?> doesn’t count) or to just leave off the ?> closing token.


Deployment is often cited as the biggest advantage of PHP: drop some files and you’re done. Indeed, that’s much easier than running a whole process as you may have to do with Python or Ruby or Perl. But PHP leaves plenty to be desired.

Across the board, I’m in favor of running Web applications as app servers and reverse-proxying to them. It takes minimal effort to set this up, and the benefits are plenty: you can manage your web server and app separately, you can run as many or few app processes on as many machines as you want without needing more web servers, you can run the app as a different user with zero effort, you can switch web servers, you can take down the app without touching the web server, you can do seamless deployment by just switching where a fifo points, etc. Welding your application to your web server is absurd and there’s no good reason to do it any more.

  • PHP is naturally tied to Apache. Running it separately, or with any other webserver, requires just as much mucking around (possibly more) as deploying any other language.
  • php.ini applies to every PHP application run anywhere. There is only one php.ini file, and it applies globally; if you’re on a shared server and need to change it, or if you run two applications that need different settings, you’re out of luck; you have to apply the union of all necessary settings and pare them down from inside the apps themselves using ini_set or in Apache’s configuration file or in .htaccess. If you can. Also wow that is a lot of places you need to check to figure out how a setting is getting its value.
  • Similarly, there is no easy way to “insulate” a PHP application and its dependencies from the rest of a system. Running two applications that require different versions of a library, or even PHP itself? Start by building a second copy of Apache.
  • The “bunch of files” approach, besides making routing a huge pain in the ass, also means you have to carefully whitelist or blacklist what stuff is actually available, because your URL hierarchy is also your entire code tree. Configuration files and other “partials” need C-like guards to prevent them from being loaded directly. Version control noise (e.g., .svn) needs protecting. With mod_php, everything on your filesystem is a potential entry point; with an app server, there’s only one entry point, and only the URL controls whether it’s invoked.
  • You can’t seamlessly upgrade a bunch of files that run CGI-style, unless you want crashes and undefined behavior as users hit your site halfway through the upgrade.
  • Despite how “simple” it is to configure Apache to run PHP, there are some subtle traps even there. While the PHP docs suggest using SetHandler to make .php files run as PHP, AddHandler appears to work just as well, and in fact Google gives me twice as many results for it. Here’s the problem.When you use AddHandler, you are telling Apache that “execute this as php” is one possible way to handle .php files. But! Apache doesn’t have the same idea of file extensions that every human being on the planet does. It’s designed to support, say, index.html.en being recognized as both English and HTML. To Apache, a file can have any number of file extensions simultaneously.

    Imagine you have a file upload form that dumps files into some public directory. To make sure nobody uploads PHP files, you just check that they don’t have a .php extension. All an attacker has to do is upload a file named foo.php.txt; your uploader won’t see a problem, but Apache will recognize it as PHP, and it will happily execute.

    The problem here isn’t “using the original filename” or “not validating better”; the problem is that your web server is configured to run any old code it runs across—precisely the same property that makes PHP “easy to deploy”. CGI required +x, which was something, but PHP doesn’t even do that. And this is no theoretical problem; I’ve found multiple live sites with this issue.

Missing features

I consider all of these to be varying levels of critical for building a Web application. It seems reasonable that PHP, with its major selling point being that it’s a “Web language”, ought to have some of them.

  • No template system. There’s PHP itself, but nothing that acts as a big interpolator rather than a program.
  • No XSS filter. No, “remember to use htmlspecialchars” is not an XSS filter. This is.
  • No CSRF protection. You get to do it yourself.
  • No generic standard database API. Stuff like PDO has to wrap every individual database’s API to abstract the differences away.
  • No routing. Your website looks exactly like your filesystem. Many developers have been tricked into thinking mod_rewrite (and .htaccess in general) is an acceptable substitute.
  • No authentication or authorization.
  • No dev server. (“Fixed” in 5.4. Led to the Content-Length vuln below. Also, you have to port all your rewrite rules to a PHP wrapper thing, because there’s no routing.)
  • No interactive debugging.
  • No coherent deployment mechanism; only “copy all these files to the server”.


Language boundaries

PHP’s poor security reputation is largely because it will take arbitrary data from one language and dump it into another. This is a bad idea. "<script>" may not mean anything in SQL, but it sure does in HTML.

Making this worse is the common cry for “sanitizing your inputs”. That’s completely wrong; you can’t wave a magic wand to make a chunk of data inherently “clean”. What you need to do is speak the language: use placeholders with SQL, use argument lists when spawning processes, etc.

  • PHP outright encourages “sanitizing”: there’s an entire data filtering extension for doing it.
  • All the addslashes, stripslashes, and other slashes-related nonsense are red herrings that don’t help anything.
  • There is, as far as I can tell, no way to safely spawn a process. You can ONLY execute a string via the shell. Your options are to escape like crazy and hope the default shell uses the right escaping, or pcntl_fork and pcntl_exec manually.
  • Both escapeshellcmd and escapeshellarg exist with roughly similar descriptions. Note that on Windows, escapeshellarg does not work (because it assumes Bourne shell semantics), and escapeshellcmd just replaces a bunch of punctuation with spaces because nobody can figure out Windows cmd escaping (which may silently wreck whatever you’re trying to do).
  • The original built-in MySQL bindings, still widely-used, have no way to create prepared statements.

To this day, the PHP documentation on SQL injection recommends batty practices like type-checking, using sprintf and is_numeric, manually using mysql_real_escape_string everywhere, or manually using addslashes everywhere (which “may be useful”!). There is no mention of PDO or paramaterization, except in the user comments. I complained about this very specifically to a PHP dev at least two years ago, he was alarmed, and the page has never changed.


  • register_globals. It’s been off by default for a while by now, and it’s gone in 5.4. I don’t care. This is an embarrassment.
  • include accepting HTTP URLs. Likewise.
  • Magic quotes. So close to secure-by-default, and yet so far from understanding the concept at all. And, likewise.
  • You can, say, probe a network using PHP’s XML support, by abusing its ubiquitous support for filenames-as-URLs. Only libxml_disable_entity_loader() can fix this, and the problem is only mentioned in the manual comments.

(5.5 brings a just-do-it password hashing function, password_hash, which should hopefully cut down on hand-rolled crypto code.)


The PHP interpreter itself has had some fascinating security problems.

  • In 2007 the interpreter had an integer overflow vulnerability. The fix started with if (size > INT_MAX) return NULL; and went downhill from there. (For those not down with the C: INT_MAX is the biggest integer that will fit in a variable, ever. I hope you can figure out the rest from there.)
  • More recently, PHP 5.3.7 managed to include a crypt() function that would, in effect, let anyone log in with any password.
  • PHP 5.4’s dev server is vulnerable to a denial of service, because it takes the Content-Length header (which anyone can set to anything) and tries to allocate that much memory. This is a bad idea.

I could dig up more but the point isn’t that there are X many exploits—software has bugs, it happens, whatever. The nature of these is horrifying. And I didn’t seek these out; they just happened to land on my doorstep in the last few months.


Some commentary has rightfully pointed out that I don’t have a conclusion. And, well, I don’t have a conclusion. If you got all the way down here, I assumed you agreed with me before you started 🙂

If you only know PHP and you’re curious to learn something else, give the Python tutorial a whirl and try Flask for the web stuff. (I’m not a huge fan of its template language, but it does the job.) It breaks apart the pieces of your app, but they’re still the same pieces and should look familiar enough. I might write a real post about this later; a whirlwind introduction to an entire language and web stack doesn’t belong down here.

Later or for bigger projects you may want Pyramid, which is medium-level, or Django, which is a complex monstrosity that works well for building sites like Django’s.

If you’re not a developer at all but still read this for some reason, I will not be happy until everyone on the planet has gone through Learn Python The Hard Way so go do that.

There’s also Ruby with Rails and some competitors I’ve never used, and Perl is still alive and kicking with Catalyst. Read things, learn things, build things, go nuts.


Thanks to the following for inspiration:

Let me know if you have any additions, or if I’m (factually!) wrong about something.


Finding Time to Become a Better Developer

There’s no time for anything. At least that’s how it feels doesn’t it? No time to learn all the things you think you need to learn to stay ahead of the curve. No time to go back and refactor that ugly piece of code. It works (sort of) and there’s a deadline approaching. No time to write unit tests for everything. No time to write documentation or comments for the next guy who gets stuck maintaining what you wrote. No time to think. No time to breathe. No time!

Well… if you take the time to read this article, I promise you’ll find yourself with more time for what’s important.

I used to think that the only way to be a great developer was to work myself sick. My health, friendships, and family all suffered because of it. Understanding the following 5 truths about time management for a developer is what saved me.

1. You don’t need to learn every new thing in order to stay relevant.

There is no question that a good developer should always be learning, but where you focus your learning can make a huge difference in the amount of time it takes to stay on top of your game.

“The old thing is dead. Long live the NEW, about-to-be-old thing!”

First of all, don’t get suckered in by headlines on dev blogs that announce a new standard every 37 seconds. Most new technologies, frameworks, and features will never get any real traction and you’ll never need to know them. Those that do emerge will take a lot longer to gain adoption than the blogosphere — and the vendors who hock these new technologies — would have you believe. Companies are invested in their tech stack and, other than a handful of tiny tech startups, they can’t just turn on a dime. So, relax, your career is safe.

Focus your learning on three areas, in the following order of priority:

  1. Fundamentals — It’s a lot easier to pick up new skills when you have a real command of the underlying fundamentals. For example, if you understand JavaScript deeply, you can master any new JavaScript framework in record speed. If you understand Object Oriented Programming deeply, you can master new object oriented languages quickly, too. Deeply learning the fundamentals will 10x your learning efficiency. Always focus on improving fundamentals above all else.
  2. The latest version/feature of the stack(s) you use the most — There’s a stack of technologies that you probably use every day. These are the tools that will put food on the table for you and your family. When new versions of these tools are released, it’s worth investing the time to learn about them.
  3. In-demand tech that is backed by market leaders — if a big, well established company like Google, Facebook, or Microsoft puts out something new and it starts getting some buzz, it’s worth looking into. There were a hundred and one JavaScript frameworks all vying for attention and then Angular and React showed up and wiped them off the map. I’m not saying there won’t be disruptors that come from nowhere and become the next big thing but, more often than not, no-name tech is just noise.

Learning time should be a part of your schedule. Set aside a specific amount of time for learning every day. It doesn’t need to be a lot of time, even 25 minutes of reading and experimentation every day adds up quickly.

2. Writing good code takes less time than writing bad code, BUT it doesn’t feel that way.

You probably feel like the time you spend on a new feature ends when you run the code and it appears to work. But that’s just the beginning of your time investment. Time spent on a feature includes time spent debugging that feature later and also time spent refactoring and working other code around any poor design decisions you made when implementing that feature. When you start to understand your time investment this way, it becomes obvious that, in the long run, fewer errors and better design are a worthwhile investment.

There are two things you can do that will reduce errors in your code and lead to better design.

  1. Use test-driven development. Write the test first, then write the code that satisfies the test. This not only leads to less buggy code but also to better design, because when you have to structure code in a testable way, you end up making smaller, simpler functions that have fewer dependencies.
  2. Use an iterative design approach. Don’t spend time trying to make code perfect before you’ve spent time trying to make the code work. You’ll never, ever get it right completely in your head. You have to get those fingers banging on a keyboard and produce code that runs and does what’s expected. The problem is that developers tend to make one of two common mistakes; either they spend too much time thinking and not enough time actually doing, or they don’t spend enough time improving their first solution. Follow the mantra first stated by Kent Beck: “make it work, make it right, make it fast” — and in that order.

3. Working 24/7 does NOT make you a hero. Managing expectations does.

This is the one that nearly killed me. I used to agree and commit to any crazy timeline my boss or client could come up with. I was afraid of saying “no.” I was afraid of letting anyone down. I would do whatever it took to deliver. I have literally slept under my desk, and pulled multiple caffeine-fueled 40+ hour marathon coding sessions.

At first I was a shining star. I would get a big pat on the back and I felt like a hero. But I set an expectation that was impossible to live up to. Working like that is unsustainable. Eventually, I started to burn out, get sick, and miss deadlines. I started getting a reputation as unreliable and inconsistent. It was bad news.

What I eventually came to understand, and what you should commit to learning too, is that the real heroes are the ones who are consistently reliable. They say what they’ll do and do what they say. The only way to be that kind of hero is to manage expectations.

You need to take control of the timelines so that you are always and without fail delivering high quality work exactly on time. This is incredibly difficult at first. It means having to say “no” and having to push back.

In the beginning, your boss or client won’t be thrilled by your resistance, but once you demonstrate that you are trustworthy and reliable, everything will start to change.

Over time, other developers will be late, deliver sloppy work, or burn out and become unreliable. Then you will become the real hero of your team. In fact, learning this made me one of the most in demand consultants in my market. I’ve built a stellar reputation for quality and timeliness, because I vigorously manage expectations.

4. Not all time spent “improving” code has the same ROI.

Spending time is an investment. Like all investments, it’s reasonable to expect a return on investment (ROI). You should be getting back at least as much — and hopefully more — value than you put in.

We talked about “make it work, make it right, make it fast.” It’s a good mantra but there is a trap: “right” does not mean perfect, and “fast” does not mean absolutely as fast as possible.

“Right” means that the code works consistently and is easy to refactor. “Fast” means that the speed of execution does not have a negative impact on the overall user experience. The most important thing is that your application feels fast to the user.

So, don’t waste time trying to shave time off a function that is barely used, or trying to save another few milliseconds on something that already runs faster than a human can blink (~300ms). And don’t waste time trying to refactor working, well-structured code because you just learned some new technique or approach that you’ve convinced yourself you suddenly have to go back and apply to everything you’ve ever done.

5. Scheduled down time makes you more productive.

This was a very hard one for me to learn and accept. How can you possibly be more productive when you’re not spending all your time producing? Well, it’s true.

According to Allison Gabriel, an assistant professor of management at Virginia Commonwealth University who studies job demands and employee motivation, “There is a lot of research that says we have a limited pool of cognitive resources. When you are constantly draining your resources, you are not being as productive as you can be. If you get depleted, we see performance decline. You’re able to persist less and have trouble solving tasks”.

Always working sets off strain reactions, such as stress, fatigue, and negative mood. These drain your focus and your physical and emotional resources.

The brain’s ability to self-regulate — to stay disciplined — wanes with each exercise of self-control during the day. It’s a loss of resources that must be replenished. Otherwise it becomes harder to stay on-task, be attentive and solve problems.

Your mind and body need down time, and they’re going to get it whether you like it or not. So, schedule that down time. Actually plan and put on your calendar real scheduled breaks. This will allow you to take down time without feeling guilty about it. It will make work-time easier to endure because you’ll know that you have a scheduled break right around the corner.

The Sad State of Web Development

The Sad State of Web Development

Random thoughts on web development

Going to shit

2015 is when web development went to shit. Web development used to be nice. You could fire up a text editor and start creating JS and CSS files. You can absolutely still do this. That has not changed. So yes, everything I’m about to say can be invalidated by saying that.

The web (specifically the Javascript/Node community) has created some of the most complicated, convoluted, over engineered tools ever conceived.


At times, I think where web development is at this point is some cruel joke played on us by Ryan Dahl. You see, to get into why web development is so terrible, you have to start at Node.

By definition I was a magpie developer, so undoubtedly I used Node, just as everyone should. At universities they should make every developer write an app with Node.js, deploy it to production, then try to update the dependencies 3 months later. The only downside is we would have zero new developers coming out of computer science programs.

Lets take everything that was great in Ruby and re write it in Javascript, I think was the official motto.

Most of the smart magpies have moved on to Go at this point, but the people who have stayed in the Node community have undoubtedly created the most over engineered eco system that has ever appeared. No one can create a library that does anything. Every project that creeps up is even more ambitious than the next. It all starts with a core module and 400 plugins for this module. No one will build something that actually does anything. I just don’t understand. The only thing I can think, is people are just constantly re writing Node.js apps over and over.

Javascript has zero standard library, so as soon as you npm init a new Node app you better install at least 15 terabytes of modules to get 1/16th the standard lib of something like Ruby or Go. It may seem super cool to have all these small modules until you try to update them. When the developer who created that module doesn’t follow semver, so you’re fucked. Sorry. To the people who say I’m wrong about this; STOP rewriting your micro services for 5 minutes and listen to me. Your shit WILL fucking break on a patch level change. Other dependencies will not play nice.

Enter the front end (not like that)

I didn’t really realize how the Node community affected the front end community until developers started writing their tools in Node. Then started publishing front end libraries on NPM. Now we’re really fucked. These people have taken configuration to the extreme and I did Java Server Faces professionally for 4 years. 0_0


A great project called 6to5, which did what the name implied. By installing a simple Browserify transformer you could write ES6 code(well ES7 too, hence the name change) and “compile” it to ES5.

Now it’s some convoluted mess of plugins that tries to do everything everyone ever wanted, while actually doing nothing out of the box.

I removed the section where I called out the creator of Babel by name. Honestly I overlooked the statement as a personal attack. I apologized to him publicly and hope to talk to him more in the future. — Drew


People actually use this thing. Can a library actually do shit out of the box anymore? I just want to install something and use it, not decide all the little plugins I want to use. New developer comes onto your team:

Oh hey, we use PostCSS. Look at the gulp/grunt/broccoli/brunch file and see what plugins I’ve used. When you do that, then look up what each plugin does. After you have wasted the entire day on that, then start writing some css, or PostCSS, whatever the fuck it actually is. I really just wanted SASS but decided to use these 185 plugins instead and you know, because it’s written in Javascript


I don’t even know where to start with this project. From what I can tell the background of React is: Facebook couldn’t create a notification indicator on, so they create this over engineered dump pile to solve that problem. Now they can tell you how many unread posts you have while downloading 15 terabytes of Javascript. Once they solved that issue they proceeded to write everything in React. They even built a comment system with it, because you know making an Ajax call and a DOM append is really hard.

That’s right. All you guys using React like it’s the only way to solve every problem ever are using it because Facebook couldn’t build a fucking notification icon.

I have the Chrome plugin that shows when a site uses React. I swear every other website I visit uses React, for the stupidest stuff. So many content sites use React. It’s pitiful. It’s like developers just forget that these frameworks come and go with the wind. Just take a step back and think about your front end choices in 2009. Now 2011. Now 2013. Now 2015. Just think about it. Do you really think putting all your eggs into a basket like React is a good idea?

Of course everyone in the tech community has to rewrite all their interfaces in React now. If you love to get off to to tech stacks then you’ll love hearing from Netflix, Yahoo, Airbnb, Vimeo and Imgur. You know who didn’t give a flying fuck about React? Their customers. Good job Yahoo, you rewrote your shitty mail client in React. Your customers didn’t give a shit. They just want it to work. My poor wife with her shitty Chromebook. She can play Crysis at 60fps, but fuck if she can read her email on Yahoo. Oh Vimeo, you couldn’t display the view count on the video without bringing in React? I really appreciate that. My cpu does too. Imgur, really appreciate you bringing in React on a page.. to display a fucking image. I mean you can’t even make this up.

Look at this video of Airbnb’s front end. I really think it is a satire piece on web development. Now look at this The whole page is static content, yet they literally hit the Rails stack, then hit the Node stack to render the React to a string and then send it back through the Rails stack. They even toyed with the idea of rewriting Airbnb in Node. 0_0. Front end developers come in to a company like Airbnb, like a parasitic infection of over engineered sloth turd. For what? Masterbating about their line code count for displaying fucking text on a page?

Please guys/girls, just take a step back every now and then. How does rewriting your interface in the latest framework get you to the next customer? Or the next 50 customers. Does it actually make your customers happier?

Don’t fucking build a SPA

Really all I’m saying is don’t build a SPA. A SPA will lock you into a framework that has the shelf life of a hamster dump. When you think you need a SPA, just stop thinking. Just don’t. Your users just don’t fucking care.

If I see a section on my app that is really hard to with Pjax/Turbolinks and jQuery, I’ll bring in a library/framework like Vue.js, *cough* React, Angular. All good choices for doing really complex forms(although I find Angular to be the best at this), with a ton of conditional validation. You know what though, these are the outliers in my experience, not the norm.

Maybe 1 or 2 pages on your app will have really complex UI, but the other 95% of the app does not. So you pay a huge penalty doing a SPA. You’re typically writing all the basic CRUD stuff in a SPA from scratch. The backend framework you’re using can’t help you in any way. So my advice is to use Rails, Django, Play Framework, Laravel, or Phoenix to develop most of the app, because they help you with most of the boilerplate stuff, and bring in the flavor of the month on a page that needs it. So when the next flavor of the month comes out you’re entire app is not knee deep in the last flavor of the month. You can just re write that one page.

Hello my name is Drew and I’m a recovering magpie front end developer.

I originally wrote this anonymously. Yea I was pretty frustrated. It’s all good. Let’s ship some awesome stuff for people!

I apologize to anyone I offended. Thank you to the open source community for all you do!


Being A Developer After 40

Being A Developer After 40

(This is the talk I have given at App Builders Switzerland on April 25th, 2016. The slides are available on SpeakerDeck and at the bottom of this article.)
Hi everyone, I am a forty-two years old self-taught developer, and this is my story.
A couple of weeks ago I came by the tweet below, and it made me think about my career, and those thoughts brought me back to where it all began for me:

I started my career as a software developer at precisely 10am, on Monday October 6th, 1997, somewhere in the city of Olivos, just north of Buenos Aires, Argentina. The moment was Unix Epoch 876142800. I had recently celebrated my 24th birthday.

The World In 1997

The world was a slightly different place back then.
Websites did not have cookie warnings. The future of the web were portals like AltaVista was my preferred search engine. My e-mail was, which meant that my first personal website was located in We were still mourning Princess Lady Diana. Steve Jobs had taken the role of CEO and convinced Microsoft to inject 150 million dollars into Apple Computer. Digital Equipment Corporation was suing Dell. The remains of Che Guevara had just been brought back to Cuba. The fourth season of “Friends” had just started. Gianni Versace had just been murdered in front of his house. Mother Teresa, Roy Lichtenstein and Jeanne Calment (the world’s oldest person ever) had just passed away. People were playing Final Fantasy 7 on their PlayStation like crazy. BBC 2 started broadcasting the Teletubbies. James Cameron was about to release Titanic. The Verve had just released their hit “Bitter Sweet Symphony” and then had to pay most royalties to the Rolling Stones.

Smartphones looked like the Nokia 9000 Communicator; they had 8 MB of memory, a 24 MHz i386 CPU and run the GEOS operating system.
Smartwatches looked like the CASIO G-SHOCK DW-9100BJ. Not as many apps but the battery life was much longer.
IBM Deep Blue had defeated for the first time Garry Kasparov in a game of chess.
A hacker known as “_eci” published the C code for a Windows 3.1, 95 and NT exploit called “WinNuke,” a denial-of-service attack that on TCP port 139 (NetBIOS) causing a Blue Screen of Death.
Incidentally, 1997 is also the year Malala Yousafzai, Chloë Grace Moretz and Kylie Jenner were born.
Many film storylines take place in 1997, to name a few: Escape from New York, Predator 2, The Curious Case of Benjamin Button, Harry Potter and the Half-Blood Prince, The Godfather III and according to Terminator 2: Judgement Day, Skynet became self-aware at 2:14 am on August 29, 1997. That did not happen; however, in an interesting turn of events, the domain had been registered on September 15th that year.
We were two years away from Y2K and the media were starting to get people nervous about it.

My First Developer Job

My first job consisted of writing ASP pages in various editors, ranging from Microsoft FrontPage, to HotMeTaL Pro to EditPlus, managing cross-browser compatibility between Netscape Navigator and Internet Explorer 4, and writing stored procedures in SQL Server 6.5 powering a commercial website published in Japanese, Russian, English and Spanish” without any consistent UTF-8 support across the software stack.
The product of these efforts ran in a Pentium II server hosted somewhere in the USA, with a stunning 2 GB hard disk drive and a whooping 256 MB of RAM. It was a single server running Windows NT 4, SQL Server 6.5 and IIS 2.0, serving around ten thousand visitors per day.
My first professional programming language was this mutant called VBScript, and of course a little bit of JavaScript on the client side, sprinkled with lots of “if this is Netscape do this, else do that” because back then I had no idea how to use JavaScript properly.
Interestingly, it’s 2016 and we are barely starting to understand how to do anything in JavaScript.
Unit tests were unheard of. The Agile Manifesto had not been written yet. Continuous integration was a dream. XML was not even a buzzword. Our QA strategy consisted of restarting the server once a week, because otherwise it would crash randomly. We developed our own COM+ component in Visual J++ to parse JPEG files uploaded to the server. As soon as JPEG 2000-encoded files started popping up, our component broke miserably.
We did not use source control, not even CVS, RCS or, God forbid, SourceSafe. Subversion did not exist yet. Our Joel Test score was minus 25.

6776 Days

For the past 6776 days I have had a cup of coffee in the morning and wrote code with things named VBScript, JavaScript, Linux, SQL, HTML, Makefiles, Node.js, CSS, XML, .NET, YAML, Podfiles, JSON, Markdown, PHP, Windows, Doxygen, C#, Visual Basic, Visual Basic.NET, Java,, Ruby, unit tests, Python, shell scripts, C++, Objective-C, batch files, and lately Swift.
In those 6776 days lots of things happened; most importantly, my wife and I got married. I quit 6 jobs and I was fired twice. I started and closed my own business. I finished my Master Degree. I published a few open source projects, and one of them landed me an article on Ars Technica by Erica Sadun herself. I was featured in Swiss and Bolivian TV shows. I watched live keynotes by Bill Gates and by Steve Jobs in Seattle and San Francisco. I spoke at and co-organised conferences in four continents. I wrote and published two books. I burned out twice (not the books, myself,) and lots of other things happened, both wonderful and horrible.
I have often pondered about leaving the profession altogether. But somehow, code always calls me back after a while. I like to write apps, systems, software. To avoid burning out, I have had to develop strategies.
In this talk I will give you my secrets, so that you too can reach the glorious age of 40 as an experienced developer, willing to continue in this profession.

Advice For The Young At Heart

Some simple tips to reach the glorious age of 40 as a happy software developer.

1. Forget The Hype

The first advice I can give you all is, do not pay attention to hype. Every year there is a new programming language, framework, library, pattern, component architecture or paradigm that takes the blogosphere by storm. People get crazy about it. Conferences are given. Books are written. Gartner hype cycles rise and fall. Consultants charge insane amounts of money to teach, deploy or otherwise fuckup the lives of people in this industry. The press will support these horrors and will make you feel guilty if you do not pay attention to them.
In 1997 it was CORBA & RUP.
In 2000 it was SOAP & XML.
In 2003 it was Model Driven Architecture and Software Factories.
In 2006 it was Semantic Web and OLPC.
In 2009 it was Augmented Reality.
In 2012 it was Big Data.
In 2015… Virtual Reality? Bots?
Do not worry about hype. Keep doing your thing, keep learning what you were learning, and move on. Pay attention to it only if you have a genuine interest, or if you feel that it could bring you some benefit in the medium or long run.
The reason for this lies in the fact that, as the Romans said in the past, Nil nove sul sole. Most of what you see and learn in computer science has been around for decades, and this fact is purposedly hidden beneath piles of marketing, books, blog posts and questions on Stack Overflow. Every new architecture is just a reimagination and a readaptation of an idea that was floating around for decades.

2. Choose Your Galaxy Wisely

In our industry, every technology generates what I call a “galaxy.” These galaxies feature stars but also black holes; meteoric changes that fade in the night, many planets, only a tiny fraction of which harbour some kind of life, and lots of cosmic dust and dark matter.
Examples of galaxies are, for example, .NET, Cocoa, Node.js, PHP, Emacs, SAP, etc. Each of these features evangelists, developers, bloggers, podcasts, conferences, books, training courses, consulting services, and inclusion problems. Galaxies are built on the assumption that their underlying technology is the answer to all problems. Each galaxy, thus, is based in a wrong assumption.
The developers from those different galaxies embody the prototypical attitudes that have brought that technology to life. They adhere to the ideas, and will enthusiatically wear the t-shirts and evangelize others about the merits of their choice.
Actually, I use the term “galaxy” to avoid the slightly more appropriate if not less controversial term “religion,” which might describe this phenomenon better.
In my personal case, I spent the first ten years of my career in the Microsoft galaxy, and the following nine in the Apple galaxy.
I dare say, one of the biggest reasons why I changed galaxies was Steve Ballmer. I got tired of the general attitude of the Microsoft galaxy people against open source software.
On the other hand, I also have to say that the Apple galaxy is a delightful place, full of artists and musicians and writers who, by chance or ill luck, happen to write software as well.
I attended conferences in the Microsoft galaxy, like the Barcelona TechEd 2003, or various Tech Talks in Buenos Aires, Geneva or London. I even spoke at the Microsoft DevDays 2006 in Geneva. The general attitude of developers in the Microsoft galaxy is unfriendly, “corporate” and bound in secrecy, NDAs and cumbersome IT processes.
The Apple galaxy was to me, back in 2006, exactly the opposite; it was full of people who were musicians, artists, painters; they would write software to support their passion, and they would write software with passion. It made all the difference, and to this day, I still enjoy tremendously this galaxy, the one we are in, right now, and that has brought us all together.
And then the iPhone came out, and the rest is history.
So my recommendation to you is: choose your galaxy wisely, enjoy it as much or as little as you want, but keep your telescope pointed towards the other galaxies, and prepare to make a hyperjump to other places if needed.

3. Learn About Software History

This takes me to the next point: learn how your favorite technology came to be. Do you like C#? Do you know who created it? How did the .NET project came to be? Who was the lead architect? Which were the constraints of the project and why did the language turned out to be what it is now?
Apply the same recipe to any language or CPU architecture that you enjoy or love: Python, Ruby, Java, whatever the programming language; learn their origins, how they came up to be. The same for operating systems, networking technologies, hardware, anything. Go and learn how people came up with those ideas, and how long they took to grow and mature. Because good software takes ten years, you know.

The stories surrounding the genesis of our industry are fascinating, and will show you two things: first, that everything is a remix. Second, that you could be the one remixing the next big thing. No, scratch that: you are going to be the creators of the next big thing.
And to help you get there, here is my (highly biased) selection of history books that I like and recommend:

You will also learn to value those things that stood the test of time: Lisp, TeX, Unix, bash, C, Cocoa, Emacs, Vim, Python, ARM, GNU make, man pages. These are some examples of long-lasting useful things that are something to celebrate, cherish and learn from.

4. Keep on Learning

Learn. Anything will do. Wanna learn Fortran? Go for it. Find Erlang interesting? Excellent. Think COBOL might be the next big thing in your career? Fantastic. Need to know more about Functional Reactive Programming? Be my guest. Design? Of course. UX? You must. Poetry? You should.
Many common concepts in Computer Science have been around for decades, which makes it worthwhile to learn old programming languages and frameworks; even “arcane” ones. First, it will make you appreciate the current state of the industry (or hate it, it depends,) and second, you will learn how to use the current tools more effectively” if anything, because you will understand its legacy and origins.
Tip 1: learn at least one new programming language every year. I did not come up with this idea; The Pragmatic Programmer book did. And it works.
One new programming language every year. Simple, huh? Go beyond the typical “Hello, World” stage, and build something useful with it. I usually build a simple calculator with whatever new technology I learn. It helps me figure out the syntax, it makes me familiar with the APIs or the IDE, etc.
Tip 2: read at least 6 books per year. I have shown above a list of six must-read books; that should keep you busy for a year. Here goes the list for the second year:

(OK, those are seven books.)
Six books per year looks like a lot, but it only means one every 2 months. And most of the books I have mentioned in this presentation are not that long, and even better, they are outstandingly well written, they are fun and are full of insight.
Look at it this way: if you are now 20 years old, by the age of 30 you will have read over 60 books, and over 120 when you reach my age. And you will have played with at least 20 different programming languages. Think about it for a second.
Some of the twelve books I’ve selected for you have been written in the seventies, others in the eighties, some in the nineties and finally most of them are from the past decade. They represent the best writing I have come across in our industry.
But do not just read them; take notes. Bookmark. Write on the pages of the books. Then re-read them every so often. Borges used to say that a bigger pleasure than reading a book is re-reading it. And also, please, buy those books you really like in paper format. Believe me. eBooks are overrated. Nothing beats the real thing.
Of course, please know that as you will grow old, the number of things that qualify as new and/or important will drop dramatically. Prepare for this. It is OK to weep silently when you realise this.

If I could go back in time and tell the younger me exactly one and only one thing, it would be “learn UNIX” – Jeff Atwood

5. Teach

Once you have learnt, teach. This is very important.
This does not mean that you should setup a classroom and invite people to hear your ramblings (although it would be awesome if you did!) It might mean that you give meaningful answers to questions in Stack Overflow; that you write a book; that you publish a podcast about your favorite technology; that you keep a blog; that you write on Medium; that you go to another continent and set up programming schools using Raspberry Pis; or that you help a younger developer by becoming their mentor (do not do this before the age of 30, though.)
Teaching will make you more humble, because it will painfully show you how limited your knowledge is. Teaching is the best way to learn. Only by testing your knowledge against others are you going to learn properly. This will also make you more respectful regarding other developers and other technologies; every language, no matter how humble or arcane, has its place within the Tao of Programming, and only through teaching will you be able to feel it.
And through teaching you can really, really make a difference in this world. Back in 2012 I received a mail from a person who had attended one of my trainings. She used to work as an Adobe Flash developer. Remember ActionScript and all that? Well, unsurprisingly after 12 years of working as a freelance Flash developer she suddenly found herself unemployed. Alone. With a baby to feed. She told me in her message that she had attended my training, that she had enjoyed it and also learnt something useful, and that after that she had found a job as a mobile web developer. She wrote to me to say thank you.
I cannot claim that I changed the world, but I might have nudged it a little bit, into something (hopefully) better. This thought has made every lesson I gave since then much more worthwhile and meaningful.

6. Workplaces Suck

Every day, with every action and choice, you’re either a teacher and an inspiration, or a lesson and a reminder. – Cat Swart

Do not expect software corporations to offer any kind of career path. They might do this in the US, but I have never seen any of that in Europe. This means that you are solely responsible for the success of your career. Nobody will tell you “oh, well, next year you can grow to be team leader, then manager, then CTO…”
Not. At. All. Quite the opposite, actually: you were, are and will be a software developer, that is, a relatively expensive factory worker, whose tasks your managers would be happy to offshore no matter what they tell you.
Do not take a job just for the money. Software companies have become sweatshops where you are supposed to justify your absurdly high salary with insane hours and unreasonable expectations. And, at least in the case of Switzerland, there is no worker union to help you if things go bad. Actually there are worker unions in Switzerland, but they do not really care about situations that will not land them some kind of media exposure.
Even worse; in most workplaces you will be harassed, particularly if you are a woman, a member of the LGBT community or from a non-caucasian ethnic group. I have seen developers threatened to have their work visas not renewed if they did not work faster. I have witnessed harassment of women and gay colleagues.
Some parts of our industry are downright disgusting, and you do not need to be in Silicon Valley to live it. You do not need Medium to read it. You could experience that right here in Switzerland. Many banks have atrocious workplaces. Financial institutions want you to vomit code 15 hours a day, even if the Swiss working laws explicitly forbid such treatments. Pharmaceutical companies want you to write code to cheat test results and to help them bypass regulations. Startups want your skin, working for 18 hours for no compensation, telling you bullshit like “because we give you stock options” or “because we are all team players.”
It does not matter that you are Zach Holman and that you can claim in your CV that you literally wrote Github from scratch: you will be fired for the pettiest of reasons.
It does not matter that the app brings more than half of your employer traffic and revenues; the API team will treat you and your ideas with contempt and sloppiness.
I have been asked to work for free by very well known people in the industry, some of them even featured in Wikipedia, and it is simply appalling. I will not give out their names, but I will prevent any junior from getting close to them, because people working without ethics do not deserve anyone’s brain.
Whenever an HR manager tells you “you must do this (whatever wrong thing in your frame of reference) because we pay you a salary,” remember to answer the following: “you pay me a salary, but I give you my brain in exchange, and I refuse to comply with this order.”
And to top it all, they will put you in an open space, and for some reason they will be proud about it. Open spaces are a cancer. They are without a doubt the worst possible office layout ever invented, and the least appropriate for software development” or any type of brain work for that matter.
Remember this: the fact that you understand something does not imply that you have to agree to it.
Disobey authority. Say “fuck you, I won’t do what you tell me” and change jobs. There are fantastic workplaces out there; not a lot, but they exist. I have been lucky enough to work in some of them. Do not let a bad job kill your enthusiasm. It is not worth it. Disobey and move on.
Or, better yet, become independent.

Myth: Open offices result in massive collaboration.
Reality: 2 people loudly collaborate; 30 must wear headphones to get any work done. – Jochen Wolters

7. Know Your Worth

You have probably heard about the “10x Software Engineer” myth, right? Well here is the thing: it is not a myth, but it does not work they way you think it works.
It works, however, from the point of view of the employer: a “10x Software Engineer” generates worth 10 times whatever the employer pays. That means that you she or he gets 100 KCHF per year, but she or he are actually creating a value worth over a million francs. And of course, they get the bonuses at the end of the fiscal year, because, you know, capitalism. Know your worth. Read Karl Marx and Thomas Piketty. Enough said.
Keep moving; be like the shark that keeps on swimming, because your skills are extremely valuable. Speak out your salary, say it loud, blog about it, so that your peers know how much their work is worth. Companies want you to shut up about that, so that women are paid 70% of what men are paid. So speak up! Blog about it! Tweet it! I am making 135 KCHF per year. That was my current salary. How about you? And you? The more we speak out, the less inequality there will be. Any person doing my job with my experience should get the same money, regardless of race, sex, age or preferred football team. End of the story. But it is not like that. It is not.

A customer walks into a bar. He asks for a beer made out of wine. The project manager agrees. Both question the bartender’s competence. – Daniel Méndez

8. Send The Elevator Down

If you are a white male remember all the privilege you have enjoyed since birth just because you were born that way. It is your responsibility to change the industry and its bias towards more inclusion.
It is your duty to send the elevator down.
Take conscious decisions in your life. Be aware of your actions and their effect. Do not blush or be embarrased for changing your opinions. Say “I’m sorry” when required. Listen. Do not be a hotshot. Have integrity and self-respect.
Do not critisize or make fun of the technology choices of your peers; for other people will have their own reasons to choose them, and they must be respected. Be prepared to change your mind at any time through learning. One day you might like Windows. One day you might like Android. I am actually liking some parts of Android lately. And that is OK.

Desirable developer skills:
1 Ability to ignore new tools and technologies
2 Taste for simplicity
3 Good code deletion skills
4 Humility
– David Winterbottom


Everybody is raving about Swift, but in reality what I pay more attention to these days is LLVM itself.
I think LLVM is the most important software project today, as measured in its long-term impact. Objective-C blocks, Rust & Swift (the two most loved strongly typed and compiled programming languages in the 2016 StackOverflow developer survey,) Dropbox Pyston, the Clang Static Analyser, ARC, Google Souper, Emscripten, LLVMSharp, Microsoft LLILC, Rubymotion, cheerp, watchOS apps, the Android NDK, Metal, all of these things were born out or powered by LLVM. There are compilers using LLVM as a backend for pretty much all the most important languages of today. The .NET CLR will eventually interoperate with it, and Mono already uses it. Facebook has tried to integrate LLVM with HHVM, and WebKit recently switched from LLVM to the new B3 JIT JavaScript compiler.
LLVM is cross-platform, cross-CPU-architecture, cross-language, cross-compiler, cross-eyed-tested, free as in gratis and free as a bird.
Learn all you can about LLVM. This is the galaxy where true innovation is happening now. This is the foundation for the next 20 years.

Java is 20 years old, C# is 15 – I think it is better to see Swift as a response to that sort of managed language (the next step?) – Chris Lattner

10. Follow Your Gut

I had the gut feeling .NET was going to be big when I watched its introduction in June 2000. I had the gut feeling the iPhone was going to be big when I watched its introduction in 2007.
In both cases people laughed at my face, literally. In both cases I followed my gut feeling and I guess things worked out well.
Follow your gut. You might be lucky, too.

11. APIs Are King

Great APIs enable great apps. If the API sucks, the app will suck, too, no matter how beautiful the design.
Remember that chunky is better than chatty, and that clients should be dumb; push as much logic as you can down to the API.
Do not invent your own security protocols.
Learn a couple of server-side technologies, and make sure Node is one of those.
Leave REST aside and embrace, ZeroMQ, RabbitMQ, Erlang, XMPP; explore realtime as the next step in app development. Realtime is not only for chat apps. Remove polling from the equation forever.
Oh, and start building bots around those APIs. Just saying.

12. Fight Complexity

Simpler is better. Always. Remember the KISS principle. And I do not mean only at the UI level, but all the way until the deepest layers of your code.
Refactoring, unit tests, code reviews, pull requests, all of these tools are at your disposal to make sure that the code you ship is the simplest possible architecture that works. This is how you build resilient systems for the long term.

“Ok, let’s make a rails app”
“Oh, I need rails first”
“Oh, I need rbenv first”
“Oh I need brew”
“Oh I need xcode tools”
… rage. – Matthew Jewell


The most important thing to remember is that your age does not matter.

One of my sons said to me, “Impossible, Dad. Mathematicians do all their best work by the time they’re 40. And you’re over 80. It’s impossible for you to have a good idea now.”
If you’re still awake and alert mentally when you’re over 80, you’ve got the advantage that you’ve lived a long time and you’ve seen many things, and you get perspective. I’m 86 now, and it’s in the last few years that I’ve had these ideas. New ideas come along and you pick up bits here and there, and the time is ripe now, whereas it might not have been ripe five or 10 years ago.
Michael Atiyah, Fields Medal and Abel Prize winner Mathematician, quoted in a Wired article.

As long as your heart tells you to keep on coding and building new things, you will be young, forever.
In 2035, exactly 19 years from now, somebody will give a talk at a software conference similar to this one, starting like this:
“Hi, I am 42 years old, and this is my story.”
Hopefully one of you will be giving that presentation; otherwise, it will be an AI bot. You will provide some anecdotical facts about 2016, for example that it was the year when David Bowie, Umberto Eco, Gato Barbieri and Johan Cruyff passed away, or when SQL Server was made available in Linux, or when Google AlphaGo beat a Go champion, or when the Panama Papers and the Turkish Citizenship Database were leaked the same day, or when Google considered using Swift for Android for the first time, or as the last year in which people enjoyed this useless thing called privacy.
We will be three years away from the Year 2038 Problem and people will be really nervous about it.
Of course I do not know what will happen 19 years from now, but I can tell you three things that will happen for sure:

  1. Somebody will ask a question in Stack Overflow about how to filter email addresses using regular expressions.
  2. Somebody will release a new JavaScript framework.
  3. Somebody will build something cool on top of LLVM.

And maybe you will remember this talk with a smile.
Thank you so much for your attention.