Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already...

85

Transcript of Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already...

Page 1: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

Refactoring-Analys and OO project refactoring

Björn Ekström [email protected]

Magnus Holmberg [email protected]

2nd June 2006

Page 2: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

Abstract

In this report it will be shown how, when and why you should refactor your code.

Refactoring is when you rewrite your code in a more understandable and readable

way without changing its external behavior. There are many di�erent patterns to

follow when you start with your refactoring, these are used to make your refactoring

safe so you don�t change the behavior of your code in the process. To �nd what

to refactor you can �smell� the code which is a way to �nd places where the code

can be refactored. When you found these smells you have di�erent methods to solve

them. Many of these patterns and methods are explained in the report and the other

methods used are referenced. It may not always be a good idea to refactor, you have

to calculate the risks and the time consumed against the bene�ts. Although in big

projects where many people are involved you almost always save time and money

when you refactor. This is because of easier maintenance and less time spent on

�xing bugs and errors. This report also contains a big example of a project being

refactored. In that example it will be shown how and what refactorings were made.

In the end some conclusions are made regarding refactoring.

Page 3: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

Contents

1 Introduction 4

2 What is refactoring? 42.1 Refactoring without knowing . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3 How to refactor? 43.1 Refactoring methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3.1.1 Rename Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.1.2 Split Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.1.3 Replace Temp with Query . . . . . . . . . . . . . . . . . . . . . . . 63.1.4 Pull up �eld/method . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3.2 Refactoring patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.1 Refactoring In Very Small Steps . . . . . . . . . . . . . . . . . . . . 83.2.2 Backtrack If Refactoring Fails . . . . . . . . . . . . . . . . . . . . . 83.2.3 The First Refactoring Step . . . . . . . . . . . . . . . . . . . . . . . 83.2.4 Test Every Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.5 Refactoring In Duets . . . . . . . . . . . . . . . . . . . . . . . . . . 93.2.6 Refactoring Using Tools . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Why and when to refactor? 94.1 Code smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4.1.1 Duplicate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104.1.2 Switch Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 104.1.3 Long Parameter List . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4.2 Economics of refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114.3 Bene�ts and drawbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

5 Risks with refactoring 12

6 Design patterns in�uence on refactoring 12

7 Refactoring of a OO project 137.1 Explanation of the project . . . . . . . . . . . . . . . . . . . . . . . . . . . 137.2 Structure of the project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147.3 Refactoring of the project . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

7.3.1 Rename method/variables . . . . . . . . . . . . . . . . . . . . . . . 147.3.2 Extract method, Pull up method . . . . . . . . . . . . . . . . . . . 157.3.3 Remove unnecessary methods . . . . . . . . . . . . . . . . . . . . . 157.3.4 Replace temp with query, Replace parameter with method . . . . . 167.3.5 Collapse Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

7.4 Testing behavior of the refactored project . . . . . . . . . . . . . . . . . . . 16

2

Page 4: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

8 Conclusions 17

A Code of the OO project before the refactoring 19A.1 Minermain.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19A.2 Diamant.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19A.3 Dorr.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20A.4 Figure.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21A.5 Figurelist.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25A.6 Kloss.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31A.7 Meny.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32A.8 Minerapp.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33A.9 Monster.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42A.10 Nyckel.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44A.11 Ondtulpan.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45A.12 Pausemeny.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46A.13 Player.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47A.14 Scorepanel.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48A.15 Stormonster.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50A.16 Storondtulpan.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

B Code of the OO project after the refactoring 54B.1 Minermain.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54B.2 Diamant.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54B.3 Dorr.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55B.4 Figure.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56B.5 Figurelist.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61B.6 Kloss.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66B.7 Minerapp.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67B.8 Monster.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75B.9 Nyckel.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77B.10 Ondtulpan.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78B.11 Player.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79B.12 Scorepanel.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80B.13 Stormonster.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82B.14 Storondtulpan.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

3

Page 5: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

1 Introduction

Refactoring is when you rework your code in a more understandable way. The code willthen be much more easy to read and that leads to easier maintenance. The goal with thisreport is to show how to refactor and give example of di�erent strategies and methods.These strategies and methods will be used to make a full refactoring of an object orientedproject and from that bene�ts and drawbacks of refactoring will be discussed.

2 What is refactoring?

Di�erent kinds of refactoring is done many times in our ordinary life, for example writing anessay is never done in one step, you always read it through and change small things to makeit more readable. In ordinary language we often call this reorganization. Another parallelis to the mathematic word factoring where you split up a complex expression to a moresimple readable expression, for example you can factorize (x2 − 4) into (x− 2) (x + 2). Theterm refactoring is used when you work with software engineering. [WIKWIR]

Refactoring is a way to clean up and improve the internal structure of already workingcode without changing its external behavior. Its a technique of improving the design andin that way hopefully make maintenance easier and more e�cient. When refactoring isdone you never rewrite the entire code, you just change one thing at the time to get a moreunderstandable and readable code. If you would rewrite the code its a good chance thatyou could change the functionality of the program and that is not the goal of refactoring.Although when you start to refactor you almost always �nd things to improve along theway. Therefore you should always refactor �rst and then make the improvements you foundwhen refactoring. If you start to make the improvements at the same time as refactoring itsa risk that you get unwanted behavior from the program due to unforeseen consequences.

One small example is to change variables to explaining names, if you have a variable'num' it does not say much what its used for, instead call it 'NumberOfApples'. In this wayeveryone knows what the variables are used for even after a few years.[REFMF][WIKIPREF]

2.1 Refactoring without knowing

When you are programming you often refactor without knowing. You are making yourcode more easy to understand for your own sake so you can modify and understand itlater. Many of the things you do without knowing are methods that will be explainedbelow.

3 How to refactor?

There are di�erent ways of refactoring but you basically go through the code line by lineand see what you can do to make it easier to read. When you do it you should rememberto take as small steps as possible to avoid coming to a state where the code does not

4

Page 6: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

work and its to complex to go back to how it was. And always when you have done yourrefactorings, you should compile and test so it still works as before. To help you with thisthere are a lot of di�erent methods and patterns that will be presented below.

3.1 Refactoring methods

The methods below are recognized by known programmers within this �eld. These are justfew of all existing and are presented here to get you a better view and understanding ofwhat refactoring methods is.

3.1.1 Rename Method

It is important that you have good names on your methods. If the naming is done badlyit is hard to tell what the method does. Methods should be named in such way so its easyto know what they are doing just by looking at their name. A good way to do this is to letthe name of the method describe the method shortly. It may not be as easy as it seems todescribe complex methods in just a few short words, but by improving this skill you are astep closer to being a skillful programmer.

If there is a method which gets the total amount of a customers account balance.

public int accbalance()

{

return(account1 + account2 + account3);

}

You want to change the name to getTotalAccountBalance. First make a copy of the oldmethod and then change the name of the copy. Then you change so that the old copy callsthe new one.

public int accbalance()

{

return getTotalAccountBalance();

}

public int getTotalAccountBalance()

{

return(account1 + account2 + account3);

}

Test it and if it works you can now �nd the callers of the method, change them so thatthey call the new method and then remove the old one. [REFMF], page 221.

5

Page 7: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

3.1.2 Split Loop

Splitting loops are done when you have one loop doing more than one thing. Doing morethan one thing at the time in a loop makes it less clear. Splitting them up makes it easierfor further refactoring of your program. Many programmers would say that this makesthe program not as fast because the loop have to execute twice or more. But don�t beso sure, because its not that often that loops are the bottleneck. For example the cachehitratio can become better if you split them up. If it in a later state shows that the loopsare slowing it down its just to slam them back together again. [WIKSL]

Lets say we have a loop that does two thing at the same time.

for (int i = 0; i < length; i++)

{

averageAge += age[i];

totalSalary += salary[i];

}

Splitting them up like below makes it clearer.

for (int i = 0; i < length; i++)

{

totalSalary += salary[i];

}

for (int i = 0; i < length; i++)

{

averageAge += age[i];

}

3.1.3 Replace Temp with Query

Using temporary variables are not such a good idea because they are temporary and canonly be accessed localy. They also make the methods longer. To �x this problem we wantto put temporary variables in query methods, this will let any method to access the infor-mation and it helps to get cleaner code. [REFMF], page 97.

Lets say we have some temporary variables:

double CirclePerimeter = 3.14159265 * radie;

double RectanglePerimeter = Side1*2 + side2*2;

if (CirclePerimeter > RectanglePerimeter)

return Perimeter;

else

return Rectangle;

6

Page 8: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

Instedad of temporary variables, put them in query methods:

if (CirclePerimeter() > RectanglePerimeter())

return CirclePerimeter();

else

return RectanglePerimeter();

...

double CirclePerimeter()

{

return 3.14159265 * radie;

}

double RectanglePerimeter()

{

return Side1*2 + side2*2;

}

3.1.4 Pull up �eld/method

If you have the same variable in all of your subclasses you should pull it up to the superclassto make it easier to see that all subclasses uses the same variable. The variable doesn`talways have the same name in all subclasses as you can see in Figure 1 below, so you haveto look for how the variable is used. If it is used in a similar way you can pull it up tothe superclass. This refactoring can be done in exactly the same way with a method (Pullup method). If two methods are doing the same thing in all subclasses, pull it up to thesuperclass. [REFMF], page 259, 260.

Figure 1: Pull up �eld

7

Page 9: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

3.2 Refactoring patterns

There are di�erent patterns you can follow when you refactor your code. They can seemvery simple and obvious but its very good to have them in mind when you refactor.

3.2.1 Refactoring In Very Small Steps

Often when you have done a large refactoring you come to a place where the code does notwork and you have changed too much to be able to change it back. This problem is whatthis pattern tries to solve. The solution is to refactor in very small steps as the name ofthe pattern says. Then if you come to a place where the code does not work you have agood chance of �nding the problem since the search area is very small. This pattern is verygood to combine with �Test every Refactoring� that will be shown below. [WIKRIVSS]

3.2.2 Backtrack If Refactoring Fails

Sometimes the refactoring you do fails and you end up with non working code which youcant �nd the error in. This can be despite that you used the pattern �Refactoring In VerySmall Steps�. This pattern is used when you want an easy way to go back to when thecode worked. The solution to this problem is to make backup copies of your code beforeyou start to refactor. When you have applied your refactoring and its working you makea new backup to replace the old one. If it doesn�t work you use your backup copy to getback to previous state. [WIKBIRF]

3.2.3 The First Refactoring Step

When are you ready to start refactoring? You should �rst make sure you have coveredall test cases in your program. If you have done that you can easily make sure that yourrefactoring didn�t change the behavior of the code. Use this with �Backtrack If RefactoringFails� and you will have a good chance of making your refactoring without any biggerproblem. Then along the way when you refactor its also good to use �Refactoring In VerySmall Steps� and �Test Every Refactoring� (explained below). [WIKTFRS]

3.2.4 Test Every Refactoring

To avoid �nding errors in the code at a too late state in your refactoring you should usethis pattern. As the name of the pattern says you should test every refactoring you make,even the small ones. If you don�t, you risk to miss some errors that could cause seriousdamage to your program at a later state. Its good to use this pattern with �The FirstRefactoring Step� to make sure you covered all the test cases. As usual when you do therefactoring its a good idea to have �Refactoring In Very Small Steps� and �Backtrack IfRefactoring Fails� in mind. [WIKTER]

8

Page 10: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

3.2.5 Refactoring In Duets

How do you do to make as little errors as possible? People always see things in di�erentways, therefore when you are able to, refactor with someone more then yourself. Its a goodchance that he sees the things you miss and vice versa. [WIKRID]

3.2.6 Refactoring Using Tools

When you refactor you often introduce some bug that you will discover when you use �TestEvery Refactoring�. Then you have to �x it or if you use �Backtrack If Refactoring Fails�maybe go back to your backup copy and redo the refactoring. This takes time and the bestthing would be if the error never occurred, but since we are humans, mistakes are made.To reduce the mistakes made you can use refactoring tools, they can make many changesand checks, very fast and safe. [WIKRUT]

4 Why and when to refactor?

When you are making dinner, the fastest way to get it done is to leave the dishes to thenext day and not clean after yourself. The next day the fastest way to make dinner is stillto not clean the kitchen. And this will be true for every day you make dinner. Howeverif you look at the time spent making dinner over a year it would take a lot less time ifyou had clean the kitchen after every dinner. Example from [WIKCTK]. This is why youcan earn a lot of time if you refactor your code. When you don�t refactor your code thedesign of it will decay. People who does changes or updates to the code does not take fullcomprehension of it. So after time the code will lose its design and structure. Refactoringwill make it retain the design and structure. The worse the design is the harder it is topreserve it. So its preferable to do regular refactoring. More code also makes it harderto understand. Refactoring helps to reduce the amount of code and in that way it makesit much easier to do modi�cations correctly. It also makes you to see things more clearly.[REFMF]

�As the code gets clearer, I �nd I can see things about the design that Icould not see before. Had I not changed the code, I probably never would haveseen these things, because I'm just not clever enough to visualize all this in myhead. Ralph Johnson describes these early refactorings as wiping the dirt o� awindow so you can see beyond.� Martin Fowler, [REFMF], page 48.

Although its not always a good idea to refactor, if you know for sure that the code isworking and that no one ever will have a reason to change it its better to save some timeand leave it as it is. Then you can also avoid the risk of introducing bugs without knowing.You should never refactor for refactoring sake.

9

Page 11: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

4.1 Code smells

�If it stinks, change it.� Grandma Beck, discussing child-rearing philosophy.

Code smells is when you have an idea that something might be wrong with the code, butit's not necessary that it is. When you feel that the code smells bad it can be a goodidea to take a closer look at it. To �nd these code smells there are di�erent guidelines andmethods, some of them will be explained below. The methods can be an idea of what youshould refactor. Many code smells are easy to �nd, even unexperienced programmers can�nd them but not always correct them. Finding codes smells is a good way to become abetter programmer. A good essay in the subject is written by Martin Fowler and KentBeck named Bad Smells in Code, published in Fowlers book Refactoring: Improving theDesign of Existing Code. [MFCS][REFMF][WIKIPCS]

4.1.1 Duplicate Code

Duplicate code is nothing that your want. It is unnecessary to have the same code indi�erent places. The goal is to eliminate duplicate code because its better to merge themtogether. Code is best when its kept simple and short. It's not always as simple as itsounds because code that does the same thing not always looks the same. [REFMF], page63

Methods which can solve the bad smell:Extract MethodPull up FieldForm TemplateSubstitute Algorithm

4.1.2 Switch Statements

Switch statements is in some languages acceptable but should be avoided in object-orientedprogramming. This is because same switch statements are often found in di�erent placesof the code and from DUPLICATE CODE we know that its nothing that we want. Whenswitch statements are scattered in the code its hard to do changes because you have to�nd each one of the switch statement and do the same changes to all of them. If there arejust a few cases where you don�t expect them to change, its not needed to solve this smell.[SOBCS][FOOCS][REFMF], page 68

Methods which can solve the bad smell:Extract MethodMove MethodReplace Type Code with SubclassesReplace Type Code with State/StrategyReplace Conditional with Polymorphism

10

Page 12: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

4.1.3 Long Parameter List

Passing everything in to routines by using long parameters is not good because they are dif-�cult to use and hard to understand. This is not needed when you programming in object-orientated languages instead you can ask other objects to get the information for you. Thisway is much better because you don�t always need the data which have been passed tothe routine but when you do need it, its only to make some requests. [AWPCS][REFMF],page 65

Methods which can solve the bad smell:Replace Parameter with MethodPreserve Whole ObjectIntroduce Parameter Object

4.2 Economics of refactoring

First of all it cost to make the actual changing of the code, renaming variables etc. Thenyou have to test all the changes and see that your program has not changed behavior. Acost also to consider is if you without knowing introduced a bug in the program that thetests misses. The cost could then be severe. In the end it also cost to update eventualdocumentation. Despite of all these costs you can save money if you do refactoring becausenext time you would update or add some features to your program it will go a lot faster,especially if someone else then yourself is going to make changes in your code. If you savemoney or not on refactoring will have to be decided from case to case. It depends on howmuch time you use to make the refactoring and how much time you would save if you leftthe code as it was rather than refactor it. Another to consider when you choose whetherto refactor or not is the risk of an unknown bug that could be very expensive in the end. Ifyou are making a big project or a project with many people involved the rule is to alwaysrefactor. In almost all of these cases the time of refactoring is much smaller then the timesaved. [WIKEOR]

4.3 Bene�ts and drawbacks

Below will be shown a list of bene�ts and drawbacks with refactoring.

Bene�ts

• Easier to understand refactored code

• Easier maintenance

• Easier to add new features

• Easier to �nd bugs

11

Page 13: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

• Easier to reuse refactored code

• Can make the program execute faster

• All above helps you develop code faster

Drawbacks

• Takes time

• Can introduce bugs

• Can make the program execute slower

Then in each case you have to look at the bene�ts and drawbacks and decide if its worthto refactor or not.

5 Risks with refactoring

There are many reasons to why you should refactor but every time you refactor you takea risk of adding errors in a already working program. To reduce the probability of addingerrors you should follow the patterns and methods presented above and always refactorsmall pieces of code at a time.

�By de�nition, you only refactor code that is already working, which whereI come from is scary. Working code is a valuable asset since it is hard to getright (...) and takes time. Touching working code is always a risk and so thereshould be a darned good reason for doing it.� Robert X. Cringely, [PBSRWR]

Another kind of risk with refactoring is that the execution of the program can be slowersince you sometimes divide up things etc. The code might be easier to understand andmaintain but when you actually are running the code it could be slower.

A third kind of risk with refactoring is to spend unnecessary time with it. Sincerefactoring can be pretty time-consuming you should make sure you don�t do it in caseswhere its not needed.

6 Design patterns in�uence on refactoring

A design pattern is a pattern you follow when you start programming. There are manydi�erent design patterns and they are all solving some known problems in a good andwell tested way. When you use a design pattern and are implementing your program italmost always gets a good structure. A good structure leads to easy refactoring or even sothat some of the refactoring already gets done when you are programming. There are alsoexamples where a design pattern have been detected after the refactoring have been done.There are not much research made in this area but design patterns and refactoring seemswell connected. Maybe to implement a design pattern is a way to refactor before you startcoding? [XPEDP]

12

Page 14: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

7 Refactoring of a OO project

7.1 Explanation of the project

This project were developed in October 2004 during a course in object oriented program-ming in c++ at Mälardalens Högskola. It is called �Bosse Miner� and is a simple platformgame where you control a �miner� through three di�erent levels. To complete each levelyou should avoid the evil tulips, monsters and at the same time get the key for the exitdoor. When you have the key you have to make your way to the exit door and then thenext level will start. During the game you can also pick up diamonds to get extra scorepoints. Figure 2 below shows the game in runtime.

Figure 2: BosseMiner

13

Page 15: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

7.2 Structure of the project

There is one superclass in the structure of this project called �Figure� and 12 classes thatinherit from �Figure� called �Diamant�, �Dorr�, �Kloss�, �Meny�, �Monster�, �Nyckel�, �Ond-tulpan�, Pausemeny�, �Player�, �Scorepanel�, �Storondtulpan�, �Storondmonster�. There isalso a class called �Figurelist� that have a list of �Figures� in its internal structure. LikeFigure 3 below shows.

Figure 3: StructureOOP

7.3 Refactoring of the project

In this section it will be explained which refactorings have been done on the project. Itwill be shown why and how the changes were made and what methods that were used. Tosee the the whole project code before the refactoring see appendix A and to see the codeafter the refactoring see appendix B. When the refactoring was made the above explainedpatterns �Refactoring In Very Small Steps�, �Backtrack If Refactoring Fails�, �The FirstRefactoring Step�, �Test Every Refactoring� and �Refactoring In Duets� were used as muchas possible.

7.3.1 Rename method/variables

The project was looked through page by page and all variables and method names thatwere unclear were changed. Two typical examples of what were changed is shown below.The rest of the changes that were made are shown in the appendix.

One variable were called �lista� which means list in Swedish. But what does the listconsist of? We choose to rename the variable �lista� to �ListOfFigures� since that is whatit consists of.

14

Page 16: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

�getspinfo� were the name of one method that were used to get information from ascore panel. We changed the method name to �getScorePanelInfo� which give us an directexplanation of what is does without having to check inside the method. See 3.1.1 for moreinformation of the rename method.

7.3.2 Extract method, Pull up method

When looking through the code a bad smell called duplicate code were found, in severalclasses the method load contained parts of exact same code as you can see in Figure 4. Tosolve this smell �Extract method� and �Pull up method� were used. The parts of the codethat were the same in di�erent classes were moved to a own method and pulled up to thesuperclass �Figure�.

Figure 4: Duplicate code

Another case of duplicate code were found in four di�erent places in �Figurelist�. Thecode parts were all extracted to a separate method. The same smell were found in �min-erapp.h� were some code also were extracted to methods instead. 3.1.4 describes the �Pullup method�, 4.1.1 �duplicate code� and [REFMF], page 89 �Extract method�.

7.3.3 Remove unnecessary methods

Two di�erent methods were found in the project that never were used so they simply weredeleted. One unnecessary constructor in the class �Figure� were also found and deleted.

15

Page 17: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

7.3.4 Replace temp with query, Replace parameter with method

Some temporary variables were found in the code that easily could be replaced by queriesinstead. When doing this a bad smell of �Long parameter list� were also found. To solvethis smell the method with the long parameter list were divided in to three smaller methodslike Figure 5 below.

Figure 5: Long Parameter List

These three small methods were also used to replace the temp variables. All temporaryvariables could not be removed but the smell were narrowed down a lot. See 3.1.3 for moreinfo about �Replace temp with query�, [REFMF], page 235 for �Replace parameter withmethod� and for �Long parameter list� see [REFMF], page 65.

7.3.5 Collapse Hierarchy

Two bad smells of �Lazy class� were found in the project, it was the two menus used inthe game �Meny� and �Pausemeny�. The only thing those two classes were doing was toprovide a constructor to create the menus. These two classes were removed with �CollapseHierarchy� and instead one extra constructor was made in the Figure class. [REFMF],page 68 describes �Lazy class� and [REFMF], page 279 �Collapse Hierarchy�.

7.4 Testing behavior of the refactored project

During the refactoring of the project test were made many times like �Test every refactor-ing� says. A big test in the end were also performed where all di�erent situations weretested to make sure that there hadn't been any changes in the behavior of �Bosse miner�.

16

Page 18: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

8 Conclusions

Writing this essay on refactoring we learned that how you write code is an whole scienceand far more important than we could imagine. There is so much you have to think aboutin how to make the code understandable, not just for yourself but also for others. As it isright now people write code in many di�erent ways and often this leads to that others canhave di�culties to understand the code. When refactoring is made your code will have achance to be useful and improved by others. When we now have learned about refactoringwe know it is a very important part of programming. Despite if you follow the refactoringsteps or not you should have in mind that others one day may need to change and improveyour code. Refactoring is time consuming but in the end it often saves you a lot of time.

Refactoring our project was not so easy because of our inexperience in this area. Firstwe did not know where and how to start but after a while we got a grip of the situation.When going through the code we found di�erent smells and to every smell we had a numberof methods in how to solve the smell. Despite that the project were not so big we foundquite large refactorings that were made, for example we removed two whole classes. Inthe end we think refactoring made this project more understandable for others. It is hardto know if it is worth the time spent on refactoring on this particular project but in thefuture we will for sure use refactoring when programming.

17

Page 19: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

References

[REFMF] http://mirrors.cn99.com/books/Refactoring.pdf Refactoring, improving the de-

sign of existing code by Martin Fowler

[WIKWIR] http://c2.com/cgi/wiki?WhatIsRefactoring

[WIKIPREF] http://en.wikipedia.org/wiki/Refactoring

[WIKSL] http://www.refactoring.com/catalog/splitLoop.html

[WIKRIVSS] http://c2.com/cgi/wiki?RefactoringInVerySmallSteps

[WIKBIRF] http://c2.com/cgi/wiki?BacktrackIfRefactoringFails

[WIKTFRS] http://c2.com/cgi/wiki?TheFirstRefactoringStep

[WIKTER] http://c2.com/cgi/wiki?TestEveryRefactoring

[WIKRID] http://c2.com/cgi/wiki?RefactoringInDuets

[WIKRUT] http://c2.com/cgi/wiki?RefactoringUsingTools

[WIKCTK] Robert Martin and Je� Grigg, http://c2.com/cgi/wiki?CleanTheKitchen

[MFCS] http://www.martinfowler.com/bliki/CodeSmell.html

[WIKIPCS] http://en.wikipedia.org/wiki/Code_smell

[SOBCS] http://www.soberit.hut.�/mmantyla/BadCodeSmellsTaxonomy.htm

[FOOCS] http://foozle.berkeley.edu/projects/streek/agile/bad-smells-in-code.html

[AWPCS] http://www.awprofessional.com/articles/article.asp?p=102271&seqNum=5

[WIKEOR] http://c2.com/cgi/wiki?EconomicsOfRefactoring

[PBSRWR] http://www.pbs.org/cringely/pulpit/pulpit20030508.html

[XPEDP] http://www.xpexchange.net/english/articles/designPatternsAndRefactoring.html

All sources last checked in may 2006.

18

Page 20: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

A Code of the OO project before the refactoring

A.1 Minermain.cpp

#include "stdafx.h"

#include "Minerapp.h"

#include <iomanip>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

Minerapp app;

app.init();

app.showModal();

return 0;

}

A.2 Diamant.h

#ifndef Diamant_h

#define Diamant_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Diamant: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "D " << "diamant.bmp" << " " << getX() << " " << getY() << " "

<< getvisible() << endl;

}

19

Page 21: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

bool vis;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

ladda >> vis;

setvisible(vis);

}

void getsort(char& sort)

{

sort = 'D';

}

private:

};

#endif

A.3 Dorr.h

#ifndef Dorr_h

#define Dorr_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

20

Page 22: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

////////////////////////////////////////////////////////////////////////////

class Dorr: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "E " << "exit.bmp" << " " << getX() << " " << getY() << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

}

void getsort(char& sort)

{

sort = 'E';

}

private:

};

#endif

A.4 Figure.h

#ifndef FIGURE_H

#define FIGURE_H

#include "..\saglib\SAGLIB.hpp"

#include <algorithm>

using namespace std;

21

Page 23: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

class Figure

{

public:

Figure(Bitmap* pBmp, int x,int y)

{

m_pBmp =pBmp;

m_x = x;

m_y = y;

}

Figure()

{

}

~Figure()

{

delete m_pBmp;

}

int getX()const {return m_x;}

int getY()const {return m_y;}

int getWidth()const{return m_pBmp->getWidth();}

int getHeight() const {return m_pBmp->getHeight();}

void setX(int x)

{

m_x = x;

}

void setY(int y)

{

m_y = y;

}

void setvisible(bool vis)

{

visible = vis;

}

bool getvisible()

{

22

Page 24: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

return visible;

}

void setFigure(int x, int y, string bmp, bool vis)

{

m_x = x;

m_y = y;

m_pBmp = new Bitmap(bmp);

m_pBmp->addTransparentColor(0,0,255);

visible = vis;

}

bool operlapsWith(const Figure& other) const

{

if( (getX() > (other.getX() + other.getWidth())) || (other.getX() >

(getX()+getWidth()) ) )

return false;//DISJOINT

if((getY() > (other.getY() + other.getHeight())) || (other.getY() >

(getY()+getHeight())))

return false;//DISJOINT

return true; // OVERLAP

}

bool overX(const Figure& other, int oldX) const //Kollar om player krockar i X-led

{

if ((((oldX > getX()) && (oldX < getX()+getWidth())) || ((oldX + other.getWidth())

> getX()) && ((oldX + other.getWidth()) < (getX()+getWidth()))) || (((oldX > getX())

&& (oldX < getX()+getWidth())) && ((oldX + other.getWidth()) > getX()) &&

((oldX + other.getWidth()) < (getX()+getWidth()))))

return true;

return false;

}

bool sideY(const Figure& other, int oldY) const //Kollar om player krockar i Y-led

{

if ((oldY >= getY()) && (oldY <= (getY() + getHeight())))

return true;

if (((oldY + other.getHeight()) >= getY()) && ((oldY + other.getHeight()) <=

(getY()+getHeight())))

return true;

23

Page 25: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

if ((oldY <= getY()) && ((oldY + other.getHeight()) >= (getY()+getHeight())))

return true;

return false;

}

bool isPointInside(int x,int y)

{

return ((x >= getX()) &&

(x <= getX() + getWidth()) &&

(y >= getY()) &&

(y <= getY() + getHeight()));

}

virtual void draw(Graphics& g)

{

m_pBmp->draw(g,m_x,m_y);

g.setColor(250,250,250);

}

virtual void getsort(char& sort)

{

}

virtual void ladda(ifstream &ladda)

{

}

virtual void save(ofstream &spara)

{

}

virtual void changeliv(int livchange)

{

}

24

Page 26: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

virtual void changescore(int scorechange)

{

}

virtual void move()

{

}

virtual void loop()

{

}

virtual void getspinfo(int &liv, int& score,int& level)

{

}

virtual void setspinfo(int &liv, int& score,int& level)

{

}

private:

Bitmap* m_pBmp;

int m_x;

int m_y;

bool visible;

};

#endif

A.5 Figurelist.h

#ifndef Figurelist_h

#define Figurelist_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

25

Page 27: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

#include "Figure.h"

#include "Kloss.h"

#include "Scorepanel.h"

#include "Ondtulpan.h"

#include "Storondtulpan.h"

#include "Monster.h"

#include "Stormonster.h"

#include "Nyckel.h"

#include "Diamant.h"

#include "Dorr.h"

#include "Meny.h"

#include "Player.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

class Figurelist

{

public:

void add(Figure *Fp)

{

Fpvector.push_back(Fp);

}

void spara()

{

int i;

ofstream spara("save.txt");

spelare->save(spara);

for(i=0;i<Fpvector.size();i++)

{

Fpvector[i]->save(spara);

}

spara.close();

}

26

Page 28: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

void ladda(string level)

{

Figure* nyPtr;

int i;

ifstream ladda(level.c_str());

for(i=0;i<Fpvector.size();i++)

{

delete Fpvector[i];

}

Fpvector.clear();

char tag;

while (ladda)

{

ladda >> tag;

if(ladda)

{

switch (tag)

{

case 'K':

nyPtr = new Kloss();

break;

case 'S':

nyPtr = new Scorepanel();

break;

case 't':

nyPtr = new Ondtulpan();

break;

case 'T':

nyPtr = new Storondtulpan();

break;

case 'm':

nyPtr = new Monster();

break;

case 'M':

nyPtr = new Stormonster();

break;

27

Page 29: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

case 'N':

nyPtr = new Nyckel();

break;

case 'D':

nyPtr = new Diamant();

break;

case 'E':

nyPtr = new Dorr();

break;

case 'P':

nyPtr = new Player();

break;

}

nyPtr->ladda(ladda);

if(tag !='P')

Fpvector.push_back(nyPtr);

else

spelare = nyPtr;

}

}

ladda.close();

}

vector<Figure*> get()

{

return Fpvector;

}

int getvectorsize()

{

return Fpvector.size();

}

Figure* getvectornr(int nr)

{

return Fpvector[nr];

}

void changeliv(int livchange)

28

Page 30: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

int i;

char sort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(sort);

if (sort == 'S')

{

Fpvector[i]->changeliv(livchange);

}

}

}

void changescore(int scorechange)

{

int i;

char sort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(sort);

if (sort == 'S')

{

Fpvector[i]->changescore(scorechange);

}

}

}

bool nyckeltagen()

{

int i;

char sort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(sort);

if (sort == 'N')

{

if(Fpvector[i]->getvisible())

29

Page 31: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

return false;

}

}

return true;

}

Figure* getspelare()

{

return spelare;

}

void getspinfo(int &liv, int& score,int& level)

{

int i;

char sort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(sort);

if (sort == 'S')

{

Fpvector[i]->getspinfo(liv, score, level);

}

}

}

void setspinfo(int &liv, int& score,int& level)

{

int i;

char sort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(sort);

if (sort == 'S')

{

Fpvector[i]->setspinfo(liv, score, level);

}

}

30

Page 32: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

~Figurelist()

{

int i;

delete spelare;

for(i=0;i<Fpvector.size();i++)

{

delete Fpvector[i];

}

}

private:

vector<Figure*> Fpvector;

Figure* spelare;

};

#endif

A.6 Kloss.h

#ifndef Kloss_h

#define Kloss_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Kloss: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "K " << "kloss.bmp" << " " << getX() << " " << getY() << endl;

31

Page 33: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

}

void getsort(char& sort)

{

sort = 'K';

}

private:

};

#endif

A.7 Meny.h

#ifndef Meny_h

#define Meny_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Meny: public Figure

{

32

Page 34: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

public:

Meny()

{

setFigure(300, 300, "meny.bmp", false);

}

private:

};

#endif

A.8 Minerapp.h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include "Figurelist.h"

#include "Kloss.h"

#include "Scorepanel.h"

#include "Player.h"

#include "Monster.h"

#include "Stormonster.h"

#include "Nyckel.h"

#include "Diamant.h"

#include "Dorr.h"

#include "Meny.h"

#include "Pausemeny.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

class Minerapp:public Application

{

public:

virtual void init()

{

Application::init("Samlarbosse strikes again",945,740);

33

Page 35: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

krockar = false;

hopp = false;

vandhopp = false;

hopptid = 0;

meny = new Meny();

pausemeny = new Pausemeny();

lista.ladda("level1.txt");

spelare = lista.getspelare();

Application::setAndStartTimer(1);

}

~Minerapp()

{

delete spelare;

delete meny;

delete pausemeny;

}

virtual void onTimer(unsigned int tVal)

{

if (meny->getvisible())

{

while (true)

{

if(isKeyDown(SG_N))

{

lista.ladda("level1.txt");

spelare = lista.getspelare();

meny->setvisible(false);

break;

}

if(isKeyDown(SG_Q))

{

exit(0);

}

if(isKeyDown(SG_L))

{

34

Page 36: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

lista.ladda("save.txt");

spelare = lista.getspelare();

meny->setvisible(false);

break;

}

}

}

if (menytemp)

{

meny->setvisible(true);

menytemp = false;

}

if (pausemeny->getvisible())

{

while (true)

{

if(isKeyDown(SG_N))

{

lista.ladda("level1.txt");

spelare = lista.getspelare();

pausemeny->setvisible(false);

break;

}

if(isKeyDown(SG_Q))

{

exit(0);

}

if(isKeyDown(SG_L))

{

lista.ladda("save.txt");

spelare = lista.getspelare();

pausemeny->setvisible(false);

break;

}

if(isKeyDown(SG_S))

{

lista.spara();

pausemeny->setvisible(false);

35

Page 37: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

break;

}

if(isKeyDown(SG_F))

{

pausemeny->setvisible(false);

break;

}

}

}

if (isKeyDown(SG_P))

{

pausemeny->setvisible(true);

}

int oldX = spelare->getX();

int oldY = spelare->getY();

if (oldX < -30) //Gör så att gubben kan springa "runt" spelplanen

{

spelare->setX(940);

oldX = spelare->getX();

}

if (oldX > 945) //Gör så att gubben kan springa "runt" spelplanen

{

spelare->setX(-29);

oldX = spelare->getX();

}

if (vandhopp == true)

{

spelare->setY(spelare->getY()+16);

hopptid++;

if (hopptid == 15)

{

hopptid = 0;

vandhopp = false;

}

}

36

Page 38: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

spelare->setY(spelare->getY()-8);

if(isKeyDown(SG_LEFT))

spelare->setX(spelare->getX()-6);

if(isKeyDown(SG_RIGHT))

spelare->setX(spelare->getX()+6);;

char sort;

bool temp;

int liv;

int score;

int level;

for (i=0; i<lista.getvectorsize(); i++)

{

krockar = lista.getvectornr(i)->operlapsWith(*spelare);

lista.getvectornr(i)->getsort(sort);

if (sort == 'm' || sort == 'M')

{

lista.getvectornr(i)->move();

}

if (krockar)

{

switch (sort)

{

case 'K':

temp = true;

if ((lista.getvectornr(i)->sideY(*spelare, oldY)))

{

spelare->setX(oldX);

temp = false;

}

if ((lista.getvectornr(i)->overX(*spelare, oldX)) && (temp == true))

{

if (oldY < spelare->getY())

37

Page 39: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

vandhopp = false;

hopptid = 0;

}

if (oldY > spelare->getY())

{

hopp = false;

}

spelare->setY(oldY);

temp = false;

}

if ((isKeyDown(SG_UP)) && (hopp == false))

{

hopp = true;

vandhopp = true;

}

break;

case 'S':

//Gör ingenting

break;

case 'T':

lista.changeliv(-1);

lista.getspinfo(liv, score, level);

if (liv == 0)

{

meny->setvisible(true);

}

else

{

spelare->setY(40);

spelare->setX(40);

}

break;

case 't':

lista.changeliv(-1);

lista.getspinfo(liv, score, level);

38

Page 40: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

if (liv == 0)

{

meny->setvisible(true);

}

else

{

spelare->setY(40);

spelare->setX(40);

}

break;

case 'm':

lista.changeliv(-1);

lista.getspinfo(liv, score, level);

if (liv == 0)

{

meny->setvisible(true);

}

else

{

spelare->setY(40);

spelare->setX(40);

}

break;

case 'M':

lista.changeliv(-1);

lista.getspinfo(liv, score, level);

if (liv == 0)

{

meny->setvisible(true);

}

else

{

spelare->setY(40);

spelare->setX(40);

}

break;

break;

39

Page 41: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

case 'N':

if (lista.getvectornr(i)->getvisible())

{

lista.changescore(554);

}

lista.getvectornr(i)->setvisible(false);

break;

case 'D':

if (lista.getvectornr(i)->getvisible())

{

lista.changescore(277);

}

lista.getvectornr(i)->setvisible(false);

break;

case 'E':

if (lista.nyckeltagen())

{

lista.changescore(1001);

lista.getspinfo(liv, score, level);

if (level == 1)

{

lista.ladda("level2.txt");

}

if (level == 2)

{

lista.ladda("level3.txt");

}

if (level == 3)

{

menytemp = true;

}

level++;

lista.setspinfo(liv, score, level);

spelare = lista.getspelare();

40

Page 42: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

break;

}

}

}

updateDisplay();

}

virtual void onDraw(Graphics& g)

{

for (i=0; i<lista.getvectorsize(); i++)

{

if (lista.getvectornr(i)->getvisible())

lista.getvectornr(i)->draw(g);

}

spelare->draw(g);

if(meny->getvisible())

{

meny->draw(g);

}

if(pausemeny->getvisible())

{

pausemeny->draw(g);

}

}

private:

Figure* spelare;

Figure* meny;

Figure* pausemeny;

bool krockar;

bool menytemp;

bool hopp;

bool vandhopp;

41

Page 43: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

int hopptid;

int i;

Figurelist lista;

};

A.9 Monster.h

#ifndef Monster_h

#define Monster_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Monster: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "m " << "monster.bmp" << " " << getX() << " " << getY() << " " << dir

<< " " << minx << " " << maxx << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

ladda >> x;

ladda >> y;

42

Page 44: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

setFigure(x, y, bmp, true);

ladda >> dir;

ladda >> minx;

ladda >> maxx;

}

void getsort(char& sort)

{

sort = 'm';

}

virtual void move()

{

if (dir == 6)

{

setX(getX()+10);

if (getX() > maxx)

{

dir = 4;

setX(getX()-10);

}

}

if (dir == 4)

{

setX(getX()-10);

if (getX() < minx)

{

dir = 6;

setX(getX()+10);

}

}

}

private:

int maxx;

int minx;

int dir;

};

43

Page 45: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

#endif

A.10 Nyckel.h

#ifndef Nyckel_h

#define Nyckel_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Nyckel: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "N " << "nyckel.bmp" << " " << getX() << " " << getY() << " "

<< getvisible() << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

bool vis;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

ladda >> vis;

setvisible(vis);

44

Page 46: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

void getsort(char& sort)

{

sort = 'N';

}

private:

};

#endif

A.11 Ondtulpan.h

#ifndef Ondtulpan_h

#define Ondtulpan_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Ondtulpan: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "t " << "tulpan.bmp" << " " << getX() << " " << getY() << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

45

Page 47: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

}

void getsort(char& sort)

{

sort = 't';

}

private:

};

#endif

A.12 Pausemeny.h

#ifndef Pausemeny_h

#define Pausemeny_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Pausemeny: public Figure

{

public:

Pausemeny()

{

setFigure(300, 300, "pausemeny.bmp", false);

}

private:

46

Page 48: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

};

#endif

A.13 Player.h

#ifndef Player_h

#define Player_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Player: public Figure

{

public:

Player()

{

}

virtual void save(ofstream& spara)

{

spara << "P " << "player.bmp" << " " << getX() << " " << getY() << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

47

Page 49: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

void getsort(char& sort)

{

sort = 'P';

}

private:

};

#endif

A.14 Scorepanel.h

#ifndef Scorepanel_h

#define Scorepanel_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Scorepanel: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "S " << "scorepanel.bmp" << " " << getX() << " " << getY() << " "

<< liv << " " << score << " " << level << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

48

Page 50: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

ladda >> liv;

ladda >> score;

ladda >> level;

}

void getsort(char& sort)

{

sort = 'S';

}

virtual void draw(Graphics& g)

{

Figure::draw(g);

char buf[255];

sprintf(buf,"Liv=%d",liv);

g.drawText(buf,450,700);

sprintf(buf,"Score=%d",score);

g.drawText(buf,360,700);

sprintf(buf,"Level=%d",level);

g.drawText(buf,520,700);

}

void changeliv(int livchange)

{

liv = liv + livchange;

}

void changescore(int scorechange)

{

score = score + scorechange;

}

void getspinfo(int &nyliv, int& nyscore,int& nylevel)

{

nyliv = liv;

49

Page 51: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

nyscore = score;

nylevel = level;

}

void setspinfo(int &nyliv, int& nyscore,int& nylevel)

{

liv = nyliv;

score = nyscore;

level = nylevel;

}

private:

int score;

int liv;

int level;

};

#endif

A.15 Stormonster.h

#ifndef Stormonster_h

#define Stormonster_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Stormonster: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "M " << "stormonster.bmp" << " " << getX() << " " << getY() << " "

<< dir << " " << minx << " " << maxx << endl;

}

50

Page 52: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

ladda >> dir;

ladda >> minx;

ladda >> maxx;

}

void getsort(char& sort)

{

sort = 'M';

}

virtual void move()

{

if (dir == 6)

{

setX(getX()+4);

if (getX() > maxx)

{

dir = 4;

setX(getX()-4);

}

}

if (dir == 4)

{

setX(getX()-4);

if (getX() < minx)

{

51

Page 53: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

dir = 6;

setX(getX()+4);

}

}

}

private:

int maxx;

int minx;

int dir;

};

#endif

A.16 Storondtulpan.h

#ifndef Storondtulpan_h

#define Storondtulpan_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Storondtulpan: public Figure

{

public:

virtual void save(ofstream& spara)

{

spara << "T " << "tulpanstor.bmp" << " " << getX() << " " << getY() << endl;

}

virtual void ladda(ifstream& ladda)

{

int x, y;

string bmp;

ladda >> bmp;

52

Page 54: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

ladda >> x;

ladda >> y;

setFigure(x, y, bmp, true);

}

void getsort(char& sort)

{

sort = 'T';

}

private:

};

#endif

53

Page 55: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

B Code of the OO project after the refactoring

B.1 Minermain.cpp

#include "stdafx.h"

#include "Minerapp.h"

#include <iomanip>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

Minerapp application;

application.init();

application.showModal();

return 0;

}

B.2 Diamant.h

#ifndef Diamant_h

#define Diamant_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Diamant: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "D " << "diamant.bmp" << " " << getX() << " " << getY()

<< " " << getvisible() << endl;

}

54

Page 56: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

virtual void load(ifstream& FileToLoadFrom)

{

bool visible;

LoadFigure(FileToLoadFrom);

FileToLoadFrom >> visible;

setvisible(visible);

}

void getsort(char& sort)

{

sort = 'D';

}

private:

};

#endif

B.3 Dorr.h

#ifndef Dorr_h

#define Dorr_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Dorr: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

55

Page 57: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

FileToSaveIn << "E " << "exit.bmp" << " " << getX() << " " << getY() << endl;

}

void getsort(char& sort)

{

sort = 'E';

}

private:

};

#endif

B.4 Figure.h

#ifndef FIGURE_H

#define FIGURE_H

#include "..\saglib\SAGLIB.hpp"

#include <algorithm>

#include <fstream>

using namespace std;

class Figure

{

public:

Figure(int NewX, int NewY, string NewBmpPicture, bool NewVisible)

{

m_xPosition = NewX;

m_yPosition = NewY;

m_BmpPicture = new Bitmap(NewBmpPicture);

m_BmpPicture->addTransparentColor(0,0,255);

m_visible = NewVisible;

}

Figure()

{

}

56

Page 58: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

~Figure()

{

delete m_BmpPicture;

}

int getX()const

{

return m_xPosition;

}

int getY()const

{

return m_yPosition;

}

int getWidth()const

{

return m_BmpPicture->getWidth();

}

int getHeight() const

{

return m_BmpPicture->getHeight();

}

void setX(int NewX)

{

m_xPosition = NewX;

}

void setY(int NewY)

{

m_yPosition = NewY;

}

void setvisible(bool visible)

{

m_visible = visible;

}

bool getvisible()

{

return m_visible;

57

Page 59: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

void setFigure(int NewX, int NewY, string NewBmpPicture, bool NewVisible)

{

m_xPosition = NewX;

m_yPosition = NewY;

m_BmpPicture = new Bitmap(NewBmpPicture);

m_BmpPicture->addTransparentColor(0,0,255);

m_visible = NewVisible;

}

void LoadFigure(ifstream& FileToLoadFrom)

{

int xPosition, yPosition;

string bmpPicture;

FileToLoadFrom >> bmpPicture;

FileToLoadFrom >> xPosition;

FileToLoadFrom >> yPosition;

setFigure(xPosition, yPosition, bmpPicture, true);

}

bool operlapsWith(const Figure& other) const

{

if( (getX() > (other.getX() + other.getWidth())) || (other.getX() >

(getX()+getWidth()) ) )

return false;//DISJOINT

if((getY() > (other.getY() + other.getHeight())) || (other.getY() >

(getY()+getHeight())))

return false;//DISJOINT

return true; // OVERLAP

}

bool overX(const Figure& other, int oldX) const //Check if player crashes in x

{

if ((oldX > getX()) && (oldX < getX()+getWidth()))

return true;

if(((oldX + other.getWidth()) > getX()) && ((oldX + other.getWidth()) <

(getX()+getWidth())))

return true;

58

Page 60: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

if((((oldX > getX()) && (oldX < getX()+getWidth())) && ((oldX + other.getWidth()) >

getX()) && ((oldX + other.getWidth()) < (getX()+getWidth()))))

return true;

return false;

}

bool sideY(const Figure& other, int oldY) const //Check if player crashes in y

{

if ((oldY >= getY()) && (oldY <= (getY() + getHeight())))

return true;

if (((oldY + other.getHeight()) >= getY()) && ((oldY + other.getHeight()) <=

(getY()+getHeight())))

return true;

if ((oldY <= getY()) && ((oldY + other.getHeight()) >= (getY()+getHeight())))

return true;

return false;

}

bool isPointInside(int x,int y)

{

return ((x >= getX()) &&

(x <= getX() + getWidth()) &&

(y >= getY()) &&

(y <= getY() + getHeight()));

}

virtual void draw(Graphics& g)

{

m_BmpPicture->draw(g,m_xPosition,m_yPosition);

g.setColor(250,250,250);

}

virtual void getsort(char& sort)

{

59

Page 61: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

virtual void load(ifstream &FileToLoadFrom)

{

LoadFigure(FileToLoadFrom);

}

virtual void save(ofstream &FileToSaveIn)

{

}

virtual void changelife(int lifechange)

{

}

virtual void changescore(int scorechange)

{

}

virtual void move()

{

}

virtual void getScorePanelLife(int &getLife)

{

}

virtual void getScorePanelLevel(int &getLevel)

{

}

virtual void getScorePanelScore(int &getScore)

{

}

virtual void setScorePanelInfo(int &newLife, int &newScore,int &newLevel)

60

Page 62: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

}

private:

Bitmap* m_BmpPicture;

int m_xPosition;

int m_yPosition;

bool m_visible;

};

#endif

B.5 Figurelist.h

#ifndef Figurelist_h

#define Figurelist_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include "Kloss.h"

#include "Scorepanel.h"

#include "Ondtulpan.h"

#include "Storondtulpan.h"

#include "Monster.h"

#include "Stormonster.h"

#include "Nyckel.h"

#include "Diamant.h"

#include "Dorr.h"

#include "Player.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

class Figurelist

{

public:

void add(Figure *Fp)

61

Page 63: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

Fpvector.push_back(Fp);

}

void SaveAll()

{

int i;

ofstream FileToSaveIn("save.txt");

player->save(FileToSaveIn);

for(i=0;i<Fpvector.size();i++)

{

Fpvector[i]->save(FileToSaveIn);

}

FileToSaveIn.close();

}

void LoadFromFile(string level)

{

Figure* nyPtr;

int i;

ifstream FileToLoadFrom(level.c_str());

for(i=0;i<Fpvector.size();i++)

{

delete Fpvector[i];

}

Fpvector.clear();

char FigureSort;

while (FileToLoadFrom)

{

FileToLoadFrom >> FigureSort;

if(FileToLoadFrom)

{

switch (FigureSort)

62

Page 64: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

case 'K':

nyPtr = new Kloss();

break;

case 'S':

nyPtr = new Scorepanel();

break;

case 't':

nyPtr = new Ondtulpan();

break;

case 'T':

nyPtr = new Storondtulpan();

break;

case 'm':

nyPtr = new Monster();

break;

case 'M':

nyPtr = new Stormonster();

break;

case 'N':

nyPtr = new Nyckel();

break;

case 'D':

nyPtr = new Diamant();

break;

case 'E':

nyPtr = new Dorr();

break;

case 'P':

nyPtr = new Player();

break;

}

nyPtr->load(FileToLoadFrom);

if(FigureSort != 'P')

Fpvector.push_back(nyPtr);

else

player = nyPtr;

}

}

FileToLoadFrom.close();

63

Page 65: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

int getvectorsize()

{

return Fpvector.size();

}

Figure* getvectornr(int nr)

{

return Fpvector[nr];

}

void changelife(int lifechange)

{

Fpvector[getScorePanel()]->changelife(lifechange);

}

void changescore(int scorechange)

{

Fpvector[getScorePanel()]->changescore(scorechange);

}

bool nyckeltagen()

{

int i;

char FigureSort;

for (i=0; i<Fpvector.size(); i++)

{

Fpvector[i]->getsort(FigureSort);

if (FigureSort == 'N')

{

if(Fpvector[i]->getvisible())

return false;

}

}

return true;

}

64

Page 66: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

Figure* getPlayer()

{

return player;

}

void setScorePanelInfo(int &life, int& score,int& level)

{

Fpvector[getScorePanel()]->setScorePanelInfo(life, score, level);

}

int getScorePanelLife(void)

{

int life;

Fpvector[getScorePanel()]->getScorePanelLife(life);

return life;

}

int getScorePanelLevel(void)

{

int level;

Fpvector[getScorePanel()]->getScorePanelLevel(level);

return level;

}

int getScorePanelScore(void)

{

int score;

Fpvector[getScorePanel()]->getScorePanelScore(score);

return score;

}

int getScorePanel(void)

{

int i;

char FigureSort;

for (i=0; i<Fpvector.size(); i++)

65

Page 67: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

Fpvector[i]->getsort(FigureSort);

if (FigureSort == 'S')

{

return i;

}

}

}

~Figurelist()

{

int i;

delete player;

for(i=0;i<Fpvector.size();i++)

{

delete Fpvector[i];

}

}

private:

vector<Figure*> Fpvector;

Figure* player;

};

#endif

B.6 Kloss.h

#ifndef Kloss_h

#define Kloss_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

66

Page 68: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

////////////////////////////////////////////////////////////////////////////

class Kloss: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "K " << "kloss.bmp" << " " << getX() << " " << getY() << endl;

}

void getsort(char& sort)

{

sort = 'K';

}

private:

};

#endif

B.7 Minerapp.h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include "Figurelist.h"

#include "Kloss.h"

#include "Scorepanel.h"

#include "Player.h"

#include "Monster.h"

#include "Stormonster.h"

#include "Nyckel.h"

#include "Diamant.h"

#include "Dorr.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

67

Page 69: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

class Minerapp:public Application

{

public:

virtual void init()

{

Application::init("Samlarbosse strikes again",945,740);

crash = false;

inAir = false;

jumpGoingUp = false;

jumpingTimer = 0;

menu = new Figure(300, 300, "meny.bmp", false);

pausemenu = new Figure(300, 300, "pausemeny.bmp", false);

ListOfFigures.LoadFromFile("level1.txt");

player = ListOfFigures.getPlayer();

Application::setAndStartTimer(1);

}

~Minerapp()

{

delete player;

delete menu;

delete pausemenu;

}

virtual void onTimer(unsigned int tVal)

{

if (menu->getvisible())

{

while (true)

{

if(isKeyDown(SG_N))

{

ListOfFigures.LoadFromFile("level1.txt");

player = ListOfFigures.getPlayer();

menu->setvisible(false);

break;

}

68

Page 70: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

if(isKeyDown(SG_Q))

{

exit(0);

}

if(isKeyDown(SG_L))

{

ListOfFigures.LoadFromFile("save.txt");

player = ListOfFigures.getPlayer();

menu->setvisible(false);

break;

}

}

}

if (MainMenu)

{

menu->setvisible(true);

MainMenu = false;

}

if (pausemenu->getvisible())

{

while (true)

{

if(isKeyDown(SG_N))

{

ListOfFigures.LoadFromFile("level1.txt");

player = ListOfFigures.getPlayer();

pausemenu->setvisible(false);

break;

}

if(isKeyDown(SG_Q))

{

exit(0);

}

if(isKeyDown(SG_L))

{

ListOfFigures.LoadFromFile("save.txt");

player = ListOfFigures.getPlayer();

pausemenu->setvisible(false);

69

Page 71: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

break;

}

if(isKeyDown(SG_S))

{

ListOfFigures.SaveAll();

pausemenu->setvisible(false);

break;

}

if(isKeyDown(SG_F))

{

pausemenu->setvisible(false);

break;

}

}

}

if (isKeyDown(SG_P))

{

pausemenu->setvisible(true);

}

int oldX = player->getX();

int oldY = player->getY();

if (oldX < -30) //Make the miner ``run around'' the screen

{

player->setX(940);

oldX = player->getX();

}

if (oldX > 945) //Make the miner ``run around'' the screen

{

player->setX(-29);

oldX = player->getX();

}

if (jumpGoingUp == true)

{

player->setY(player->getY()+16);

jumpingTimer++;

70

Page 72: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

if (jumpingTimer == 15)

{

jumpingTimer = 0;

jumpGoingUp = false;

}

}

player->setY(player->getY()-8);

if(isKeyDown(SG_LEFT))

player->setX(player->getX()-6);

if(isKeyDown(SG_RIGHT))

player->setX(player->getX()+6);;

char FigureSort;

for (i=0; i<ListOfFigures.getvectorsize(); i++)

{

crash = ListOfFigures.getvectornr(i)->operlapsWith(*player);

ListOfFigures.getvectornr(i)->getsort(FigureSort);

if (FigureSort == 'm' || FigureSort == 'M')

{

ListOfFigures.getvectornr(i)->move();

}

if (crash)

{

switch (FigureSort)

{

case 'K':

CrashWithFriendlySurface(i, oldX, oldY);

break;

case 'S':

//Do nothing

break;

case 'T':

CrashAndDie();

break;

case 't':

CrashAndDie();

break;

71

Page 73: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

case 'm':

CrashAndDie();

break;

case 'M':

CrashAndDie();

break;

case 'N':

TreasureTaken(554, i);

break;

case 'D':

TreasureTaken(257, i);

break;

case 'E':

if(ListOfFigures.nyckeltagen())

{

ExitLevel();

}

break;

}

}

}

updateDisplay();

}

virtual void onDraw(Graphics& g)

{

for (i=0; i<ListOfFigures.getvectorsize(); i++)

{

if (ListOfFigures.getvectornr(i)->getvisible())

ListOfFigures.getvectornr(i)->draw(g);

}

player->draw(g);

if(menu->getvisible())

{

menu->draw(g);

}

if(pausemenu->getvisible())

{

pausemenu->draw(g);

}

72

Page 74: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

void CrashAndDie(void)

{

ListOfFigures.changelife(-1);

if (ListOfFigures.getScorePanelLife() == 0)

{

menu->setvisible(true);

}

else

{

player->setY(40);

player->setX(40);

}

}

void TreasureTaken(int score, int i)

{

if (ListOfFigures.getvectornr(i)->getvisible())

{

ListOfFigures.changescore(score);

}

ListOfFigures.getvectornr(i)->setvisible(false);

}

void ExitLevel(void)

{

int life;

int score;

int level;

ListOfFigures.changescore(1001);

level = ListOfFigures.getScorePanelLevel();

score = ListOfFigures.getScorePanelScore();

life = ListOfFigures.getScorePanelLife();

if (ListOfFigures.getScorePanelLevel() == 1)

{

ListOfFigures.LoadFromFile("level2.txt");

}

else if (ListOfFigures.getScorePanelLevel() == 2)

{

73

Page 75: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

ListOfFigures.LoadFromFile("level3.txt");

}

else if (ListOfFigures.getScorePanelLevel() == 3)

{

MainMenu = true;

}

level++;

ListOfFigures.setScorePanelInfo(life, score, level);

player = ListOfFigures.getPlayer();

}

void CrashWithFriendlySurface(int i, int oldX,int oldY)

{

bool crashTest;

crashTest = true;

if ((ListOfFigures.getvectornr(i)->sideY(*player, oldY)))

{

player->setX(oldX);

crashTest = false;

}

if ((ListOfFigures.getvectornr(i)->overX(*player, oldX)) && (crashTest == true))

{

if (oldY < player->getY())

{

jumpGoingUp = false;

jumpingTimer = 0;

}

if (oldY > player->getY())

{

inAir = false;

}

player->setY(oldY);

crashTest = false;

}

if ((isKeyDown(SG_UP)) && (inAir == false))

74

Page 76: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

{

inAir = true;

jumpGoingUp = true;

}

}

private:

Figure* player;

Figure* menu;

Figure* pausemenu;

bool crash;

bool MainMenu;

bool inAir;

bool jumpGoingUp;

int jumpingTimer;

int i;

Figurelist ListOfFigures;

};

B.8 Monster.h

#ifndef Monster_h

#define Monster_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Monster: public Figure

{

public:

75

Page 77: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "m " << "monster.bmp" << " " << getX() << " " << getY() << " "

<< direction << " " << minX << " " << maxX << endl;

}

virtual void load(ifstream& FileToLoadFrom)

{

LoadFigure(FileToLoadFrom);

FileToLoadFrom >> direction;

FileToLoadFrom >> minX;

FileToLoadFrom >> maxX;

}

void getsort(char& sort)

{

sort = 'm';

}

virtual void move()

{

if (direction == 6)

{

setX(getX()+10);

if (getX() > maxX)

{

direction = 4;

setX(getX()-10);

}

}

if (direction == 4)

{

setX(getX()-10);

if (getX() < minX)

{

direction = 6;

setX(getX()+10);

}

76

Page 78: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

}

private:

int maxX;

int minX;

int direction;

};

#endif

B.9 Nyckel.h

#ifndef Nyckel_h

#define Nyckel_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Nyckel: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "N " << "nyckel.bmp" << " " << getX() << " " << getY() << " "

<< getvisible() << endl;

}

virtual void load(ifstream& FileToLoadFrom)

{

bool visible;

LoadFigure(FileToLoadFrom);

FileToLoadFrom >> visible;

77

Page 79: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

setvisible(visible);

}

void getsort(char& sort)

{

sort = 'N';

}

private:

};

#endif

B.10 Ondtulpan.h

#ifndef Ondtulpan_h

#define Ondtulpan_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Ondtulpan: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "t " << "tulpan.bmp" << " " << getX() << " " << getY() << endl;

}

void getsort(char& sort)

{

sort = 't';

78

Page 80: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

private:

};

#endif

B.11 Player.h

#ifndef Player_h

#define Player_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Player: public Figure

{

public:

Player()

{

}

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "P " << "player.bmp" << " " << getX() << " " << getY() << endl;

}

void getsort(char& sort)

{

sort = 'P';

}

private:

};

79

Page 81: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

#endif

B.12 Scorepanel.h

#ifndef Scorepanel_h

#define Scorepanel_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Scorepanel: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "S " << "scorepanel.bmp" << " " << getX() << " " << getY()

<< " " << life << " " << score << " " << level << endl;

}

virtual void load(ifstream& FileToLoadFrom)

{

LoadFigure(FileToLoadFrom);

FileToLoadFrom >> life;

FileToLoadFrom >> score;

FileToLoadFrom >> level;

}

void getsort(char& sort)

{

sort = 'S';

}

virtual void draw(Graphics& g)

{

Figure::draw(g);

80

Page 82: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

char TextToDraw[255];

sprintf(TextToDraw,"Liv=%d",life);

g.drawText(TextToDraw,450,700);

sprintf(TextToDraw,"Score=%d",score);

g.drawText(TextToDraw,360,700);

sprintf(TextToDraw,"Level=%d",level);

g.drawText(TextToDraw,520,700);

}

void changelife(int lifechange)

{

life = life + lifechange;

}

void changescore(int scorechange)

{

score = score + scorechange;

}

void setScorePanelInfo(int &newLife, int &newScore,int &newLevel)

{

life = newLife;

score = newScore;

level = newLevel;

}

virtual void getScorePanelLife(int &getLife)

{

getLife = life;

}

virtual void getScorePanelLevel(int &getLevel)

{

getLevel = level;

}

virtual void getScorePanelScore(int &getScore)

{

getScore = score;

}

81

Page 83: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

private:

int score;

int life;

int level;

};

#endif

B.13 Stormonster.h

#ifndef Stormonster_h

#define Stormonster_h

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Stormonster: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "M " << "stormonster.bmp" << " " << getX() << " " << getY() << " "

<< direction << " " << minX << " " << maxX << endl;

}

virtual void load(ifstream& FileToLoadFrom)

{

LoadFigure(FileToLoadFrom);

FileToLoadFrom >> direction;

FileToLoadFrom >> minX;

FileToLoadFrom >> maxX;

82

Page 84: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

}

void getsort(char& sort)

{

sort = 'M';

}

virtual void move()

{

if (direction == 6)

{

setX(getX()+4);

if (getX() > maxX)

{

direction = 4;

setX(getX()-4);

}

}

if (direction == 4)

{

setX(getX()-4);

if (getX() < minX)

{

direction = 6;

setX(getX()+4);

}

}

}

private:

int maxX;

int minX;

int direction;

};

#endif

B.14 Storondtulpan.h

#ifndef Storondtulpan_h

#define Storondtulpan_h

83

Page 85: Refactoring - MDH · Refactoring is a way to clean up and improve the internal structure of already working code without changing its external behavior. Its a technique of improving

#include "stdafx.h"

#include "..\saglib\SAGLIB.hpp"

#include "Figure.h"

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

#include <math.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////

class Storondtulpan: public Figure

{

public:

virtual void save(ofstream& FileToSaveIn)

{

FileToSaveIn << "T " << "tulpanstor.bmp" << " " << getX() << " " << getY() << endl;

}

void getsort(char& sort)

{

sort = 'T';

}

private:

};

#endif

84