Buy

Yay! We got rid of a flat function. Woh - not so fast: inside battle(), we're calling a flat function: didJediDestroyShipUsingTheForce():

59 lines lib/BattleManager.php
... lines 1 - 2
class BattleManager
{
... lines 5 - 9
public function battle(Ship $ship1, $ship1Quantity, Ship $ship2, $ship2Quantity)
{
... lines 12 - 18
if (didJediDestroyShipUsingTheForce($ship1)) {
... lines 20 - 23
}
... lines 25 - 56
}
}

No bueno!

Refactoring to private Functions

This lives at the bottom of functions.php. In our app, this is only called from inside battle(), and since it obviously relates to battles, let's move it into BattleManager. Make it a private function:

66 lines lib/BattleManager.php
... lines 1 - 2
class BattleManager
{
... lines 5 - 58
private function didJediDestroyShipUsingTheForce(Ship $ship)
{
$jediHeroProbability = $ship->getJediFactor() / 100;
return mt_rand(1, 100) <= ($jediHeroProbability*100);
}
}

Why did I make it private? Well, do we need use this function from outside of this class? No - the only code using it is up in battle(), so this is a perfect candidate to be private.

Above in battle(), update the calls to be $this->didJediDestroyShipUsingTheForce(). The "force" of our app is happy again:

66 lines lib/BattleManager.php
... lines 1 - 2
class BattleManager
{
... lines 5 - 9
public function battle(Ship $ship1, $ship1Quantity, Ship $ship2, $ship2Quantity)
{
... lines 12 - 18
if ($this->didJediDestroyShipUsingTheForce($ship1)) {
... lines 20 - 23
}
if ($this->didJediDestroyShipUsingTheForce($ship2)) {
... lines 26 - 29
}
... lines 31 - 56
}
... lines 58 - 64
}

Now, if someday we did want to use this function from outside of BattleManager, then we could change it to public. Ok, so why not just make everything public - isn't that more flexible? Yes, but making this private is nice: it means that if I want to change this function - add arguments or even change what it returns - I know that the only code that will be affected will be right inside this class. If it's public, who knows what code I might break in my app?

Start with private, make it public only if you need. The same rule goes for protected - something we'll talk about later with inheritance.

Let's make sure we didn't bust things. Refresh!

Yes!

Service 2: ShipLoader

In functions.php, only the flat get_ships() function remains. You guys know what do to: move it into a class!

Should we move it into BattleManager? No - it doesn't relate to battles. Instead, create a new class for this - how about ShipLoader:

37 lines lib/ShipLoader.php
... lines 1 - 2
class ShipLoader
{
... lines 5 - 36
}

Let's work our magic: go grab get_ships() and move it into ShipLoader. Remove the old commented code and make the function public. Also, rename it from get_ships() to getShips() - that's a more common naming standard for methods in a class:

37 lines lib/ShipLoader.php
... lines 1 - 2
class ShipLoader
{
public function getShips()
{
$ships = array();
$ship = new Ship('Jedi Starfighter');
... lines 10 - 33
return $ships;
}
}

Yep, that's great! Now we need to update the code that calls this function. But first, open functions.php and require the new ShipLoader.php:

6 lines functions.php
... lines 1 - 4
require_once __DIR__.'/lib/ShipLoader.php';

getShips() is used in battle.php and index.php - start there. To call the method, create a $shipLoader variable and create a new ShipLoader() object. Now, just $shipLoader->getShips():

119 lines index.php
<?php
require __DIR__.'/functions.php';
$shipLoader = new ShipLoader();
$ships = $shipLoader->getShips();
... lines 6 - 119

Do the same thing in battle.php:

99 lines battle.php
<?php
require __DIR__.'/functions.php';
$shipLoader = new ShipLoader();
$ships = $shipLoader->getShips();
... lines 6 - 99

I think it's time to try it. Click to create a new battle. Looks pretty good. Setup a new battle and, Engage. Ok! battle.php works too!

No More functions.php

AND, all the flat functions are gone! Object-orient all the things! So if you look in functions.php, well, there aren't any functions here: just require statements, and even those we'll get rid of eventually. To celebrate, give this a more appropriate name: bootstrap.php. Update this in battle.php:

99 lines battle.php
<?php
require __DIR__.'/bootstrap.php';
... lines 3 - 99

and index.php:

119 lines index.php
<?php
require __DIR__.'/bootstrap.php';
... lines 3 - 119

Refresh once more! Let's keep going.

Leave a comment!

  • 2015-12-14 weaverryan

    Good tip! I didn't show that here because I want them to understand what changes and why. But in real life, I absolutely use this :).