Your SlideShare is downloading. ×
0
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Lean Php Presentation
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Lean Php Presentation

14,325

Published on

Overview of issues with doing lean development in PHP -- Project Management, Testing, and Community.

Overview of issues with doing lean development in PHP -- Project Management, Testing, and Community.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
14,325
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
27
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Lean PHP Practices Alan Pinstein & Jason Ardell Atlanta PHP Users Group April 1, 2009
  • 2. What is Leverage? More work the first time, usually involves: Learning a new library or tool Setting up infrastructure Easier to do it 2..∞ Easier to maintain
  • 3. Types of Leverage Project Leverage Testing Leverage Community Leverage
  • 4. Project Leverage It hurts when I... Set up my project on a new machine Deploy new versions of my project Stop doing that!
  • 5. Project Leverage - Tools mp - Migrations for PHP (presentation) rake/cap => pantr is php gitflow user_management Dependency management runit - daemons / process supervision config-magic
  • 6. runit Process Supervisor Don’t write daemons - you’ll do it wrong Write scripts, and runit keeps them alive in the background Gracefully handles errors, failures, logging, upgrades
  • 7. runit in action // graceful upgrade 2010-02-10_03:53:55 Stop requested for worker process on queue: inbox 2010-02-10_03:53:55 Stopping worker process on queue: inbox 2010-02-10_03:53:56 Starting worker process on queue: inbox // graceful error handling 2010-04-01_17:55:08 [Job: 383820 RUNNING] Process InboxImage 60629 (Carol 011_fi.jpg) 2010-04-01_17:55:08 [Job: 383820 COMPLETED] 2010-04-01_17:55:08 JQWorker doesn't have enough memory for next job (4194304). 2010-04-01_17:55:08 Starting worker process on queue: inbox 2010-04-01_17:55:09 [Job: 383821 RUNNING] Process InboxImage 60622 (Carol 015_fi.jpg) 2010-04-01_17:55:09 [Job: 383821 COMPLETED]
  • 8. config-magic N config files * M environments = Too Many Config Files Config-Magic applies “profiles”: dev-alan, dev-jason, staging, production to “templates”: framework, orm, rake, cap, shell scripts, webserver
  • 9. # config.ini [templates] httpd.configFileTemplate = ##TEMPLATES_DIR##/##CONFIG##.conf httpd.configFile = ##OUTPUT_DIR##/##CONFIG##.conf propel-conf.configFileTemplate = ##TEMPLATES_DIR##/virtualtour-conf.php propel-conf.configFile = ##OUTPUT_DIR##/virtualtour-conf.php propel-build-properties.configFileTemplate = ##TEMPLATES_DIR##/build.properties propel-build-properties.configFile = ##OUTPUT_DIR##/../propel-build/ build.properties propel-conf-xml.configFileTemplate = ##TEMPLATES_DIR##/runtime-conf.xml propel-conf-xml.configFile = ##OUTPUT_DIR##/../propel-build/runtime-conf.xml webapp.configFileTemplate = ##TEMPLATES_DIR##/##CONFIG##.conf webapp.configFile = ##OUTPUT_DIR##/##CONFIG##.conf sh.configFileTemplate = ##TEMPLATES_DIR##/##CONFIG##.conf sh.configFile = ##OUTPUT_DIR##/##CONFIG##.conf [data] ; your default data here. any settings here will be overridden by values in the profile's ini file on a setting-by-setting basis isProduction = false path.psql = /usr/bin/psql path.convert = /usr/bin/convert path.propel-gen = externals/pear/propel-gen path.phocoa = ##path.project.appDir##/externals/phocoa/phocoa path.php.include_path = ##path.phocoa##:##path.project.appDir##:##path.project.appDir##/ classes:##path.project.appDir##/externals:##path.project.appDir##/externals/pear/php path.php = "/usr/bin/php -d include_path=##path.php.include_path##" app.group = showcase_web app.user = tourbuzz httpd.user = _www
  • 10. # profile - dev.ini path.php = "/opt/local/bin/php -d include_path=##path.php.include_path##" path.project.containerDir = /Users/ardell/Documents/workspace/ tourbuzz path.project.appDir = ##path.project.containerDir##/tourbuzz path.awstats = /opt/showcase/awstats/wwwroot/cgi-bin/awstats.pl path.convert = /opt/local/bin/convert path.psql = /opt/local/lib/postgresql83/bin/psql host.name = ardell.dev.tourbuzz.net host.aliases = host.ip = 127.0.0.1 host.port = 8080 db.host = localhost db.name = virtualtour_dev db.user = virtualtour db.pass = app.user = ardell app.group = tourbuzz_web runit.system_service_dir = /opt/local/var/service
  • 11. # template #!/bin/sh PHP="##path.php##" export PSQL=##path.psql## export IS_PRODUCTION=<?php print ($profileData ['##isProduction##'] ? 1 : 0); ?> # db settings export DB_ROOT_USER=##db.root.user## export DB_USER=##db.user## export DB_NAME=##db.name## export DB_HOST=##db.host## export PROJECT_DIR=##path.project.containerDir## export LOG_DIR=$PROJECT_DIR/log export APP_DIR=##path.project.appDir## export APP_USER=##app.user## export APP_GROUP=##app.group##
  • 12. $ cfg dev #!/bin/sh PHP="/opt/local/bin/php -d include_path=/Users/alanpinstein/dev/sandbox/ virtualtour/tourbuzz/externals/phocoa/phocoa:/Users/alanpinstein/dev/sandbox/ virtualtour/tourbuzz:/Users/alanpinstein/dev/sandbox/virtualtour/tourbuzz/ classes:/Users/alanpinstein/dev/sandbox/virtualtour/tourbuzz/externals:/Users/ alanpinstein/dev/sandbox/virtualtour/tourbuzz/externals/pear/php" export PSQL=/opt/local/lib/postgresql83/bin/psql export IS_PRODUCTION=0 # db settings export DB_ROOT_USER=postgres export DB_USER=virtualtour export DB_NAME=virtualtour_dev export DB_HOST=localhost export PROJECT_DIR=/Users/alanpinstein/dev/sandbox/virtualtour export LOG_DIR=$PROJECT_DIR/log export APP_DIR=/Users/alanpinstein/dev/sandbox/virtualtour/tourbuzz export APP_USER=alanpinstein export APP_GROUP=showcase_web
  • 13. Testing Leverage It hurts when I... Refactor Introduce regression bugs Don’t have confidence that my code works Have to test my web pages in N browsers
  • 14. Testing Leverage -Tools Write Testable Code - Miško Hevery This is the hard part - there are good tools for the rest Writing Tests (PHPUnit) Mocking Collaborators - $this->getMock(‘MyClass’) Scenario-based Tests - @dataProvider Bootstrapping Data (Fixturenator) Selenium RC - SauceLabs Hosted Browsers
  • 15. fixturenator Test Data doesn’t always scale Makes it easy to decouple tests from test data Prototypal Test Data Generation Inspired by factory_girl
  • 16. fixturenator - Define Objects // Static data for each instance Fixturenator::define('User', array('username' => 'joe')); Fixturenator::define('User', function($factory) { $factory->username = 'joe'; }); Fixturenator::define('User', create_function('$factory', ' $factory->username = 'joe'; '}); // Dynamism $user = Fixturenator::create('User', array('password' => 'return rand (1000,9999);')); $user = Fixturenator::create('User', array('email' => 'return "{$o- >username}@domain.com";')); // Sequences Fixturenator::createSequence('username', 'return "username{$n}";'); Fixturenator::getSequence('username')->next(); // => username1 Fixturenator::getSequence('username')->next(); // => username2
  • 17. fixturenator - Build Object Graphs // Factory.php Fixturenator::define('ValidUser', array('username' => 'joe')); // Test.php // Returns an unsaved User instance $user = Fixturenator::create('ValidUser'); // Customize the generated object $user = Fixturenator::create('ValidUser', array('password' => '1234')); $this->assertTrue($user->validate()); $user->setPassword(NULL); // User requires password $this->assertFalse($user->validate());
  • 18. Community Leverage It hurts when I.... Try to share my PHP libraries with other people Re-write code that I know already exists Try to fix bugs in projects that aren’t my own
  • 19. Community Leverage - Tools Pearfarm (Gemcutter for PHP) A Community PEAR Server Trivially Easy to Make PEAR Packages “App Store” Effect GitHub Social Coding Infrastructure Easy to contribute / accept contributions “App Store” Effect
  • 20. pearfarm $spec = Pearfarm_PackageSpec::create(array(Pearfarm_PackageSpec::OPT_BASEDIR => dirname(__FILE__))) ->setName('fixturenator') ->setChannel('apinstein.pearfarm.org') ->setSummary('A factory-based fixture generator.') ->setDescription('AWESOME.') ->setReleaseVersion('0.0.3') ->setReleaseStability('alpha') ->setApiVersion('0.0.3') ->setApiStability('alpha') ->setLicense(Pearfarm_PackageSpec::LICENSE_MIT) ->setNotes('http://github.com/apinstein/fixturenator') ->addMaintainer('lead', 'Alan Pinstein', 'apinstein', 'apinstein@mac.com') ->addFilesSimple('Fixturenator.php');
  • 21. PHP really needs... CLI Framework (for building good tools) Project Management (rake/cap) PEAR/Dependency Management Efficient PEAR install/upgrades Non-PEAR code: php/lib/exec Better Community More Quality Contributions More Cooperation More Use of Modern Language Features

×