Slide 1

Slide 1 text

clean code: refactoring PRESENTED BY JEFF CAROUTH @jcarouth Saturday, February 8, 14

Slide 2

Slide 2 text

is hard Programming Saturday, February 8, 14

Slide 3

Slide 3 text

Why is programming difficult? Saturday, February 8, 14

Slide 4

Slide 4 text

Are you a compiler? Saturday, February 8, 14

Slide 5

Slide 5 text

Any fool can write code a computer can understand.” “ Saturday, February 8, 14

Slide 6

Slide 6 text

Good programmers write code humans can understand.” “ – Martin Fowler Saturday, February 8, 14

Slide 7

Slide 7 text

Read These Books Saturday, February 8, 14

Slide 8

Slide 8 text

clean code Saturday, February 8, 14

Slide 9

Slide 9 text

Clean code is readable; it tells a story. Saturday, February 8, 14

Slide 10

Slide 10 text

Clean code is cared for; it is maintained. Saturday, February 8, 14

Slide 11

Slide 11 text

Clean code is efficient; it is done right. Saturday, February 8, 14

Slide 12

Slide 12 text

Clean code is extensible; it is able to solve tomorrow’s problems. Saturday, February 8, 14

Slide 13

Slide 13 text

Clean code is simple; it is easy to understand how it works and what it does. Saturday, February 8, 14

Slide 14

Slide 14 text

the two rules of clean code Saturday, February 8, 14

Slide 15

Slide 15 text

Rule #1 Write dirty code, then clean it. Saturday, February 8, 14

Slide 16

Slide 16 text

Rule #1 Write dirty code, then clean it. You cannot write clean code at first. > Saturday, February 8, 14

Slide 17

Slide 17 text

Rule #1 Write dirty code, then clean it. You cannot write clean code at first. Your first pass at solving a problem will not be your best. > > Saturday, February 8, 14

Slide 18

Slide 18 text

Rule #1 Write dirty code, then clean it. You cannot write clean code at first. Your first pass at solving a problem will not be your best. > > Successive refinement through refactoring is the key to clean code. > Saturday, February 8, 14

Slide 19

Slide 19 text

Rule #2 Leave the code cleaner than you found it. Saturday, February 8, 14

Slide 20

Slide 20 text

Rule #2 Leave the code cleaner than you found it. Shamelessly borrowed from the Boy Scouts of America. > Saturday, February 8, 14

Slide 21

Slide 21 text

Rule #2 Leave the code cleaner than you found it. Shamelessly borrowed from the Boy Scouts of America. Incremental changes are the way to go. > > Saturday, February 8, 14

Slide 22

Slide 22 text

Rule #2 Leave the code cleaner than you found it. Shamelessly borrowed from the Boy Scouts of America. Incremental changes are the way to go. > > Even if the only change you make is cosmetic, you are maintaining clean code. > Saturday, February 8, 14

Slide 23

Slide 23 text

an example Saturday, February 8, 14

Slide 24

Slide 24 text

class AccountService { public function find($id) { if (is_string($id) && strlen($id) == 36) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } else { throw new \InvalidArgumentException('ID is not valid'); } } } Saturday, February 8, 14

Slide 25

Slide 25 text

class AccountService { public function find($id) { if (is_string($id) && strlen($id) == 36) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } else { throw new \InvalidArgumentException('ID is not valid'); } } } Saturday, February 8, 14

Slide 26

Slide 26 text

When you have a significant number of nested conditionals, you can refactor them to be more understandable using guard clauses. Refactoring Saturday, February 8, 14

Slide 27

Slide 27 text

class AccountService { public function find($id) { if (is_string($id) && strlen($id) == 36) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } else { throw new \InvalidArgumentException('ID is not valid'); } } } Saturday, February 8, 14

Slide 28

Slide 28 text

class AccountService { public function find($id) { if (!is_string($id) || strlen($id) != 36) { throw new \InvalidArgumentException('Account ID is not valid'); } $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } } Saturday, February 8, 14

Slide 29

Slide 29 text

Complicated or boolean expressions using magic numbers or otherwise non-obvious logic should be refactored to a descriptively named helper method. Refactoring Saturday, February 8, 14

Slide 30

Slide 30 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } //snip – my favorite slide-only refactoring } private function isValidId($id) { return is_string($id) && strlen($id) == 36; } } Saturday, February 8, 14

Slide 31

Slide 31 text

public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } Saturday, February 8, 14

Slide 32

Slide 32 text

Extract what could be common functionality, or even functionality that belongs on a different object into methods. Refactoring Saturday, February 8, 14

Slide 33

Slide 33 text

private function fetchAccountDataById($id) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); } else { $data = array(); } return $data; } Saturday, February 8, 14

Slide 34

Slide 34 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->fetchAccountDataById($id); if (empty($data)) { return null; } $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } private function fetchAccountDataById($id) { //snip – slides are not very tall } } Saturday, February 8, 14

Slide 35

Slide 35 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->fetchAccountDataById($id); if (empty($data)) { return null; } $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } } Saturday, February 8, 14

Slide 36

Slide 36 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->fetchAccountDataById($id); return $this->buildAccountFromData($data); } private function buildAccountFromData($data) { if (empty($data)) { return null; } $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } // snip } Saturday, February 8, 14

Slide 37

Slide 37 text

Replace instances of returning null in place of an object with returning instances of a NullObject where possible and appropriate. Refactoring Saturday, February 8, 14

Slide 38

Slide 38 text

$accountService = new AccountService(new MyPdoWrapper(...)); $account = $accountService->fetch('...'); if (null === $account) { //bail. we don't have a valid account } if (!$account->isActive()) { //error the account is not active } Saturday, February 8, 14

Slide 39

Slide 39 text

class NullAccount extends Account { public function isActive() { return false; } } Saturday, February 8, 14

Slide 40

Slide 40 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->fetchAccountDataById($id); return $this->buildAccountFromData($data); } private function buildAccountFromData($data) { if (empty($data)) { return new NullAccount(); } $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } // snip } Saturday, February 8, 14

Slide 41

Slide 41 text

Extract methods or logic into classes when the code isn’t necessarily relevant to the object you are working in. Refactoring Saturday, February 8, 14

Slide 42

Slide 42 text

class AccountService { // snip private function fetchAccountDataById($id) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); } else { $data = array(); } return $data; } // snip } Saturday, February 8, 14

Slide 43

Slide 43 text

class AccountDataProvider { public function __construct(PDO $pdo) { $this->dbh = $pdo; } public function fetchById($id) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); } else { $data = array(); } return $data; } } Saturday, February 8, 14

Slide 44

Slide 44 text

class AccountService { // snip public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->provider->fetchById($id); return $this->buildAccountFromData($data); } // snip } Saturday, February 8, 14

Slide 45

Slide 45 text

$accountService = new AccountService(new AccountDataProvider($pdo)); $account = $accountService->fetch('...'); if (!$account->isActive()) { //error the account is not active } Saturday, February 8, 14

Slide 46

Slide 46 text

Which is more readable? Saturday, February 8, 14

Slide 47

Slide 47 text

class AccountService { public function find($id) { if (isset($id) && strlen($id) == 36) { $statement = $this->db->prepare( "SELECT * FROM accounts WHERE id = :account_id" ); $statement->execute(['account_id' => $id]); if ($statement->rowCount() == 1) { $data = $statement->fetch(); $account = new Account(); $account->setId($data['id']); $account->setName($data['name']); return $account; } else { return null; } } else { throw new \InvalidArgumentException('ID is not valid'); } } } Saturday, February 8, 14

Slide 48

Slide 48 text

class AccountService { public function find($id) { if (!$this->isValidId($id)) { throw new \InvalidArgumentException('Account ID is not valid'); } $data = $this->provider->fetchById($id); return $this->buildAccountFromData($data); } // snip } Saturday, February 8, 14

Slide 49

Slide 49 text

Two examples are better than one Saturday, February 8, 14

Slide 50

Slide 50 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true) { $url = ""; if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$this->config->storeDomainName; } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= $store->GetFullUrl($trySSL, $isMobile); } $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date)); } } } else { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$domainName; } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= "http://".$domainName; } $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date)); } } } } } Saturday, February 8, 14

Slide 51

Slide 51 text

{ $url = ""; if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$this->config->sto } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= $store->GetFullUrl($trySSL, $isMobile); } $url .= "/product_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->dat } } } else { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { Saturday, February 8, 14

Slide 52

Slide 52 text

$url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } } else { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$domainName; } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= "http://".$domainName; } $url .= "/product_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } } } } Saturday, February 8, 14

Slide 53

Slide 53 text

{ $url = ""; if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$this->config->sto } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= $store->GetFullUrl($trySSL, $isMobile); } $url .= "/product_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->dat } } } else { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { Saturday, February 8, 14

Slide 54

Slide 54 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; if ($includeDomain) { if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { $url .= $this->config->secureProtocol.$domainName; } else { $url .= "http://".$domainName; } } else { if ($this->featureToggle) { $url .= $this->config->secureProtocol.$this->config->store } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; Saturday, February 8, 14

Slide 55

Slide 55 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; if ($includeDomain) { if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { $url .= $this->config->secureProtocol.$domainName; } else { $url .= "http://".$domainName; } } else { if ($this->featureToggle) { $url .= $this->config->secureProtocol.$this->config->store } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; Saturday, February 8, 14

Slide 56

Slide 56 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { $url .= $protocol.$domainName; } else { $url .= "http://".$domainName; } } else { if ($this->featureToggle) { $url .= $protocol.$this->config->storeDomainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } if (!$store->isDefault()) { Saturday, February 8, 14

Slide 57

Slide 57 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if (!$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; } else { if ($this->featureToggle) { $url .= $protocol.$this->config->storeDomainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } Saturday, February 8, 14

Slide 58

Slide 58 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if (!$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; } else { if ($this->featureToggle) { $url .= $protocol.$this->config->storeDomainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } Saturday, February 8, 14

Slide 59

Slide 59 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault()) { if (!$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; } else { if ($this->featureToggle) { $url .= $protocol.$domainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } Saturday, February 8, 14

Slide 60

Slide 60 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault()) { if ($this->featureToggle) { $url .= $protocol.$domainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } Saturday, February 8, 14

Slide 61

Slide 61 text

$url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault()) { if ($this->featureToggle) { $url .= $protocol.$domainName; } else { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; Saturday, February 8, 14

Slide 62

Slide 62 text

$url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault()) { if (!$this->featureToggle) { $url .= $store->GetFullUrl($trySSL, $isMobile); } } } if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; if ($this->featureToggle) { Saturday, February 8, 14

Slide 63

Slide 63 text

$url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault() && !$this->featureToggle) { $trySSL = false; $url .= $store->GetFullUrl($trySSL, $isMobile); } } if (!$store->isDefault()) { if ($this->featureToggle) { $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } Saturday, February 8, 14

Slide 64

Slide 64 text

} if (!$store->isDefault()) { if ($this->featureToggle) { $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { $url .= "/product_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } } else { if ($this->featureToggle) { $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { $url .= "/product_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } } } } Saturday, February 8, 14

Slide 65

Slide 65 text

} if ($this->featureToggle) { if (!$store->isDefault()) { $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } } else { if (!$store->isDefault()) { $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } else { $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date) } } } } } Saturday, February 8, 14

Slide 66

Slide 66 text

} if ($this->featureToggle) { $url .= "/checkout?product_id=".$this->productId; } else { $url .= "/resort_detail.php?ProductId=".$this->productId; } if ($this->isDated) { $dateParam = $this->featureToggle ? "start_date" : "StartDate"; $url = "&{$dateParam}=" . date("Y-m-d", strtotime($this->date)); } } } Saturday, February 8, 14

Slide 67

Slide 67 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault() && !$this->featureToggle) { $trySSL = false; $url .= $store->GetFullUrl($trySSL, $isMobile); } } if ($this->featureToggle) { Saturday, February 8, 14

Slide 68

Slide 68 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->getDomainNameForStore($store); // snip } // snip } private function getDomainNameForStore($store) { $domainName = $this->config->storeDomainName; if ($store->isDefault()) { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } } } } Saturday, February 8, 14

Slide 69

Slide 69 text

whew Saturday, February 8, 14

Slide 70

Slide 70 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true) { $url = ""; if (!$store->isDefault()) { $trySSL = false; $forceToCore = false; if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$this->config->storeDomainName; } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= $store->GetFullUrl($trySSL, $isMobile); } $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date)); } } } else { $domainName = $this->config->domainName; if (!$domainName) { $domainName = $this->config->desktopDomainName; } if ($this->featureToggle) { if ($includeDomain) { $url .= $this->config->secureProtocol.$domainName; } $url .= "/checkout?product_id=".$this->productId; if ($this->isDated()) { $url .= "&date=".date("Y-m-d", strtotime($this->date)); } } else { if ($includeDomain) { $url .= "http://".$domainName; } $url .= "/resort_detail.php?ProductId=".$this->productId; if ($this->isDated()) { $url .= "&StartDate=".date("Y-m-d", strtotime($this->date)); } } } } } Saturday, February 8, 14

Slide 71

Slide 71 text

class Product { public function createUrl($store, $isMobile = false, $includeDomain = true) { $url = ""; $protocol = $this->config->secureProtocol; if ($includeDomain) { $domainName = $this->getDomainNameForStore($store); if ($store->isDefault() && !$this->featureToggle) { $protocol = "http://"; } $url .= $protocol.$domainName; if (!$store->isDefault() && !$this->featureToggle) { $trySSL = false; $url .= $store->GetFullUrl($trySSL, $isMobile); } } if ($this->featureToggle) { $url .= "/checkout?product_id=".$this->productId; } else { $url .= "/product_detail.php?ProductId=".$this->productId; } if ($this->isDated) { $dateParam = $this->featureToggle ? "start_date" : "StartDate"; $url = "&{$dateParam}=" . date("Y-m-d", strtotime($this->date)); } } private function getDomainNameForStore($store) Saturday, February 8, 14

Slide 72

Slide 72 text

recap Saturday, February 8, 14

Slide 73

Slide 73 text

recap Code should be understandable by humans. Saturday, February 8, 14

Slide 74

Slide 74 text

recap Code should be understandable by humans. Clean code is readable, cared for, efficient, extensible, and simple. Saturday, February 8, 14

Slide 75

Slide 75 text

recap Code should be understandable by humans. Clean code is readable, cared for, efficient, extensible, and simple. Write dirty code and successively refine. Saturday, February 8, 14