An Army of Service Classes
Yay! We got rid of a flat function. Woh - not so fast: inside battle()
,
we're calling a flat function: didJediDestroyShipUsingTheForce()
:
// ... 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
:
// ... 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:
// ... 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
:
// ... 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:
// ... 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
:
// ... 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()
:
require __DIR__.'/functions.php'; | |
$shipLoader = new ShipLoader(); | |
$ships = $shipLoader->getShips(); | |
// ... lines 6 - 119 |
Do the same thing in battle.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
:
require __DIR__.'/bootstrap.php'; | |
// ... lines 3 - 99 |
and index.php
:
require __DIR__.'/bootstrap.php'; | |
// ... lines 3 - 119 |
Refresh once more! Let's keep going.
Without including require_once __DIR__.'functions.php'; on top of lib/BattleManager.php file, how come the line 19 of lib/BattleManager.php file succeed to be executed ? As the didJediDestroyShipUsingTheForce() function was defined in functions.php ( before moving it to the BattleManager class ), wasn't it supposed to be needed to add require_once __DIR__.'functions.php'; on top of lib/BattleManager.php file ?