<?php
try {
log('Connecting to the database ' . $dsn);
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
log('Connection failed to ' . $dsn . ': ' . $e->getMessage());
exit;
}
?>
Assuming the log function tracks some context for us.
This is pretty good
public function register($usernmae, $password) {
$this->log->trace('Entering ' . __CLASS__ . '::' . __FUNCTION__ ' with username = ' . $username . ' and password = ' . str_repeat('*', strlen($password)));
if (!$this->_validateUsername($username)) {
$this->log->warn('Invalid username when trying to register a new user: ' . $username);
$this->log->trace('Exiting ' . __CLASS__ . '::' . __FUNCTION__ . ' on error.');
return;
}
/* Validate the password and do the registration */
$this->log->info('New user registered with username ' . $username . ' and user ID ' . $this->_id);
$this->log->trace('Exiting ' . __CLASS__ . '::' . __FUNCTION__ . ' on success.');
return;
}
I am constrained to one slide. I might have added more logging. I certainly would have added some comments.
Sometimes you need a firehose
Trace - method by method, condition by condition.
Debug - If you put something in while writing the code, leave it there.
Info - Used to inform someone or something about a notable event.
Warn - Something unexpected happened, but we can recover.
Error - Something unexpected happened and we can't recover.
Good developers don't just tell you what they are doing now; they tell you what they are going to do.
Good code predicts the future using unit tests.
300 unit tests !== 1 application
Meh.
<?php
// Test set up stuff and mocking goes here.
$email = 'bob@example.com';
$this->assertTrue($validator->validateEmail($email));
?>
Less Meh.
<?php
// Test set up stuff and mocking goes here.
$email = 'scott.mattocks@gmail.com';
$this->assertTrue($validator->validateEmail($email));
?>
Good teams...
write things down (Logging)
know what to expect from each other (Unit Tests)
Good developers adapt quickly to changes.
Good code changes its behavior without changing the code.
Dev
⇒
QA
⇒
Staging
⇒
Produciton
$> svn ls $SVNROOT/awesomeproject/trunk
application/
bin/
conf/
doc/
lib/
tests/
My application is database driven. If we can't connect to the database, we have bigger problems.
— Me (1978 - 2011)
<?php
for (i = 0; $i < $config['db_primary_tries'], ++$i) {
try {
$db = new Database($config['db_host'], $config['db_user'], $config['db_password'])
break;
} catch (DBException $dbe) {
$log->warn('Failed connecting to primary database ' . $config['db_host'] . ' ' . ($i + 1) . ' times. ' . $dbe->getMessage());
usleep($config['db_retry_sleep']);
}
}
if (empty($db)) {
$log->error('Could not connect to primary databse ' . $config['db_host'] . ' after ' . $config['db_primary_tries'] . ' attempts. Trying secondary.');
}
// Rinse and repeat for the secondary.
?>
Good teams...
write things down (Logging)
know what to expect from each other (Unit Tests)
adapt quickly to changes (Configurations)
Good developers don't let bad developers bring them down.
Good code isolates features from each other.
Cache
⇔
Secondary DB
⇔
Primary DB
Expect failure, but don't accept it.
How to connect to a database or any other system
Try to connect using the configured timeout settings
Log failure as a warning
Retry the configured number of times, waiting the configurable amount of times between each
Try the configured back up
Repeat 2 & 3 if unsuccessful, log success as a warning
If no connections can be made successfully, log an error, but don't halt execution (it is up to the application to figure out if execution can continue)
You don't give someone production access the day you hire them.
Don't release features the instant you deploy the code.
If you take out the bad code, feature, thrid party, etc., you can relax a bit while fixing the problem.
Good teams...
write things down (Logging)
know what to expect from each other (Unit Tests)
adapt quickly to changes (Configurations)
don't let bad things bring them down (Isolation)
Good developers communicate well with non-technical folks.
Good code doesn't require you to read the code in order to know what the code is doing.
<?php
public function testWebDriver() {
$home_page = new Home(self::$session);
$home_page->open();
$schedule_page = $home_page->navigate_to('Schedule');
$schedule_page->open_session('WebDriver!');
$this->assertEquals($schedule_page->title, "WebDriver!");
}
?>
<?php
/**
* Returns the array of AMQP arguments for the given queue.
*
* Depending on the configuration available, we may have one or more arguments which
* need to be sent to RabbitMQ when the queue is declared. These arguments could be
* things like high availability configurations.
*
* If something in getInstance() is failing, check here first. Trying to declare a
* queue with a set of arguments that does not match the arguments which were used
* the first time the queue was declared most likely will not work. Check the config
* for AMQP and make sure that the arguments have not been changed since the queue
* was originally created. The easiest way to reset them is to kill off the queue
* and try to recreate it based on the new config.
*
* @param string $name The name of the queue which will be used as a key in configs.
*
* @return array The array of arguments from the config.
*/
?>
<?php
private static function _getQueueArgs($name)
{
// Start with nothing.
// We may need to set some configuration arguments.
// Check for queue specific args first and then try defaults.
// Return the args we found.
}
?>
<?php
private static function _getQueueArgs($name)
{
// Start with nothing.
$args = array();
// We may need to set some configuration arguments.
$cfg = Settings\AMQP::getInstance();
// Check for queue specific args first and then try defaults.
if (array_key_exists($name, $cfg['queue_arguments'])) {
$args = $cfg['queue_arguments'][$name];
} elseif (array_key_exists('default', $cfg['queue_arguments'])) {
$args = $cfg['queue_arguments']['default'];
}
// Return the args we found.
return $args;
}
?>
Good teams...
write things down (Logging)
know what to expect from each other (Unit tests)
adapt quickly to changes (Configurations)
don't let bad things bring them down (Isolation)
communicate clearly (Documentation)
We're Hiring!
Great Benefits
Unlimited vacation and sick time
401K matching
Hack day every 5 weeks
No Such Thing as Routine
DAUs measures in millions
Web, Mobile, and Social
PHP, Perl, Unity, Objective-C, Java, MongoDB…
Locations
Waltham, MA — Washington, D.C. — San Francisco, CA — Your house