Old code, ugly code, complex code, spaghetti code, nonsense nonsense ...... is two words: legacy code. This is a series of articles that will help you deal with and resolve it. Refactoring legacy code (1): Gold Master Reconstruction legacy code (2): Magic strings and constant refactoring legacy code (3): a complex conditional statements legacy code refactoring (4): The first unit test refactoring legacy code (5): The game can test methods legacy code refactoring (6): Offence method of reconstructing complex legacy code (7): Identification Presentation layer legacy code refactoring (8): dependent on a neat reversal in architecture this tutorial, we will continue to focus on business logic. We will assess whether RunnerFunctions.php belongs to a class, and if so, which belongs to the class? We will consider the concerns and methods belong. Finally, we will learn the concept of simulation. So, what are you waiting? Continue reading it. RunnerFunctions - from process-oriented object-oriented code, even if most of us in the form of an object-oriented, well organized classes, but some features are defined in the file. We need to take some measures to give RunnerFunctions.php function more object-oriented way. const WRONG_ANSWER_ID = 7; const MIN_ANSWER_ID = 0; const MAX_ANSWER_ID = 9; function isCurrentAnswerCorrect ($ minAnswerId = MIN_ANSWER_ID, $ maxAnswerId = MAX_ANSWER_ID) {return rand ($ minAnswerId, $ maxAnswerId) = WRONG_ANSWER_ID;!} function run () {$ display = new CLIDisplay (); $ aGame = new Game ($ display); $ aGame- \u0026 gt; add (\u0026 quot; Chet \u0026 quot;); $ aGame- \u0026 gt; add (\u0026 quot; Pat \u0026 quot;); $ aGame- \u0026 gt; add (\u0026 quot ; Sue \u0026 quot;); do {$ dice = rand (0, Nike Free Run 3 5) + 1; $ aGame- \u0026 gt; roll ($ dice);} while (didSomebodyWin ($ aGame, isCurrentAnswerCorrect ()!));} function didSomebodyWin ($ aGame, $ isCurrentAnswerCorrect) {if ($ isCurrentAnswerCorrect) {return $ aGame- \u0026 gt;! wasCorrectlyAnswered ();} else {return $ aGame- \u0026 gt;! wrongAnswer ();}} My Air Max 2011 Womens Purple Grey first instinct is to put them in a class. This is nothing genius, but it is to make us start to modify the code. Let's look at this idea can really be achieved. const WRONG_ANSWER_ID = 7; const MIN_ANSWER_ID = 0; const MAX_ANSWER_ID = 9; class RunnerFunctions {function isCurrentAnswerCorrect ($ Air Max 2012 Black Navy Blue White minAnswerId = MIN_ANSWER_ID, $ maxAnswerId = MAX_ANSWER_ID) {return rand ($ minAnswerId, $ maxAnswerId) = WRONG_ANSWER_ID;!} function run () {// ... //} function didSomebodyWin ($ aGame, $ isCurrentAnswerCorrect) {// ... //}} If we do, we need to modify test procedures and GameRunner.php to use the new class. Let us be called generic class, when you need to rename it will be easy. We do not even know the existence of this class is to be independent or be integrated into the Game class. So also do not worry about naming. private function generateOutput ($ seed) {ob_start (); srand ($ seed); (new RunnerFunctions ()) - \u0026 gt; run (); $ output = ob_get_contents (); ob_end_clean (); return $ output;} In our GoldenMasterTest.php file, we have to modify the way the code is running. Function is generateOutput (), its third line needs to be modified to create a new object and calls the run (). But this test fails. PHP Fatal error: Call to undefined function didSomebodyWin () in ... Now we need to further modify the new class. do {$ dice = rand (0, 5) + 1; $ aGame- \u0026 gt; roll ($ dice);} (! $ this- \u0026 gt; didSomebodyWin ($ aGame, $ this- \u0026 gt; isCurrentAnswerCorrect ())) while; We only need to modify the run () while the expression conditions of the process. The new code from the current class by giving didSomebodyWin () and isCurrentAnswerCorrect () to prepare the $ this- \u0026 gt; to call them. This allows the gold medal by a master program, but it undermines the Runner test. PHP Fatal error: Call to undefined function isCurrentAnswerCorrect () in /.../RunnerFunctionsTest.php on line 25 issue assertAnswersAreCorrectFor () in, but first create a Runner objects very easy to solve. private function assertAnswersAreCorrectFor ($ correctAnserIDs) {$ runner = new RunnerFunctions (); foreach ($ correctAnserIDs as $ id) {$ this- \u0026 gt; assertTrue ($ runner- \u0026 gt; isCurrentAnswerCorrect ($ id, $ id));}} Also Problems also need to be deployed Air Jordan Heels in three other functions. function testItCanFindWrongAnswer () {$ runner = new RunnerFunctions (); $ this- \u0026 gt; assertFalse ($ runner- \u0026 gt; isCurrentAnswerCorrect (WRONG_ANSWER_ID, WRONG_ANSWER_ID));} function testItCanTellIfThereIsNoWinnerWhenACorrectAnswerIsProvided () {$ runner = new RunnerFunctions (); $ this- \u0026 gt; assertTrue ($ runner- \u0026 gt; didSomebodyWin ($ this- \u0026 gt; aFakeGame (), $ this- \u0026 gt; aCorrectAnswer ()));} function testItCanTellIfThereIsNoWinnerWhenAWrongAnswerIsProvided () {$ runner = new 586590-300 Nike Kobe 8 System Elite GC Poison Green Superhero Outlet RunnerFunctions (); $ this- \u0026 gt; assertFalse ($ runner- \u0026 597806-400 Nike LeBron X EXT QS Denim-Pink Outlet gt; didSomebodyWin ($ this- \u0026 gt; aFakeGame (), $ this- \u0026 gt; aWrongAnswer ()));} While this 579756 403 Purple White Nike Black Mamba 24 Kobe Sale makes the code was passed, but it introduces some code duplication. Because we now all have passed the test procedures can be extracted to create Runner setUp () method in the. private $ runner; function setUp () {$ this- \u0026 gt; runner = new Runner ();} function testItCanFindCorrectAnswer () {$ this- \u0026 gt; assertAnswersAreCorrectFor ($ this- \u0026 gt; getCorrectAnswerIDs ());} function testItCanFindWrongAnswer () { Air Jordan Outlet $ this- \u0026 gt; assertFalse ($ this- \u0026 gt; runner- \u0026 gt; isCurrentAnswerCorrect (WRONG_ANSWER_ID, WRONG_ANSWER_ID));} function testItCanTellIfThereIsNoWinnerWhenACorrectAnswerIsProvided () {$ this- \u0026 gt; assertTrue ($ this- \u0026 gt; runner- \u0026 gt; didSomebodyWin ($ this - \u0026 gt; aFakeGame (), $ this- \u0026 gt; aCorrectAnswer ()));} function testItCanTellIfThereIsNoWinnerWhenAWrongAnswerIsProvided () {$ this- \u0026 gt; assertFalse ($ this- \u0026 gt; runner- \u0026 gt; didSomebodyWin ($ this- \u0026 gt; aFakeGame () , $ this- \u0026 gt; aWrongAnswer ()));} private function assertAnswersAreCorrectFor ($ correctAnserIDs) {foreach ($ correctAnserIDs as $ id) {$ this- \u0026 gt; assertTrue ($ this- \u0026 gt; runner- \u0026 gt; isCurrentAnswerCorrect ($ id , $ id));}} Nicely done. All these new creation and reconstruction got me thinking. We named variables runner. Maybe we can also named in a class with Nike Lebron 11 Elite the same name. Let us reconstruct it. It should be easy. If you do not check the box above 'Search for text occurrences', do not forget to include you manually modify the scope, because reconstruction will also rename the file. Now we have a file named GameRunner.php, another named Runner.php, there is New Nike Free 5.0 V4 Grey Lime Trainers a third named Game.php. I do not know how you like, but it seemed to me very confused. If this is the first time in my life to see these three documents, which I do not know what is doing. We need to remove at least one of them. In the early stages of our remodeling, create RunnerFunctions.php reason is to construct a test method and include all files. We need to enter any code, but does not run all of the code, unless prepared in the gold medal in the masters program environment. We can still do the same thing, just do not run from Nike Air Max GameRunner.php code. Before we continue, we need to update and create a new class that contains the code. . require_once __DIR__ '/Display.php';require_once __DIR__.' /Runner.php';(new Runner ()) - \u0026 gt; run (); this will do. We need to explicitly include Display.php, so that when attempting to create a new CLIDisplay Runner when it will know what to achieve. Analysis of attention I think that object-oriented programming is the most important characteristic analysis concern. I often ask myself the question is, 'This class made its name expression mean?', 'This method is concerned that this object?' 'I should be concerned about the specific value of the object it?.' Surprisingly, these types of problems has a huge role in clarifying the business domain and software architecture. In Syneto, we quiz these types of problems in the group. Many times when a developer has trouble, he or she just stood up and requested two minutes of attention from the team to understand our views for a subject. Those familiar with the architecture of the code from a software point of view one would answer, while others are more familiar with some of the business areas of business may reveal some important insights. Let's try to consider our case concern. We can continue to focus on Runner 586590-300 Nike Kobe 8 System Elite GC Poison Green Superhero Outlet class. Compared to Game class that is very likely to eliminate or reform. First, Runner should care isCurrentAnswerCorrect () how works? Runner should have any knowledge about the question and answer it? This method seems to be better to eliminate points from Game class. I strongly believe that the questions and answers about the Game class should be concerned about right or wrong answers. I really believe that Game class must provide answers concern the results for the current problem. It is time for action. We will do to move the reconstruction method. As is apparent from my previous tutorial we have seen, I will only give you see the final result. require_once __DIR__. '/CLIDisplay.php';include_once __DIR__.' /Game.php';class Runner {function run () {//...//} function didSomebodyWin ($ aGame, $ isCurrentAnswerCorrect) {// .. }} .// important to note not only the method did not, and to define the limits of the constant answer was gone too. But didSomebodyWin () how? Runner decide when someone should 585388-083 Anti-Nerf Nike KD V Elite Outlet win it? If we look at the method body, we can see a problem as prominent as the night the flashlight. function didSomebodyWin ($ aGame, $ isCurrentAnswerCorrect) {if ($ isCurrentAnswerCorrect) {return $ aGame- \u0026 gt;! wasCorrectlyAnswered ();} else {return $ aGame- \u0026 gt;! wrongAnswer ();}} Whether this method did, it only acts on the Game class object. It is verified from Game Returns the current answer. Whether it returns after a game object value in its wasCorrectlyAnswered () or wrongAnswer () method returns. This method is effective not do anything. It concerns all the Game class. This is a classic example of the code, called Attachment Hunger. A class made another class should do. It is time to move it. class RunnerFunctionsTest extends PHPUnit_Framework_TestCase {private $ runner; function setUp () {$ this- \u0026 gt; runner = new Runner ();}} As usual, we first mobile testing program. Test-driven development? anyone? This gives us no more tests can be run, so that the file can now be removed. Delete programming in my favorite part. When we run the test program, we get a very nice error: Fatal error: Call to undefined method Game :: didSomebodyWin () it is time to modify the code. The way to copy and paste into the Game class will magically get all the test. Including the old method and moved GameTest class. But the method in the right place at the same time brings two problems: Runner also need to change, we pass fake Game Game objects because it is part of the class and do not need to do anything. do {$ dice = rand (0, 5) + 1; $ aGame- \u0026 gt; roll ($ dice);} (! $ aGame- \u0026 gt; didSomebodyWin ($ aGame, $ this- \u0026 gt; isCurrentAnswerCorrect ())) while; Runner is a very simple amendment. We just $ this- \u0026 gt; didSomebodyWin (...) is amended as $ aGame- \u0026 gt; didSomebodyWin (...). After our next step, we will be back here again and modify it, test remodeling. function testItCanTellIfThereIsNoWinnerWhenACorrectAnswerIsProvided () {$ aGame = Mockery :: mock ('Game [wasCorrectlyAnswered]'); $ aGame- \u0026 gt; shouldReceive ('wasCorrectlyAnswered') - \u0026 gt; once () - \u0026 gt; andReturn (false); $ this- \u0026 gt ; assertTrue ($ aGame- \u0026 gt; didSomebodyWin ($ this- \u0026 gt; aCorrectAnswer ()));} is the time to do some simulated! Instead of using the test procedures defined in our last fake class, we will use Mockery. It allows us to simply get overwritten Game in, and I hope it is called and the return value we want. Of course, we can inherit the Game class through a fake class and rewrite our own way to do this. However, tools exist, why Nike Dunk Heels do such work? function testItCanTellIfThereIsNoWinnerWhenAWrongAnswerIsProvided () {$ aGame = Mockery :: mock ('Game [wrongAnswer]'); $ aGame- \u0026 gt; shouldReceive ('wrongAnswer') - \u0026 gt; once () - \u0026 gt; andReturn (true); $ this- \u0026 gt ; assertFalse ($ aGame- \u0026 gt; didSomebodyWin ($ this- \u0026 gt; aWrongAnswer ()));} After we rewrite the second method, we can get rid of the fake Game class and its methods of any initialization. Solve the problem! Final Thoughts Even if we can think of only Runner, but today we have made great progress. We learn the responsibilities, we define methods and variables belonging to another class. We think at a higher level and we move towards a better solution. In Syneto team, there is a strong belief that there is a way to write the code, and unless at least make the code a little clearer, or never commit changes. This is after a period of time, can bring better code base, with less correlation, more 2015 Nike Free 5.0 tests and eventually fewer errors technology. Thanks, take your time.refactoring legacy code (9): Analysis of Concerns