I just helped a co-worker with a problem in a sorting mechanism inside Javascript. Here’s the snippet that caught my eye:
var ret = (a.l > b.l) ? -1 : ((a.n.toLowerCase() < b.n.toLowerCase()) ? -1 : 1);
I looked at the code, and stated: I don’t like nested ternaries, it’s too easy to mess up or miss something. My co-worker explained that the alternative was too long and drawn out, this is how it’s always done. I pondered the code for a moment, and asked what happened when a.l < b.l, as the case seems to be missing. That was the bug.
The people I’m working with are all smart, great developers. We all miss things, tragically we’re not perfect. When you miss things, you need to be able to find them, writing overly complex code (I would consider nested ternaries an example of overly complex code) makes it really easy to find them.
I’m slowly working on improving our internal coding standards document with additional rules, at the time being I’m considering:

  1. Don’t use GOTO
  2. Don’t use nested ternaries
  3. Document the heck out of variable variables ($$variable), or variable function calls ($this->$method)
  4. Write commit messages


Any other rules you follow?



Note, while I am strongly discouraging the use of GOTO, I do not think adding it to PHP was a mistake. There are good use cases for the language construct, I just feel it’s an easy thing to fall back on when the real solution is to build your code in a more intelligent manner.

If you have a lot of content, you likely paginate, hopefully to increase usability and decrease bandwidth bills, as opposed to showing me more ads. If you do, please use a paginator that’s easy to use. Here’s an example of a paginator that I don’t like



Why don’t I like it?
Well, the two most common actions at this point are:"Go to the next page" and "Go to the page where content I’m looking for is likely to reside". Neither of those actions involves going to the last page (except by coincidence), and yet it’s the largest option by far. In fact the Last button section takes up 748 pixels (44 x 17), while the next button receives only 289 (17x17).

I’m currently looking at an alphabetically sorted list of options. If I know that the types of items I’m looking for happen to start with "S" how do I jump there? Do I start on page 5? 11? 51? 101? Likely none of the above.

Consider a pagination tool like the following.



It’s clear what you’re looking at, you can move on to the next page, as well as jump to any logical position within the pagination system with ease.
Now I know this is harder than traditional pagination systems. After all MySQL conveniently optimizes out calls to things like SELECT COUNT(*) FROM table;. Past that a quick bit of math and you know how many pages you need, and you can set offsets quite easily using a LIMIT clause or similar.

When it comes to web development, or anything else "Where there’s muck, there’s brass". Just because a problem is hard doesn’t mean you shouldn’t solve it. Users like sites they can navigate (remember many users exhibit either link dominance or mixed behavior when seeking content), they reward sites they like with sales, more visits, links, blog posts, etc.
Please find below an incredibly lame piece of code to print out the values of all the memcached constants defined on their doc page. I was running into a few errors, and getResultCode() was obligingly returning the value of the constant, rather than the constant itself. I had to look up what that value meant. For some reason I couldn't reflect the extension to get the constants and values thereof, so with some lame scraping you get the following. Code under the jump, answers (as of our version of various libraries) here:


Memcached::OPT_COMPRESSION - -1001
Memcached::OPT_SERIALIZER - -1003
Memcached::SERIALIZER_PHP - 1
Memcached::SERIALIZER_IGBINARY - 2
Memcached::SERIALIZER_JSON - 3
Memcached::OPT_PREFIX_KEY - -1002
Memcached::OPT_HASH - 2
Memcached::HASH_DEFAULT - 0
Memcached::HASH_MD5 - 1
Memcached::HASH_CRC - 2
Memcached::HASH_FNV1_64 - 3
Memcached::HASH_FNV1A_64 - 4
Memcached::HASH_FNV1_32 - 5
Memcached::HASH_FNV1A_32 - 6
Memcached::HASH_HSIEH - 7
Memcached::HASH_MURMUR - 8
Memcached::OPT_DISTRIBUTION - 9
Memcached::DISTRIBUTION_MODULA - 0
Memcached::DISTRIBUTION_CONSISTENT - 1
Memcached::OPT_LIBKETAMA_COMPATIBLE - 16
Memcached::OPT_BUFFER_WRITES - 10
Memcached::OPT_BINARY_PROTOCOL - 18
Memcached::OPT_NO_BLOCK - 0
Memcached::OPT_TCP_NODELAY - 1
Memcached::OPT_SOCKET_SEND_SIZE - 4
Memcached::OPT_SOCKET_RECV_SIZE - 5
Memcached::OPT_CONNECT_TIMEOUT - 14
Memcached::OPT_RETRY_TIMEOUT - 15
Memcached::OPT_SEND_TIMEOUT - 19
Memcached::OPT_RECV_TIMEOUT - 15
Memcached::OPT_POLL_TIMEOUT - 8
Memcached::OPT_CACHE_LOOKUPS - 6
Memcached::OPT_SERVER_FAILURE_LIMIT - 21
Memcached::HAVE_IGBINARY - #&UNDEFINED;#
Memcached::HAVE_JSON - #&UNDEFINED;#
Memcached::GET_PRESERVE_ORDER - 1
Memcached::RES_SUCCESS - 0
Memcached::RES_FAILURE - 1
Memcached::RES_HOST_LOOKUP_FAILURE - 2
Memcached::RES_UNKNOWN_READ_FAILURE - 7
Memcached::RES_PROTOCOL_ERROR - 8
Memcached::RES_CLIENT_ERROR - 9
Memcached::RES_SERVER_ERROR - 10
Memcached::RES_WRITE_FAILURE - 5
Memcached::RES_DATA_EXISTS - 12
Memcached::RES_NOTSTORED - 14
Memcached::RES_NOTFOUND - 16
Memcached::RES_PARTIAL_READ - 18
Memcached::RES_SOME_ERRORS - 19
Memcached::RES_NO_SERVERS - 20
Memcached::RES_END - 21
Memcached::RES_ERRNO - 26
Memcached::RES_BUFFERED - 32
Memcached::RES_TIMEOUT - 31
Memcached::RES_BAD_KEY_PROVIDED - 33
Memcached::RES_CONNECTION_SOCKET_CREATE_FAILURE - 11
Memcached::RES_PAYLOAD_FAILURE - -1001




$memcachedConstants = array(
0 => 'Memcached::OPT_COMPRESSION',
1 => 'Memcached::OPT_SERIALIZER',
2 => 'Memcached::SERIALIZER_PHP',
6 => 'Memcached::SERIALIZER_IGBINARY',
7 => 'Memcached::SERIALIZER_JSON',
8 => 'Memcached::OPT_PREFIX_KEY',
9 => 'Memcached::OPT_HASH',
11 => 'Memcached::HASH_DEFAULT',
12 => 'Memcached::HASH_DEFAULT',
13 => 'Memcached::HASH_MD5',
14 => 'Memcached::HASH_CRC',
15 => 'Memcached::HASH_FNV1_64',
16 => 'Memcached::HASH_FNV1A_64',
17 => 'Memcached::HASH_FNV1_32',
18 => 'Memcached::HASH_FNV1A_32',
19 => 'Memcached::HASH_HSIEH',
20 => 'Memcached::HASH_MURMUR',
21 => 'Memcached::OPT_DISTRIBUTION',
22 => 'Memcached::DISTRIBUTION_MODULA',
23 => 'Memcached::DISTRIBUTION_MODULA',
24 => 'Memcached::DISTRIBUTION_CONSISTENT',
25 => 'Memcached::OPT_LIBKETAMA_COMPATIBLE',
26 => 'Memcached::OPT_BUFFER_WRITES',
27 => 'Memcached::OPT_BINARY_PROTOCOL',
28 => 'Memcached::OPT_NO_BLOCK',
29 => 'Memcached::OPT_TCP_NODELAY',
30 => 'Memcached::OPT_SOCKET_SEND_SIZE',
31 => 'Memcached::OPT_SOCKET_RECV_SIZE',
32 => 'Memcached::OPT_CONNECT_TIMEOUT',
33 => 'Memcached::OPT_RETRY_TIMEOUT',
34 => 'Memcached::OPT_SEND_TIMEOUT',
35 => 'Memcached::OPT_RECV_TIMEOUT',
36 => 'Memcached::OPT_POLL_TIMEOUT',
37 => 'Memcached::OPT_CACHE_LOOKUPS',
38 => 'Memcached::OPT_SERVER_FAILURE_LIMIT',
39 => 'Memcached::HAVE_IGBINARY',
40 => 'Memcached::HAVE_JSON',
41 => 'Memcached::GET_PRESERVE_ORDER',
44 => 'Memcached::RES_SUCCESS',
45 => 'Memcached::RES_FAILURE',
46 => 'Memcached::RES_HOST_LOOKUP_FAILURE',
47 => 'Memcached::RES_UNKNOWN_READ_FAILURE',
48 => 'Memcached::RES_PROTOCOL_ERROR',
49 => 'Memcached::RES_CLIENT_ERROR',
50 => 'Memcached::RES_SERVER_ERROR',
51 => 'Memcached::RES_WRITE_FAILURE',
52 => 'Memcached::RES_DATA_EXISTS',
53 => 'Memcached::RES_NOTSTORED',
54 => 'Memcached::RES_NOTFOUND',
55 => 'Memcached::RES_PARTIAL_READ',
56 => 'Memcached::RES_SOME_ERRORS',
57 => 'Memcached::RES_NO_SERVERS',
58 => 'Memcached::RES_END',
59 => 'Memcached::RES_ERRNO',
60 => 'Memcached::RES_BUFFERED',
61 => 'Memcached::RES_TIMEOUT',
62 => 'Memcached::RES_BAD_KEY_PROVIDED',
63 => 'Memcached::RES_CONNECTION_SOCKET_CREATE_FAILURE',
64 => 'Memcached::RES_PAYLOAD_FAILURE'
);

foreach($memcachedConstants as $constant)
{
echo $constant . " - " . (defined($constant) ? constant($constant) : "#&UNDEFINED;#") . "
\n";
}

I think Nuclear weapons are bad. We can kill enough people with standard non-nuclear weapons thank-you-very-much, but, when you make a list of countries in the world that don’t like you, and most of those countries have them, it’s pretty easy to feel intimidated.

While the United Nations is writing strongly worded letters to Iran, it’s own security council has five permanent members: People’s Republic of China, France, Russian Federation, United Kingdom, United States. This list is practically a who’s who of nuclear weapon ownership. In fact, according to Wikipedia they have 8180 of the 8390 reported, active weapons world wide.

Political instability sucks, the prospect of rogue groups within a government taking control of weapons is terrifying. But when you’re standing surrounded by people who don’t like you, and all of them have better designed, tested, and bigger guns than you, I can’t blame you for wanting to even the score.
I'm currently looking at a project, and a few different optimizations for a project. The problem with most of them is that they will help out when the server is under light load, making it even lighter. Think something like adding etags to your server, when the file isn't changing often you save bandwidth. As the server gets busier, the file will be changing even more often, possibly approaching a situation where it's changing every time the file is requested.

My concern with a possible etag implementation is that it changes my load vs. users graph from being a simple line with a given slope, to an arc. Likely peaking slightly higher (doing that work isn't free), but with a much higher slope towards the right hand side. To be honest I'd rather have a flat graph myself, as it makes it easier to predict when things are going to explode.

What would you pick? Am I just being lazy?

I run into issues all the time where I’ve installed an application on one of my various linux boxes, but for some reason it can’t find a library it needs. I end up getting an error message along these lines:
memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

I then do a quick search on my box, and find that that library is indeed available (even in a seemingly useful location), the application just isn’t seeing it. How do I tell the application where to look, or help it find it?
Strace appears to be the answer. Simply run the command again, but through strace. You get output indicating all the different files it attempts to open. From the list you can determine where it’s looking for the library, and create a handy symbolic link there to the file in question.


paul@paul-desktop:/usr/local/src/memcached-1.2.8$ strace memcached
execve("/usr/local/bin/memcached", ["memcached"], [/ 37 vars /]) = 0
brk(0) = 0x9699000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f1a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=62870, ...}) = 0
mmap2(NULL, 62870, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f0a000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/sse2/cmov/libevent-1.4.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/sse2/cmov", 0xbfd39ba0) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/sse2/libevent-1.4.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/sse2", 0xbfd39ba0) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libevent-1.4.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/cmov", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/lib/tls/i686/libevent-1.4.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)


Generally the application will look in many different places for the file, just create the symlink in the location that fits best for your system layout.




Goodbye!

DPC Day 2 - The End from Paul Reinheimer on Vimeo.


Procuring interviews proved harder on the first real day of the conference. The strange illness I procured crossing the English channel had taken hold. Much time was spent shivering.
(content-free)

Untitled from Paul Reinheimer on Vimeo.


I'm currently working on a project that I feel will have me either forcing a square peg in a round hole, or re-inventing the wheel, both solutions seem… sub optimal.

I need to allow authenticated visitors to a website to chat to each other in a basic channel. They might need some light GUI stuff like making links clickable and that sort of thing. Moderators need the ability to revoke (delete) messages sent by users that they deem inappropriate, also send special notification messages to all users (likely they will simply be rendered in a larger font, possibly centered, but the fact that they’re "special" needs to be conveyed to the end client).

As soon as someone said the word "chat" to me, IRC and XMPP came to mind. They’re both robust and proven ways to handle the chat problem. Unfortunately they don't seem to support deleting a message that was sent previously (a concept that may be harder to accept when you’re allowing connection from an arbitrary client application). Other bits like special moderator messages and such could likely be handled by hacking into the server implementation a few extra bits and playing with an open source client and hacking there as well. The servers are likely to be written in a language like C++ or Java, so while I’m comfortable editing to hack in a few things, there's not a lot of in-house talent to work on these (and I’d have no one to go to if I ran into problems). This all feels a bit like pushing a rectangle peg into a rounded rectangle hole.

An alternative would be creating a simple PHP based server using either file, or memcached (, or something else) as a data storage system. Linking into our existing login infrastructure would be trivial: the code is already there. I have a few JavaScript chat clients kicking around, sprucing one up with the help of someone from our integration team shouldn’t be too hard at all. Our entire team would find the code rather accessible, as it's written in two languages we use frequently. This is all technology that we're already familiar with, and have demonstrated an ability to scale as our sites have grown. The problem is, I feel like something of an idiot writing the world's millionth chat application system.

Thoughts? Which would you choose?
A quick conversation with Christian Wenz. Also: Content!

DPC - 0 Interview with Christian Wenz from Paul Reinheimer on Vimeo.


A quick interview with Rob Allen

DPC Day 0 - Rob from Paul Reinheimer on Vimeo.


DPC -1 from Paul Reinheimer on Vimeo.



DPC -1 from Paul Reinheimer on Vimeo.



DPC -1 from Paul Reinheimer on Vimeo.


Uploading this video while at Sea! Uploading took nealry two hours. I'm hoping to get more videos, and videos with content up once I hit dry land and reliable interweb.

Vimeo is teh sux at the moment, it should be available here DPC Day -4 by the time you read this (and if vimeo isn't sucking)
internet is far too slow for the good videos, sorry. here's part two of last nights adventure

DPC Day -4.5 from Paul Reinheimer on Vimeo.


A conversation with Scott MacVicar about his upcoming talk and tutorial at the Dutch PHP Conference.

Dutch PHP Conference Day -5 from Paul Reinheimer on Vimeo.


Hi, I’m Paul Reinheimer, a developer working on the web.

I co-founded WonderProxy which provides access to over 200 proxies around the world to enable testing of geoip sensitive applications. We've since expanded to offer more granular tooling through Where's it Up

My hobbies are cycling, photography, travel, and engaging Allison Moore in intelligent discourse. I frequently write about PHP and other related technologies.

Search