My thoughts on startups
Just some of my random thoughts on startups.
If you find yourself in a startups were your sole and/or primary metric of success is "market share" and you see your market share increasing, don't fall under the assumption that you are succeeding as a startup. Remember, you started at 0%, so an increase is not too difficult to pull off.
The bigger issue of focusing on market share is that you are tricking yourself into believing that startups are not as risky as they actually are. You must take risks and truly innovate for them to succeed.
Your best case with this market share focus is an eventual plateau of success (curve B) far below what you could achieve with the alternative tactic.
That alternative tactic being: focus primarily on true innovation. Do something that is not being currently done or do something in a completely different way. Don't aim for what can be done in the current reality, but instead what can be done in the soon to be reality. Also start out (and remain) passionate and completely focused your product.
In this case you have a chance of hitting curve D. (that market share amassed naturally). Yes, the odds are, you will hit curve C but in that case you will hit it quickly and can course correct with a substantial pivot of the project or abandon and move onto the next, entirely different project. In contrast, with the probable outcome of the market share driven startup, it takes much longer for curve A to drop, meaning, your business will be on the failing track for longer before you detect that a course correction is needed. At that point, it is probably too late.
Of course "Success" in the graphs below is abstract and entirely open to interpretation, but discussing that would be a whole new post.
PHP's World Of Arrays
Arrays in PHP are quite powerful, partly because they are not actually arrays (read on for an explanation), but can be treated as such when needed. They gain most of the utility from a vast library of built in helper functions associated with them.
Much of my day is spent looking at others code, (were ‘others’ does include ‘me in the past’), and I often see arrays under utilized or code that fights arrays by implementing foreach loops where a single function call would suffice. With some review of the functionality afforded arrays in PHP you can learn to use them more effectively and realize that they may very well be the best solution in circumstances you had not thought of before. This is nothing against Object Oriented Programming, as I consider myself a OO programmer. There is just quite a bit that can be done efficiently and elegantly with plain old arrays in PHP.
So as a refresher course for myself and hopefully to show others some array functionality they were not aware existed, I’ve decided to write a few blog posts on some things I find useful (and have newly discovered after re-reading the array docs).
This being the first of those posts, I’ll start with the basics, a very quick intro to just what an array is and then cover examples of using arrays as some of the more simple data structures in computer science: Stacks and Queues.
What Is An Array In PHP?
What is referred to as an ‘array’ in PHP is actually an ordered map. The keys of an array can be either an integer or a string. The value for an array element can be anything.
Arrays can be created using the array() construct or in a more literal fashion of using brackets ([ ])
$x = array('bob'); $x = array(0 => 'bob'); $x[] = 'bob'; $x[0] = 'bob';
All the examples above will result in this array:
array(0 => 'bob')
If a key is not specified for a value, a new key is created with the value of 1 + the current max of the integer keys in the array.
$y = array(0 => 'red', 1 => 'blue', 7 => 'green'); $y[] = 'brown';
The $y array would now be:
$y = array(0 => 'red', 1 => 'blue', 7 => 'green', 8 => 'brown');
For more of the basics of PHP arrays, there is an excellent php.net page devoted to that subject.
Using Arrays For Basic Data Structures
Stacks
In computer science, a Stack is a last in, first out (LIFO) structure.
>push pop>
\ /
X
X
X
X
XAn example of a Stack is your browser history. You click a link and it is pushed onto the top of your browser history. You continue to click links and they are continually pushed onto the top of that Stack. Then when you click on the ‘back’ button, the very top link is popped of your history Stack.
In PHP the functions array_push and array_pop are used for manipulating an array as a Stack.
$browser_history = array('https://mail.google.com', 'http://www.php.net' ); array_push($browser_history, 'http://www.topgear.com/uk/'); print_r($browser_history); // Array // ( // [0] => https://mail.google.com // [1] => http://www.php.net // [2] => http://www.topgear.com/uk/ // ) $site = array_pop($browser_history); echo "site: {$site}"; // site: http://www.topgear.com/uk/ print_r($browser_history); // Array // ( // [0] => https://mail.google.com // [1] => http://www.php.net // )
Note that in PHP, rather than using array_push, you can just use bracketed syntax which has the same effect.
array_push($array, 'value') // has the same effect as $array[] = 'value';
Queues
A Queue is a First-In-First-Out (FIFO) data structure. (think conveyor belt)
enqueue dequeue
(unshift) queue (shift)
X --> XXXXXXX --> XIn PHP, you can use an array as a Queue by utilizing array_unshift to prepend and element to the beginning of an array and then array_pop to take an element off the end of the same array.
An example would be any perishable items in your grocery store’s dairy case. As items come into the store they are loaded in the back of the case and customers select items for purchase from the front of the case.
$yogurts = array('exp:05/10/2011', 'exp:05/08/2011' ); print_r($yogurts); //Array //( // [0] => exp:05/10/2011 // [1] => exp:05/08/2011 //) array_unshift($yogurts, 'exp:05/13/2011', 'exp:05/12/2011'); print_r($yogurts); //Array //( // [0] => exp:05/13/2011 // [1] => exp:05/12/2011 // [2] => exp:05/10/2011 // [3] => exp:05/08/2011 //)
Note, these methods do not return the affected array so you wouldn’t normally do:
$yogurts = array_unshift($yogurts, 'exp:05/13/2011', 'exp:05/12/2011');
as array_pop simply returns the last value of the array and array_unshift returns the new number of elements in the array.
So that is it for now, next up I’ll discuss using the various function to calculate the differences and intersections between array.
Install of Python dev environment on OSX
After much trial and error, this is what worked for me on a macbook pro, running snow leopard 10.6.6.
$ brew install python $ sudo easy_install pip $ pip install virtualenv $ pip install virtualenvwrapper $ vi ~/.profile # add this line to .profile source /usr/local/Cellar/python/2.7.1/bin/virtualenvwrapper.sh $ source ~/.profile
First install a current Python (OSX python is outdated).
Then use easy_install to install its replacement: pip. (use pip after this)
Then use pip to install virtualenv and virtualenvwrapper (python's env manager. Think Ruby rvm)
The docs for virtualenvwrapper are at http://www.doughellmann.com/docs/virtualenvwrapper/
Example of creating python env
$ mkvirtualenv env-0 New python executable in env-0/bin/python Installing setuptools............................done. virtualenvwrapper.user_scripts creating /Users/sam/.virtualenvs/env-0/bin/predeactivate virtualenvwrapper.user_scripts creating /Users/sam/.virtualenvs/env-0/bin/postdeactivate virtualenvwrapper.user_scripts creating /Users/sam/.virtualenvs/env-0/bin/preactivate virtualenvwrapper.user_scripts creating /Users/sam/.virtualenvs/env-0/bin/postactivate virtualenvwrapper.user_scripts creating /Users/sam/.virtualenvs/env-0/bin/get_env_details $ ll $WORKON_HOME total 88 drwxr-xr-x 5 sam staff 170 Mar 25 08:22 env-0 -rwxrwxr-x 1 sam staff 106 Mar 25 08:18 get_env_details -rw-r--r-- 1 sam staff 4082 Mar 25 08:33 hook.log -rwxrwxr-x 1 sam staff 92 Mar 25 08:18 initialize -rwxrwxr-x 1 sam staff 69 Mar 25 08:18 postactivate -rwxrwxr-x 1 sam staff 71 Mar 25 08:18 postdeactivate -rwxrwxr-x 1 sam staff 69 Mar 25 08:18 postmkvirtualenv -rwxrwxr-x 1 sam staff 63 Mar 25 08:18 postrmvirtualenv -rwxrwxr-x 1 sam staff 70 Mar 25 08:18 preactivate -rwxrwxr-x 1 sam staff 72 Mar 25 08:18 predeactivate -rwxrwxr-x 1 sam staff 94 Mar 25 08:18 premkvirtualenv -rwxrwxr-x 1 sam staff 64 Mar 25 08:18 prermvirtualenv
OSX Leopard Mysql Log Rotation
For a development machine, it is sometimes nice to log all mysql queries.
with Mysql, you turn on logging by placing this entry in your my.cnf
[mysqld] log = /var/log/mysql/mysql.log
In doing that though, the log file can get quite large pretty quickly. I started googleing around for a solution, and found this link to be quite helpful though it didn’t mention mysql logs specifically.
On Leopard, the file that controls log rotation is /etc/newsyslog.conf
The entry I use looks like this.
# logfilename [owner:group] mode count size when flags [/pid_file] [sig_num] /var/log/mysql/mysql.log mysql:wheel 644 10 1000 * JS /usr/local/mysql/data/si-sam.local.pid 30
This rotates mysql.log anytime it grows beyond 1000k and keeps 10 compressed archives on hand
For your machine the actual logfile location can differ and the location and name of the pid file will most certainly be different.
To track down the name and location of your mysql pid file, execute
$ps aux | grep mysqld
and look for the —pid-file=
--pid-file=/usr/local/mysql/data/si-sam.local.pid
Using Presta for testing RESTful APIs
I wrote a small library to wrap the PHP Curl extension in a way that makes the code using it more read-able and keeps you from having to remember all those curl_setopt(…. constants.
Presta on github
Example Use in PHPUnit
With methods in your base test class (what you specific test classes are extending) such as these
/** * * @param string $uri_path * @return Response */ protected function api_get($uri_path) { return $this->presta ->uri($this->build_uri($uri_path)) ->auth($this->username, $this->password) ->get(); } ... /** * * @param string $uri_path * @return Response */ protected function api_delete($uri_path) { return $this->presta ->uri($this->build_uri($uri_path)) ->auth($this->username, $this->password) ->delete(); }
Then in a test for deleting through the API, you can have something like this
$response = $this->api_delete("/users/1"); $this->assertTrue($response->status_code==204); $this->assertEmpty($response->entity_body); $response = $this->api_get("/users/1"); $this->assertTrue($response->status_code==404);
Plan is to continue refining the code for presta, in addition to writing a 5.3+ version.
PHP print_r as valid PHP
If you ever have PHP print_r output that you just want to cut/paste as PHP code.
class Arr { /** * $array Can be either an Array or the string output of * print_r($array, true); */ public static function print_php($array) { $array = is_array($array)?print_r($array,true):$array; $array = preg_replace( array( '/Array\n/', '/\[(.*)\] =>/', '/\)\n/' ), array( "array\n", '"${1}" =>', "),\n" ), $array); // need regex skill++ , for now this will do $array = preg_replace_callback( '/=> (.*?)\n/', // only replace if it is not the word 'array' or just digits create_function( '$matches', '$match = isset($matches[1])?$matches[1]:null; $qt = ctype_digit($match)||$match=="array"?"":"\""; $c = $match=="array"?"":","; return "=> {$qt}{$match}{$qt}{$c}\n";' ), $array); return $array; } }
Rest Resource Granularity
ASCII Infographics
Client REST
Convenience - <---------- Resource ----------> + Cache-ability,
Granularity ChattinessGetting MySQLdb For Python Working on Snow Leopard
$ curl http://gist.github.com/raw/323731/HEAD/install_homebrew.rb -o /tmp/install_homebrew.rb
$ sudo chown -R $USER /usr/local
$ ruby /tmp/install_homebrew.rb
export PATH="/usr/local/bin:$PATH"
$ brew install python
$ brew install setuptools
$ tar xfz MySQL-python-1.2.1.tar.gz $ cd MySQL-python-1.2.1 $ # edit site.cfg if necessary $ python setup.py build $ sudo python setup.py install # or su first
$ cd
$ python Python 2.6.5 (r265:79063, Apr 27 2010, 12:36:14) [GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import MySQLdb >>>
Using Unicode To Increase Information Density in Tweets
Quite a while back I grabbed the twitter handle @pdxweather with plans to broadcast the local weather over it. I first thought I would send out a daily broadcast for today's weather and tomorrow. Being Portland, Oregon, I'm centering around the "Chance of Rain" for those days at least as a starting point. This has proven to be quite a challenge to accomplish with 140 characters. The technology needed to produce such tweets is not all that difficult. I built a little PHP script that would parse the forecasts from form the weather.gov API. I then have a PHP script that builds a short summary of that information and tweets it (once a day at this point). http://twitter.com/pdxweather
Attempt 1:
Sun_18th:light rain precip%day:13 precip%eve:29 Mon_19th:light rain precip%day:53 precip%eve:64 (NOAA splits the % chance of rain to day and eve. I like this feature so I want to have that in the tweets also even though it makes it that much more difficult to stay under 140.) Lots of room for improvement here.
- Hard to see the dividing line between the days
- Not even showing hi/low temps yet and we are at ~95 char so longer weather descriptions (i.e. "Light rain and high wind warning"") along with temps could easily put us over 140
- Overall, it's just hard to parse out the individual bits of information
Attempt 2:
Goals:
- Reduce the overall character count of what we have so far so we can add more info.
- Make the tweet more 'human brain parse-able'
I first trimmed the day descriptions to gain some more characters.
Sun18:light rain precip%day:13 precip%eve:29 Mon19:light rain precip%day:53 precip%eve:64
I then determined correct spelling was optional and substituted lite for light (lite seemed a better solution than lght or lt)
Sun18:lite rain precip%day:13 precip%eve:29 Mon19:lite rain precip%day:53 precip%eve:64
These helped on the character count, but you could easily argue that these make the tweet slightly less readable. What we really need is something that shortens the character count and at the same time increases its readability. For this I turned to Unicode. If I could find a single character to replace a word like 'Sunny' or 'Rain', I could regain many characters to use elsewhere in the Tweet. I did find some 'weather' glyphs in a miscellaneous section of Unicode, unfortunately most seem to render into illegible blobs because of the typical small size you see them at. I did find
- sun:☼
- snow:✽
but nothing good for rain that was legible at small sizes (does this look like rain on an umbrella? ☔).
So I started scanning the Unicode field for something that 'looked' like rain and settled on ⑊. So using ⑊ for rain, we are at:
Sun18:lite ⑊ precip%day:13 precip%eve:29 Mon19:lite ⑊ precip%day:53 precip%eve:64
I then did a major refactor to the order of things and dropped some 'not completely necessary' terms:
Sun18:lite ⑊ 13%day 29%eve Mon19:lite ⑊ 53%day 64%eve
At this point, a great deal of ground has been made on character count, down to 53 characters, or about a 45% reduction. As a final step, I rely on alpha/digit/symbol boundaries and remove space between them. In an effort to emphasize boundaries, it is back to Unicode with → and ▮. So here it is at 49 chars:
Sun18 lite⑊13%day→29%eve▮Mon19 lite⑊53%day→64%eve
Original at 95
Sun_18th:light rain precip%day:13 precip%eve:29 Mon_19th:light rain precip%day:53 precip%eve:64
Now What
The goal now it to allow this logic to all weather tweets with will involve building a NOAA weather speak to Tweet Weather speak translator. So the overall architecture will be
- nightly, hit the NOAA API and and parse/cache the forecast on the local server
- once a day (or more), use that cached data to tweet the forcast
So I'm off to finish that, the starting point is here on github. I'll document and cleanup that code as I go along Also looking for feedback on the compaction techniques I'm using for the Tweets, so please comment if you have suggestions
Installing Git Manpages on Snow Leopard
$ git help pull No manual entry for git-pull
$ git --version git version 1.6.4.2
curl -O http://www.kernel.org/pub/software/scm/git/git-manpages-{YOUR VERSION}.tar.bz2$ cat /etc/manpaths /usr/share/man /usr/local/share/man
sudo tar xjv -C /usr/local/share/man -f git-manpages-1.6.4.2.tar.bz2
Now you should get manpages when you issue something like git help merge

