3. LISKOV SUBSTITUTION PRINCIPLE
“objects in a program should be replaceable
with instances of their subtypes without
altering the correctness of that program.”
5. WE MEET THEIR REQUIREMENTS
class User
{
public function updateStatus($status)
{
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
}
}
// The Facebook SDK
class Facebook
{
public function updateStatus($status);
}
$user->updateStatus($status);
6. NEXT…
“Allow users in our system to post updates
to Facebook or Twitter”
- The Indecisive Client
7. WE MEET THEIR REQUIREMENTS
class User
{
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
// The Twitter SDK
class Twitter {
public function postStatus($status);
}
$user->updateStatus($status);
10. FINE…
class User
{
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
11. FINE…
class User
{
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
class User
{
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->createStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
12. BUT…
class HufflepuffController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
13. BUT…
class HufflepuffController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
class GryffindoorController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
14. BUT…
class HufflepuffController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
class GryffindoorController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
class HogwartsController {
public function updateStatus($status, $gateway = 'FACEBOOK') {
switch($gateway) {
case: "FACEBOOK";
$facebook = new FacebookFacebook;
$facebook->updateStatus($status);
break;
case: "TWITTER";
$twitter = new TwitterTwitter;
$twitter->postStatus($status);
break;
}
}
}
15.
16. IT’S A PAIN
★ We should be able to easily add new
gateways whenever the client asks
★ We should be able to easily adapt to API
changes without too much trouble.
17. ADAPTERS FTW!
★ We need an interface that defines the functionality
required by out application
interface UpdatesStatuses
{
public function post($status);
public function delete($statusId);
}
18. FACEBOOK ADAPTER
class FacebookAdapter implements UpdatesStatuses
{
private $facebook;
public function __construct(FacebookFacebook $facebook)
{
$this->facebook = $facebook;
}
public function post($status)
{
$this->facebook->createStatus($status);
}
public function delete($statusId)
{
$this->facebook->deleteStatus($statusId);
}
}
19. TWITTER ADAPTER
class TwitterAdapter implements UpdatesStatuses
{
private $twitter;
public function __construct(TwitterTwitter $twitter)
{
$this->twitter = $twitter;
}
public function post($status)
{
$this->twitter->postStatus(status);
}
public function delete($statusId)
{
$this->twitter->removeStatus($statusId);
}
}
20. TAKING IT FURTHER
★ We want users to be able to add several social
accounts (connected accounts)
★ When they post using our application, the post
should also be shared on all of their social
accounts.
22. SOCIAL ACCOUNT CLASSES
class FacebookAccount implements SocialAccount
{
public function __construct(FacebookFacebook $facebook) {
$this->facebook = $facebook;
}
public function post($post) {
$this->facebook->createPost($post);
}
}
class TwitterAccount implements SocialAccount
{
public function __construct(TwitterTwitter $twitter) {
$this->twitter = $twitter;
}
public function post($post) {
$this->twitter->makePost($post);
}
}
class LinkedInAccount implements SocialAccount
{
public function __construct(LinkedInLinkedIn $linkedin) {
$this->linkedin = $linkedin;
}
public function post($post) {
$this->linkedin->makePost($post);
}
}
23. THE USER
class User
{
private $connectedAccounts = [];
public function addConnectedAccount(SocialAccount $account)
{
$this->connectedAccounts[] = $account;
}
public function postToAccounts($status)
{
foreach($this->connectedAccounts as $account)
{
$account->post($status);
}
}
}
$user->addConnectedAccount(new FacebookAccount(new FacebookFacebook));
$user->addConnectedAccount(new TwitterAccount(new TwitterTwitter));
$user->addConnectedAccount(new LinkedInAccount(new LinkedInLinkedIn));
// Sometime in the future.
$user->postToAccounts($status)
24. PRO TIP: IOC - INVERSION OF CONTROL
★ Resolves classes and their dependencies without having to
institute them each time
$user->addConnectedAccount(new FacebookAccount(new FacebookFacebook));
// becomes
$user->addConnectedAccount(new FacebookAccount());
★ Laravel has a built in IoC container
★ A few platform agnostic packages available (Pimple, Dice)