And the next topic that we're going to cover is refactoring and by doing refactoring we try to improve a piece of software's internal structure without changing its external behavior. So you may ask why fix a part of your system that is functional and it's not broken. And notice that your systems code has three purposes. It should execute its functionality, and also allow change, and also communicate well to other developers who read it. So if the code cannot do all three of this is broken. So to make sure that your program is going to be having a good structure and it's going to be easy to maintain, and also allow change, and also communicate well to the other developers, then we have to refactor the source code. And notice that code rots over time if its structure does not evolve. Why? Because when you program you may add one little thing at a time into your program. And you may also include many workarounds into your program from time to time. So eventually code is going to rot over time in terms of structure. So to improve the overall structure of your program, you have to perform refactoring from time to time. So for low level refactoring, we are talking about renaming operations and also variables. So instead of using names like function one, function two for operations, and also using names like X, Y Z, A, B, C for variables, you have to give more meaningful names to your operations and also variables, to make sure that they are going to be meaningful to not just you, but also other developers. And make sure that you name all the magic constants that you have within your program. So instead of saying that we have a magic constants X equals to 40, you should give a more meaningful name to your constant. For example, the upper bunk of the enrollment for a class is going to be 40. Or you can extract code into a method, or extract some common functionality into a module or operation, or inline an operational procedure into your program, or changing the operation signatures. We can also improve the structure of the program by splitting one operation into several to improve cohesion and also readability. And also putting statements that are semantically belong together near to each other physically within your program. And notice that there are some IDEs or tools that support this kind of refactoring. So compared to low level refactoring, high level refactoring is going to be even more important because it's going to help you improve the overall structure of your program. So in higher level refactoring we have to exchange obscure language idioms with safer alternatives. So for example, even if you can write an if statement in one single line, try to avoid doing that because you can read that one single line but some other developers, if they are not familiar with writing if statement in one single line, they may not be able to understand your source code. And also clarify a statement that has evolved over time or it's unclear using comments and also refactor according to some design patterns which we will cover later on. As I have said, compared to low level refactoring, high level refactoring is much more important because it's going to improve the overall structure of your program, but it's not well supported by tools, so you have to do it manually yourself. And these types of refactoring is going to increase code maintain liability because you improve the overall structure of your program. So now let's take a look at this example which is a program for a library. And now you can see that in the main class we have many operations and this is a typical example of a god class. So what is a god class? A god class means you have a very big class in your program or in your system that try to do everything within the system. So now you can see that we have a big main class that does almost everything within the system. And this kind of code is not good because it's difficult to read and also difficult to maintain. So how can we improve the structure? And in the first step you try to identify or categorize related attributes and operations from the class diagram. And now you can see that you have many related operations in the main class, and all these operations, they are related to items. For example, checking out items, checking in items, adding items, deleting items, or edit item, or finding items, they are all related to items. So instead of putting it in the main class, now we should put it in the item class. And we can also find that many of the operations they are related to catalog. For example, printing catalogs, sorting catalog, searching for some catalog, listing catalogs, or archive catalogs. So instead of putting them in the main class, should be more reasonable to put them in the catalog class. So that's why we have to find the natural homes for this collection of functionalities and then migrate them there. So we should put all these operations related to items in the item class, and all these operations related to catalog in the catalog class. And this is the updated class diagram. And in the last step we have to remove all the transient associations replacing them as appropriate with type specifier to attributes and operations arguments. And now in this example we can see that the main class is going to assess catalog and within catalog we're going to get different items within the library. So that's why we don't assess items directly using the main class. Now we can remove this transient association because we assess items through catalog. So now instead of having this association here, that's why here we say that it's a transient association because we don't use the main class to directly assess item. So that's why we can remove this association and finally we will get this much cleaner and much more easy to read class diagram for the library example. So now suppose that you want to add new features to the code that is not particularly well designed it or formally tested but works so far. So what should you do? So you should first assume that you have adequate time to do things right and then write unit tests to verify that the code works correctly. And then we refractor the code, and then add some new features. Some of you may argue that I don't have time to refactor because we have limited time within the project. And it's true that many developers they don't want to do refactoring because if the program is working why bother touching my working or my perfect program. And also most management people, they do not like doing refactoring because they lose time and also gain nothing. Again because the program is working why bother touching it. However, it's important to do refactoring because well-written code is much more conductive to rapid development. And also finishing refactoring increases programmer morale. And as a programmer, I guess you guys prefer working in a clean house, that means a program with a better structure. So when do we refactor? We try to do it continuously as part of the development. So we refactor and then we develop something, then we refactor and then we develop something. And it's hard to do well late in the project because by the end of the project you're going to have many features in your system, and touching one of the feature may affect the other features. So that's why it's difficult to restructure your program by the end of the project, and that's what I want to cover in this lecture.