Your SlideShare is downloading. ×
OBJECT-ORIENTED PRINCIPLES       WITH PHP5     Jason Austin - @jason_austin     TriPUG Meetup - Jan 18, 2011
GoalsExplain object-oriented conceptsIntroduce PHP5’s object oriented interfaceIllustrate how object-oriented programming ...
What makes good software?"The function of good software is to make the complexappear to be simple." - Grady Booch"Always c...
Software engineering != programming     “Programming is just typing” - Everette Allen
What is software engineering then?Software engineering is the application of a systematic,quantifiable, disciplined approac...
PHP & Software EngineeringPHP is quick to learn, almost to a faultEasy to write bad code  However, PHP provides tools to f...
Procedural Code<?php     include “config.php”;     include “display.php”;     mysql_connect($host, $user, $pass);     echo...
What’s Wrong With That!?Nothing is really wrong with it. But...    It’s really hard to read and follow    As the code base...
How else would I do it?!Object Oriented Programming FTW!
What is OOP?Programming paradigm using “objects” and their interactionsNot really popular until 1990’sBasically the opposi...
When would I use this OOP stuff? When you...  find yourself repeating code  want to group certain functions together  want ...
Why OOP?code resuse!!!maintainabilitycode reuse!!!readabilitycode reuse!!!
OOP TechniquesBefore we get to the code, a little OOP primer   Encapsulation   Modularity   Inheritance   Polymorphism
Encapsulation (It’s like a Twinkie!)Group together data and functionality (bananas and cream)Hide implementation details (...
Modularity (It’s like this sofa!)A property of an application that measures the extent towhich the application has been co...
Inheritance (It’s like Joan & Melissa Rivers)   A hierarchical way to organize data and functionality   Children receive f...
Polymorphism (It’s like that guy)Combines all the other techniquesKind of complicated so we’ll get toit later
Need to know termsclass - A collection of interrelated functions and variablesthat manipulates a single idea or concept.in...
What does a class look like?<?php     // this is a class.   $name and getHeight() are class members     class Person     {...
How to instantiate a class<?php    $p = new Person(); // at this point $p is a new Person object?> Now anyone can use the ...
Protecting Your StuffWhat if you want to keep methods and data from being changed?
ScopingFoundation of OOPImportant for exposing functionality and data to usersProtect data and method integrity
Scopespublicprivateprotected
PublicAnyone (the class itself or any instantiation of that class) can have access to themethod or propertyIf not specified...
Public Example<?php     class Person     {         public function getName()         {             return “Bob McSmithyPan...
PrivateOnly the class itself has access to the method or property
Private Example<?php     class Person     {         public function firstName()         {             return “Bob”;       ...
ProtectedOnly the class itself or a class that extends this class canhave access to the method or property
Protected Example<?php     class Person     {         protected function getName()         {             return “Bob McSmi...
What was with that $this stuff?You can access the protected data and methods with “objectaccessors”These allow you to keep...
Object AccessorsWays to access the data and methods from within objects $this self parent
$this    variable    refers to the current instantiation<?phpclass Person{    public $name = ‘bob’;    public function get...
self    keyword that refers to the class itself regardless of    instantiation status    not a variable<?phpclass Person{ ...
parent<?phpclass Person                                    keyword that refers to the parent class{    public $name = ‘bob...
Class constantsDefined with the “const” keywordAlways staticNot declared or used with $Must be a constant expression, not a...
Constant Example<?phpclass DanielFaraday{    const MY_CONSTANT = Desmond;     public static function getMyConstant()     {...
Class and Method PropertiesFinal and StaticClasses and methods can be declared either final, static, orboth!
Important Note!Class member scopes (public, private, and protected) andthe class and method properties (final and static) a...
FinalProperties or methods declared final cannot be overridden by a subclass
Final Example<?php     class Person     {         public final function getName()         {             return “Steve Dave...
StaticA method declared as static can be accessed withoutinstantiating the classYou cannot use $this within static functio...
Static Example<?php     class About     {         public static function getVersion()         {             return “Versio...
Types of ClassesAbstract ClassInterface
Abstract ClassesNever directly instantiatedAny subclass will have the properties and methods of theabstract classUseful fo...
Abstract Example<?php                                                 <?php     abstract class Car     {                  ...
InterfacesDefines which methods are required for implementing anobjectSpecifies the abstract intention of a class without pr...
Interface Example<?php                                            <?php     interface Car     {                           ...
instanceof Operator to check if one class is an instance of another class<?php                                            ...
Type HintingPHP is not strongly typed (i.e. - variables can bepretty much anything anytime)In PHP4 you have to do a lot of...
Type Hinting Example<?php    // this can be made better with type hinting!    public function promoteToManager($bob)    { ...
A Few More Termsserialize - Converting an object to a binary form (i.e. -writing an object to a file)unserialize - The oppo...
Magic MethodsMethods provided by PHP5 automagically (called by PHP on certain events)Always begin with __ (two underscores...
Magic Methods__construct()            __sleep()__destruct()             __wakeup()__get()                  __isset()__set(...
__construct() & __destruct()__construct() runs when a new object is instantiated.Suitable for any initialization that the ...
__get()       __get() is called when trying to access an undeclared       property<?phpclass Car{     protected $_data = a...
__set()       __set() is called when trying to assign an undeclared       property<?phpclass Car{     protected $_data = a...
__isset()       Used to check whether or not a data member has been declared<?phpclass Car{    protected $_data = array(  ...
__unset()        Removes a data member from a class<?phpclass Car{    protected $_data = array(        ‘door’ => 4,       ...
__call()__call() is executed when trying to access a method thatdoesn’t existThis allows you to handle unknown functions h...
_call() Example<?phpclass Sample{     public function __call($func, $arguments)     {         echo "Error accessing undefi...
__toString()Returns the string representation of a classIs automatically called whenever trying to print or echo aclass.Us...
__toString() Example<?php    class SqlQuery    {        protected $_table;        protected $_where;        protected $_or...
__sleep()Called while serializing an object__sleep() lets you define how you want the object to bestoredAlso allows you to ...
__wakeup()The opposite of __sleep() basicallyCalled when an object is being unserializedAllows you to restore the class da...
__clone()In php setting one object to anotherdoes not copy the original object;only a reference to the original ismadeTo a...
__clone() example<?php    class Animal    {        public $color;        public function setColor($color)        {        ...
__autoload()Called when you try to load a class in a file that was notalready includedAllows you to do new myClass() withou...
_autoload() example<?php     class Account     {         public function __autoload($classname)         {             requ...
A little exampleYou can use all this stuff you just learned about inheritance,scoping, interfaces, and abstract classes to...
How Would You Solve This?I have a bunch of shapes of which I want to find the areaI could get any combination of different ...
Polymorphism is the answer!...What exactly would you say that is?
PolymorphismThe last object-oriented technique!Combination of the other techniquesAllowing values of different types to be...
Polymorphism Example!Polymorphism allows a set of heterogeneous elements to betreated identically.Achieved through inherit...
Polymorphism<?php     interface HasArea     {         public function area();     }?>
Polymorphism<?php     abstract class Shape     {         private $_color;         public function __construct($color)     ...
Polymorphism<?php     class Rectangle extends Shape implements HasArea     {         private $_w; // width         private...
Polymorphism<?php     class Circle extends Shape implements HasArea     {         private $_r; // radius         public fu...
Polymorphism<?php    // this function will only take a shape that implements HasArea    function getArea(HasArea $shape)  ...
QUESTIONS?      Jason Austin    @jason_austin  jfaustin@gmail.comhttp://jasonawesome.com
Upcoming SlideShare
Loading in...5
×

Object Oriented PHP5

45,533

Published on

Discussion on the techniques and principles of Object Oriented PHP5, including encapsulation, polymorphism, inheritance, scoping, and more.

Published in: Technology
4 Comments
21 Likes
Statistics
Notes
No Downloads
Views
Total Views
45,533
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
0
Comments
4
Likes
21
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Describe a little about how exactly a class becomes an object and how that works with respect to interacting with an object in memory and not the class specifically\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • First one is false, second one is true\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Talk about difference from PHP4\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript of "Object Oriented PHP5"

    1. 1. OBJECT-ORIENTED PRINCIPLES WITH PHP5 Jason Austin - @jason_austin TriPUG Meetup - Jan 18, 2011
    2. 2. GoalsExplain object-oriented conceptsIntroduce PHP5’s object oriented interfaceIllustrate how object-oriented programming can help youHelp you write better code
    3. 3. What makes good software?"The function of good software is to make the complexappear to be simple." - Grady Booch"Always code as if the guy who ends up maintaining yourcode will be a violent psychopath who knows where youlive." - Martin GoldingGood software needs good software engineering
    4. 4. Software engineering != programming “Programming is just typing” - Everette Allen
    5. 5. What is software engineering then?Software engineering is the application of a systematic,quantifiable, disciplined approach to development.Programming is simply one phase of development
    6. 6. PHP & Software EngineeringPHP is quick to learn, almost to a faultEasy to write bad code However, PHP provides tools to facilitate the creation of solid and organized softwarePHP started as a procedural language, but has evolved!
    7. 7. Procedural Code<?php include “config.php”; include “display.php”; mysql_connect($host, $user, $pass); echo “<html>”; echo “ <head>”; echo “ <title>Page</title>”; echo “ </head>”; echo “ <body>”; printMenu(); $result = mysql_query(“Select * from news”); printContent($result); echo “</body></html>”;?>
    8. 8. What’s Wrong With That!?Nothing is really wrong with it. But... It’s really hard to read and follow As the code base grows, maintainability decreases New additions often become hacks Designers can’t easily design unless they know PHP
    9. 9. How else would I do it?!Object Oriented Programming FTW!
    10. 10. What is OOP?Programming paradigm using “objects” and their interactionsNot really popular until 1990’sBasically the opposite of procedural programming
    11. 11. When would I use this OOP stuff? When you... find yourself repeating code want to group certain functions together want to easily share some of your code want to have an organized code base think you may reuse some of your code later
    12. 12. Why OOP?code resuse!!!maintainabilitycode reuse!!!readabilitycode reuse!!!
    13. 13. OOP TechniquesBefore we get to the code, a little OOP primer Encapsulation Modularity Inheritance Polymorphism
    14. 14. Encapsulation (It’s like a Twinkie!)Group together data and functionality (bananas and cream)Hide implementation details (how they get the filling in there)Provide an explicitly definedway to interact with the data(they’re always the same shape)Hides the creamy center!
    15. 15. Modularity (It’s like this sofa!)A property of an application that measures the extent towhich the application has been composed of separate parts(modules)Easier to have a moreloosely-coupled applicationNo one part is programaticallybound to another
    16. 16. Inheritance (It’s like Joan & Melissa Rivers) A hierarchical way to organize data and functionality Children receive functionality and properties of their ancestors is-a and has-a relationships Inherently (hah!) encourages code reuse
    17. 17. Polymorphism (It’s like that guy)Combines all the other techniquesKind of complicated so we’ll get toit later
    18. 18. Need to know termsclass - A collection of interrelated functions and variablesthat manipulates a single idea or concept.instantiate - To allocate memory for a class.object - An instance of a classmethod - A function within a classclass member - A method or variable within a class
    19. 19. What does a class look like?<?php // this is a class. $name and getHeight() are class members class Person { public $name = “Bob McSmithyPants”; // this is a class variable public function getHeight() // this is a class method {} }?>
    20. 20. How to instantiate a class<?php $p = new Person(); // at this point $p is a new Person object?> Now anyone can use the Person object (call its methods, change its variables, etc.)
    21. 21. Protecting Your StuffWhat if you want to keep methods and data from being changed?
    22. 22. ScopingFoundation of OOPImportant for exposing functionality and data to usersProtect data and method integrity
    23. 23. Scopespublicprivateprotected
    24. 24. PublicAnyone (the class itself or any instantiation of that class) can have access to themethod or propertyIf not specified, a method or property is declared public by default
    25. 25. Public Example<?php class Person { public function getName() { return “Bob McSmithyPants”; } }?><?php $p = new Person(); echo $p->getName();?>
    26. 26. PrivateOnly the class itself has access to the method or property
    27. 27. Private Example<?php class Person { public function firstName() { return “Bob”; } private function lastName() { return “McSmithyPants”; } }?><?php $p = new Person(); echo $p->firstName(); // this will work echo $p->lastName(); // this does not work?>
    28. 28. ProtectedOnly the class itself or a class that extends this class canhave access to the method or property
    29. 29. Protected Example<?php class Person { protected function getName() { return “Bob McSmithyPants”; } } class Bob extends Person { public function whatIsMyName() { return $this->getName(); } }?><?php $p = new Person(); echo $p->getName(); // this won’t work $b = new Bob(); echo $b->whatIsMyName(); // this will work?>
    30. 30. What was with that $this stuff?You can access the protected data and methods with “objectaccessors”These allow you to keep the bad guys out, but still let the goodguys in.
    31. 31. Object AccessorsWays to access the data and methods from within objects $this self parent
    32. 32. $this variable refers to the current instantiation<?phpclass Person{ public $name = ‘bob’; public function getName() { return $this->name; }}$p = new Person();echo $p->getName();// will print bob?>
    33. 33. self keyword that refers to the class itself regardless of instantiation status not a variable<?phpclass Person{ public static $name = ‘bob’; public function getName() { return self::$name; }}$p = new Person();echo $p->getName();// will print bob?>
    34. 34. parent<?phpclass Person keyword that refers to the parent class{ public $name = ‘bob’; most often used when overriding public function getName() { methods return $this->name; }} also not a variable!class Bob extends Person{ What would happen if we used public function getName() { $this->getName() instead of } return strtoupper(parent::getName()); parent::getName()?}$bob = new Bob();echo $bob->getName();// will print BOB?>
    35. 35. Class constantsDefined with the “const” keywordAlways staticNot declared or used with $Must be a constant expression, not a variable, class member,result of a mathematical expression or a function callMust start with a letter
    36. 36. Constant Example<?phpclass DanielFaraday{ const MY_CONSTANT = Desmond; public static function getMyConstant() { return self::MY_CONSTANT; }}echo DanielFaraday::MY_CONSTANT;echo DanielFaraday::getMyConstant();$crazyTimeTravelDude = new DanielFaraday();echo $crazyTimeTravelDude->getMyConstant();?>
    37. 37. Class and Method PropertiesFinal and StaticClasses and methods can be declared either final, static, orboth!
    38. 38. Important Note!Class member scopes (public, private, and protected) andthe class and method properties (final and static) are notmutually exclusive!
    39. 39. FinalProperties or methods declared final cannot be overridden by a subclass
    40. 40. Final Example<?php class Person { public final function getName() { return “Steve Dave”; } } class Bob extends Person { public function getName() { return “Bob McSmithyPants”; } } // this will fail when trying to include Bob?>
    41. 41. StaticA method declared as static can be accessed withoutinstantiating the classYou cannot use $this within static functions because $thisrefers to the current instantiationAccessed via the scope resolution operator ( :: )i.e. – About::getVersion();
    42. 42. Static Example<?php class About { public static function getVersion() { return “Version 2.0”; } }?><?php echo About::getVersion(); ?>
    43. 43. Types of ClassesAbstract ClassInterface
    44. 44. Abstract ClassesNever directly instantiatedAny subclass will have the properties and methods of theabstract classUseful for grouping generic functionality of subclassedobjectsAt least one method must be declared as abstract
    45. 45. Abstract Example<?php <?php abstract class Car { $honda = new Honda(); private $_color; $honda->setColor(“black”); $honda->drive(); abstract public function drive(); ?> public function setColor($color) { $this->_color = $color; } public function getColor() { return $this->_color; } } class Honda extends Car { public function drive() { $color = $this->getColor(); echo “I’m driving a $color car!”; } }?>
    46. 46. InterfacesDefines which methods are required for implementing anobjectSpecifies the abstract intention of a class without providingany implementationLike a blueprint or templateA class can simultaneously implement multiple interfaces
    47. 47. Interface Example<?php <?php interface Car { $honda = new Honda(); public function start(); $honda->start(); public function drive(); $honda->drive(); public function stop(); $honda->stop(); } ?> class Honda implements Car { public function start() { echo “Car is started!”; } public function drive() { echo “I’m driving!”; } public function stop() { echo “The car has stopped!”; } }?>
    48. 48. instanceof Operator to check if one class is an instance of another class<?php <?php class Car class Car {} {} class Honda extends Car class Honda extends Car {} {} $car = new Car(); OR $car = new Honda(); $honda = new Honda(); if ($car instanceof Car) { if ($car instanceof $honda) { echo “true”; echo “true”; } else { } else { echo “false”; echo “false”; } } ?>?> What will get printed?
    49. 49. Type HintingPHP is not strongly typed (i.e. - variables can bepretty much anything anytime)In PHP4 you have to do a lot of checkingto find out if a parameter is the correct typeType Hinting helps make this more efficient
    50. 50. Type Hinting Example<?php // this can be made better with type hinting! public function promoteToManager($bob) { if (!is_a($bob, “Person”)) { throw new Exception(“$bob is not a Person!”); } // do stuff with $bob }?>... becomes ...<?php // this is better! public function promoteToManager(Person $bob) { // do stuff with $bob }?>
    51. 51. A Few More Termsserialize - Converting an object to a binary form (i.e. -writing an object to a file)unserialize - The opposite of serialize. To convert thestored binary representation of an object back into theobject.reference - An pointer to an object’s location in memoryrather than the actual object
    52. 52. Magic MethodsMethods provided by PHP5 automagically (called by PHP on certain events)Always begin with __ (two underscores)Declared public by default but can be overridden
    53. 53. Magic Methods__construct() __sleep()__destruct() __wakeup()__get() __isset()__set() __unset()__call() __autoload()__toString() __clone()
    54. 54. __construct() & __destruct()__construct() runs when a new object is instantiated.Suitable for any initialization that the object may need beforeit’s used.__destruct() runs when all references to an object are nolonger needed or when the object is explicitly destroyed.
    55. 55. __get() __get() is called when trying to access an undeclared property<?phpclass Car{ protected $_data = array( ‘door’ => 4, ‘type’ => ‘Jeep’, ‘vin’ => ‘2948ABJDKZLE’ ); public function __get($varName) { return $this->_data[$varName]; }}$car = new Car();echo $car->vin; // will print out 2948ABJDKZLE?>
    56. 56. __set() __set() is called when trying to assign an undeclared property<?phpclass Car{ protected $_data = array( ‘door’ => 4, ‘type’ => ‘Jeep’, ‘vin’ => ‘2948ABJDKZLE’ ); public function __set($varName, $value) { $this->_data[$varName] = $value; }}$car = new Car();$car->vin = ‘ABC’;echo $car->vin; // will print out ABC?>
    57. 57. __isset() Used to check whether or not a data member has been declared<?phpclass Car{ protected $_data = array( ‘door’ => 4, ‘type’ => ‘Jeep’, ‘vin’ => ‘2948ABJDKZLE’ ); public function __isset($varName) { return isset($this->_data[$varName]); }}$car = new Car();if (isset($car->color)) { echo “color is set!”;} else { echo “color isn’t set!”;}// will print color isn’t set?>
    58. 58. __unset() Removes a data member from a class<?phpclass Car{ protected $_data = array( ‘door’ => 4, ‘type’ => ‘Jeep’, ‘vin’ => ‘2948ABJDKZLE’ ); public function __unset($varName) { return unset($this->_data[$varName]); }}$car = new Car();unset($car->vin);if (isset($car->vin)) { echo “vin is set!”;} else { echo “vin isn’t set!”;}// will print vin isn’t set?>
    59. 59. __call()__call() is executed when trying to access a method thatdoesn’t existThis allows you to handle unknown functions however you’dlike.
    60. 60. _call() Example<?phpclass Sample{ public function __call($func, $arguments) { echo "Error accessing undefined Method<br />"; echo "Method Called: " . $func . "<br />"; echo "Argument passed to the Method: "; print_r($arguments); }}$sample = new Sample();echo $sample->doSomeStuff("Test");?>
    61. 61. __toString()Returns the string representation of a classIs automatically called whenever trying to print or echo aclass.Useful for defining exactly what you want an object to looklike as a stringCan also be used to prevent people from printing the classwithout throwing an exception
    62. 62. __toString() Example<?php class SqlQuery { protected $_table; protected $_where; protected $_orderBy; protected $_limit; public function __construct($table, $where, $orderBy, $limit) { $this->_table = $table; $this->_where = $where; $this->_orderBy = $orderBy; $this->_limit = $limit; } public function __toString() { $query = “SELECT * “ . “FROM $this->_table “ . “WHERE $this->_where “ . “ORDER BY $this->_orderBy “ . “LIMIT $this->_limit”; return $query; } }$test = new SqlQuery(tbl_users, “userType = ‘admin’”, ‘name’, 10);echo $test;?>
    63. 63. __sleep()Called while serializing an object__sleep() lets you define how you want the object to bestoredAlso allows you to do any clean up you want beforeserializationUsed in conjunction with __wakeup()
    64. 64. __wakeup()The opposite of __sleep() basicallyCalled when an object is being unserializedAllows you to restore the class data to its normal form
    65. 65. __clone()In php setting one object to anotherdoes not copy the original object;only a reference to the original ismadeTo actually get a second copy of theobject, you must use the __clonemethod
    66. 66. __clone() example<?php class Animal { public $color; public function setColor($color) { $this->color = $color; } public function __clone() { echo "<br />Cloning animal..."; } }$tiger = new Animal();$tiger->color = "Orange";$unicorn = clone $tiger;$unicorn->color = "white";echo "<br /> A tiger is " . $tiger->color;echo "<br /> A unicorn is " . $unicorn->color;?>
    67. 67. __autoload()Called when you try to load a class in a file that was notalready includedAllows you to do new myClass() without having to includemyClass.php first.
    68. 68. _autoload() example<?php class Account { public function __autoload($classname) { require_once $classname . ‘.php’; //$classname will be Profile } public function __construct() { $profile = new Profile(); } }?>
    69. 69. A little exampleYou can use all this stuff you just learned about inheritance,scoping, interfaces, and abstract classes to do some morecomplex things!
    70. 70. How Would You Solve This?I have a bunch of shapes of which I want to find the areaI could get any combination of different shapesI want to be able to find the area without having to knowthe details of the calculation myself.What OOP techniques could we use to solve this problem?
    71. 71. Polymorphism is the answer!...What exactly would you say that is?
    72. 72. PolymorphismThe last object-oriented technique!Combination of the other techniquesAllowing values of different types to be handled by a uniforminterface
    73. 73. Polymorphism Example!Polymorphism allows a set of heterogeneous elements to betreated identically.Achieved through inheritance
    74. 74. Polymorphism<?php interface HasArea { public function area(); }?>
    75. 75. Polymorphism<?php abstract class Shape { private $_color; public function __construct($color) { $this->_color = $color; } public function getColor() { return $this->_color; } }?>
    76. 76. Polymorphism<?php class Rectangle extends Shape implements HasArea { private $_w; // width private $_h; // height public function __construct($color, $w, $h) { parent::__construct($color); $this->_w = $w; $this->_h = $h; } public function area() { return ($this->_w * $this->_h); } }?>
    77. 77. Polymorphism<?php class Circle extends Shape implements HasArea { private $_r; // radius public function __construct($color, $r) { parent::__construct($color); $this->_r = $r; } public function area() { return (3.14 * pow($this->_r, 2)); } }?>
    78. 78. Polymorphism<?php // this function will only take a shape that implements HasArea function getArea(HasArea $shape) { return $shape->area(); } $shapes = array( rectangle => new Rectangle("red", 2, 3), circle => new Circle("orange", 4) ); foreach ($shapes as $shapeName => $shape) { $area = getArea($shape); echo $shapeName . " has an area of " . $area . "<br />"; }// will print:// rectangle has an area of 6// circle has an area of 50.24?>
    79. 79. QUESTIONS? Jason Austin @jason_austin jfaustin@gmail.comhttp://jasonawesome.com

    ×