Presentation is loading. Please wait.

Presentation is loading. Please wait.

Leiden University. The university to discover. Leiden University. The university to discover. Leiden University. The university to discover. Software Engineering.

Similar presentations


Presentation on theme: "Leiden University. The university to discover. Leiden University. The university to discover. Leiden University. The university to discover. Software Engineering."— Presentation transcript:

1 Leiden University. The university to discover. Leiden University. The university to discover. Leiden University. The university to discover. Software Engineering “Design during construction” Leiden Institute of Advanced Computer Science Lecture Series for BSc. “Computer Science” year 2 (Fall semester 2012)

2 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 2 | 25 Design Patterns Overview A Recap of the Object Oriented Paradigm Design Patterns  Objective  Types of Patterns  Some Examples of Design Patterns... Abstract Factory Patterm Visitor Pattern Model-View-Controller Pattern Slides based on slides by Bart Kienhuis

3 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 3 | 25 Refactoring Overview Software Entropy Program starts in a well designed state New functionality is added Deforming the state… Program was not intended for the job Program has become complex Typically Attitude: “If it ain’t broke, don’t fix it”

4 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 4 | 25 Recap of the Object Oriented Paradigm What is inheritance?  A type of relationship between (at least) two objects in which one is a subtype of the other (which we call supertype). The subtype inherits features of the supertype Why? Reusability through extendability, simplicity and realiability

5 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 5 | 25 Recap of the Object Oriented Paradigm (2) What is polymorphism?  The ability to create a variable, a function, or an object that has more than one form. Why ? Objects can behave differently, depending on context. This enables simplicity and aids extensibility. What is encapsulation?  Hiding design decisions from other software components. Why? A limited protocol is presented to other software components so they are protected from details that change. This (again) enables simplicity and aids extensibility. “No component in a complex system should depend on the internal details of any other component.” (Dan Ingalls)

6 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 6 | 25 Recap of the Object Oriented Paradigm (3) A Class is static i.e. its attributes don't change during or after execution of a program Concept (Blueprint)  Car  Human An Object has a limited lifespan i.e. Objects are created and destroyed and its attributes may change Instantiation  My car  John What is the difference between a class and an object?

7 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 7 | 25 Design Pattern Book Design Patterns: Elements of Reusable Object-Oriented Software by  Gamma et al. (a.ka. the Gang of Four)  Addison Wesley Professional (Nov 10, 1994) ISBN 0- 201-63361-2 “One of the first, and most well-received books on Design Patterns”

8 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 8 | 25 The Objective of Design Patterns “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” – Christopher Alexander

9 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 9 | 25 Why Study Design Patterns? Patterns allow us to Reuse solutions By reusing already established designs, you get a head start on my problems. I do not have to reinvent solutions for commonly recurring problems. Establish common terminology Design patterns provide a a common base of vocabulary and a common viewpoint of the problem during the analysis and design phase of a project. Patterns give you a higher-level perspective on the problem and on the process of design and object orientation. Shalloway et al. (2002) Design Patterns Eplained

10 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 10 | 25 Why Study Design Patterns? (2) Decide whether you have the “right” design, not just one that works. Improve individual learning and team learning. Improve the modifiability of code. Facilitate adoption of improved design alternatives, even when patterns are not used explicitly. Discover alternatives to large inheritance hierarchies. Shalloway et al. (2002) Design Patterns Eplained

11 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 11 | 25 Design Pattern Classification Scope: specifies whether the pattern applies primarily to classes or to objects  Class patterns deal with relationships between classes and their subclasses. These relationships are established through inheritance, so they are static— fixed at compile-time.  Object patterns deal with object relationships, which can be changed at run-time and are more dynamic.  Almost all patterns use inheritance to some extent. So the only patterns labeled "class patterns" are those that focus on class relationships.  Note that most patterns are in the Object scope.

12 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 12 | 25 Design Pattern Classification (2) Purpose Creational Design Patterns  deal with object creation mechanisms, divided into “Object-creational patterns” (deal with object creation) “Class-creational patterns” (deal with class-instantiation) Behavioral Design Patterns Structural Design Patterns Concurrency Patterns  deal with multi-threaded programming paradigm ( )

13 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 13 | 25 The Facade Pattern Intent You want to simplify how to use an existing system. You need to define your own interface. Problem You need to use only a subset of a complex system. Or you need to interact with the system in a particular way. Solution The Facade presents a new interface for the client of the existing system to use. Participants and Collaborators It presents a specialized interface to the client that makes it easier to use. Consequences The Facade simplifies the use of the required subsystem. However, since the Facade is not complete, certain functionality may be unavailable to the client. Implementation Define a new class (or classes) that has the required interface and have this new class use the existing system.

14 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 14 | 25 The Facade Pattern (Example)

15 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 15 | 25 The Facade Pattern (Implementation)

16 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 16 | 25 (Abstract) Factory Design Pattern Problem: If an application is to be portable, it needs to encapsulate platform dependencies. Solution: Provide an interface for creating families of related or dependent objects without specifying their concrete classes. http://upload.wikimedia.org/wikipedia/commons/a/a7/Abstract_ factory.svg

17 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 17 | 25 Factory Design Pattern (Implementation) 1. Define an abstract class that specifies which objects are to be made. 2. Then implement one concrete class for each family. Tables or files can also be used to essentially accomplish the same thing. Names of the desired classes can be kept in a database and then switches or run-time type identification (RTTI) can be used to instantiate the correct objects. “Pattern Oriented Design: Design Patterns From Analysis to Implementation” NetObjects

18 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 18 | 25 Visitor Design Pattern Problem: Many distinct and unrelated operations need to be performed on node objects in a heterogeneous aggregate structure. You want to avoid “polluting” the node classes with these operations. And, you don’t want to have to query the type of each node and cast the pointer to the correct type before performing the desired operation. Solution: Represent an operation to be performed on the elements of an object structure. Visitors lets you define a new operation without changing the classes of the elements on which it operates.

19 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 19 | 25 Visitor Design Pattern (Another View) “Head First Design Patterns” (2004) Freeman et al.

20 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 20 | 25 Visitor Design Pattern (Implementation) 1. Make an abstract class that represents the tasks to be performed. 2. Add a method to this class for each concrete class you started with (your original entities). 3. Add a method to the classes that you are working on to call the appropriate method in this task class, giving a reference to itself to this method. “Pattern Oriented Design: Design Patterns From Analysis to Implementation” NetObjects

21 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 21 | 25 Strategy Design Pattern Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it. Problem: The selection of an algorithm that needs to be applied depends upon the client making the request or the data being acted upon. If you simply have a rule in place that does not change, you do not need a Strategy pattern. Solution: de-couple your data, your presentation of the data and the logic for handling the events from each other.

22 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 22 | 25 Strategy Design Pattern (Example)

23 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 23 | 25 Combining Patterns Model View Controller (MVC)  consists of three kinds of objects.  The Model is the application object  The View is its screen presentation  The Controller defines the way the user interface reacts to user input.  Decoupling increases flexibility and reuse.

24 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 24 | 25 Combining Patterns (2) MVC is three patterns  Model is an Observer Design Pattern  As it keeps views and controllers updated  Controller and View implement a Strategy Design Pattern  As the interchangable controller describes the behaviour of the view  View uses a Factory Design Pattern  As it manages various kinds of display elements

25 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 25 | 25 Observer Design Pattern in the MVC

26 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 26 | 25 Critisism of Design Patterns The need for patterns implies insufficient abstraction ability in the applied language or technique  Many patterns are redundant in other languages Lacks formal foundations Leads to inefficient solutions  design pattern are attempts to standardize what are already accepted best practices. Might lead to unnecessary duplication of code. It is almost always a more efficient solution to use a well-factored implementation rather than a "just barely good enough" design pattern. Does not differ significantly from other abstractions  the Model-View-Controller paradigm is an example of a "pattern" which predates the concept of "design patterns" by several years.

27 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 27 | 25 Refactoring How to detect the opportunity to Refactor (to add value)? Set of “Smells” that indicate places that would benefit from refactoring Helps software developer to distinguish between good code and bad code Refactoring: Improving the Design of Existing code. Author: Martin Fowler Publisher: Addison Wesley ISBN:0-201-48567-2

28 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 28 | 25 Refactoring Refactoring: techniques to do redesign of existing code with little short-term pain. Is about not changing the functionality, but change the structure, order, and names. Happens in small steps  Renaming method  Moving a field from one class to another  Consolidate two similar methods in a superclass Design occurs continuously during design (compare this to the waterfall principle) Related principle: “Design for today, not for tomorrow”

29 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 29 | 25 Defining Refactoring Refactoring (noun) a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior. Refactor (verb) to restructure software by applying a series of refactorings without changing its observable behavior.

30 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 30 | 25 Refactoring improves the design of software Without refactoring the design of the program will decay Poorly designed code usually takes more code to do the same things, often because the code does the same thing in different places Refactoring makes software easier to understand In most software development environments, somebody else will eventually have to read your code Refactoring helps you find bugs Refactoring helps you program faster Why Should You Refactor?

31 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 31 | 25 Why Should You Refactor? The Rule of three (Don Roberts) Refactor when you add function Helps you to understand the code you are modifying Sometimes the existing design does not allow you to easily add the feature Refactor when you need to fix a bug If you get a bug report its a sign the code needs refactoring because the code was not clear enough for you to see the bug in the first place Refactor as you do a code review Code reviews help spread knowledge through the development team Works best with small review groups XP pair programming is active code review taken to its limit

32 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 32 | 25 Refactoring and Design Upfront design XP advocates that you code the first approach that comes in to your head, get it working, and then refactor it into shape The point is that refactoring changes the role of upfront design You are no longer looking for the perfect solution when doing design but a reasonable one Refactoring can lead to simpler designs without sacrificing flexibility

33 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 33 | 25 Refactoring and Performance A common concern with refactoring is its effect on performance Refactoring will make software slower but it also makes the software more amenable to performance tuning The secret to fast software, in all but hard real-time contexts, is to write tunable software first and then to tune it for sufficient speed Profiling ensures that you focus your tuning efforts in the right places

34 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 34 | 25 Where Did Refactoring Come From? Two of the first people to recognize the importance of refactoring were Kent Beck and Ward Cunningham The worked with Smalltalk from the 80's onward Refactoring has always been an important element in the Smalltalk community Ralph Johnson's work with refactoring and frameworks has been an important contribution Bill Opdyke focused his doctoral research on developing refactoring tools for use in frameworks Outside of Fowler's book, Opdyke's doctoral thesis is the most substantial work in this area

35 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 35 | 25 Bad Smells in Code Duplicated Code Long Method Large Class Long Parameter List Divergent Change Shotgun Surgery Feature Envy Data Clumps Primitive Obsession Switch Statements Parallel Inheritance Hierarchies Lazy Class Speculative Generality Temporary Field Message Chains Middle Man Inappropriate Intimacy Alternative Classes with Different Interfaces Incomplete Library Class Data Class Learn to identify these smells and you have already become A much better Software Engineer !

36 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 36 | 25 Duplicated Code If you see the same code structure in more than one place, you can be sure that your program will be better if you find a way to unify them The simplest duplicated code problem is when you have the same expression in two methods of the same class Perform Extract Method and invoke the code from both places Another common duplication problem is having the same expression in two sibling subclasses Perform Extract Method in both classes then Pull Up Field If you have duplicated code in two unrelated classes, consider using Extract Class in one class and then use the new component in the other

37 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 37 | 25 Long Method The longer a procedure is the more difficult it is to understand Nearly all of the time all you have to do to shorten a method is Extract Method If you try to use Extract Method and end up passing a lot of parameters, you can often use Replace Temp with Query to eliminate the temps and slim down the long list of parameters with Introduce Parameter Object and Preserve Whole Object

38 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 38 | 25 Large Class When a class is trying to do too much, it often shows up as too many instance variables. When a class has too many instance variables, duplicated code cannot be far behind A class with too much code is also a breeding ground for duplication In both cases Extract Class and Extract Subclass will work

39 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 39 | 25 Long Parameter List With objects you don't need to pass in everything the method needs, instead you pass in enough so the method can get to everything it needs This is goodness, because long parameter lists are hard to understand, because they inconsistent and difficult to use because you are forever changing them as you need more data Use Replace Parameter with Method when you can get the data in one parameter by making a request of an object you already know about

40 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 40 | 25 Divergent Change Divergent change occurs when one class is commonly changed in different ways for different reasons If for example you have to change 4 different methods every time the database changes you might have a situation where two objects are better than one To clean this up you identify everything that changes for a particular cause and use Extract Class to put them all together

41 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 41 | 25 Shotgun Surgery This situation occurs when every time you make a kind of change, you have to make a lot of little changes to a lot of different classes When the changes are all over the place they are hard to find, and its easy to miss an important change. You want to use Move Method and Move Field to put all the changes in a single class If no current class looks like a good candidate then create one Often you can use Inline Class to bring a whole bunch of behavior together

42 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 42 | 25 Feature Envy A classic smell is a method that seems more interested in a class other in the one that it is in The method clearly wants to be elsewhere, so use Move Method to get it there Sometimes only part of the method suffers from envy so in that case you can use Extract Method on the jealous bit and Move Method to get it home There are several patterns that break this rule Strategy (Gang of Four) Visitor (Gang of Four) Self Delegation (Beck)

43 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 43 | 25 Data Clumps Often you will see the same three or four data items together in lots of places: Fields in a couple of classes Parameters in many method signatures Bunches of data that hang around together really ought to be made into their own object The first step is to look for where the clumps appear as fiels and use Extract Class to turn the clumps into an object For method parameters use Introduce Parameter Object or Preserve Whole Object to slim them down

44 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 44 | 25 Primitive Obsession Java has primitives for numbers, but strings and dates, which are primitives in many environment, are classes People new to objects are sometimes reluctant to use small objects for small tasks, such as money classes that combine numbers and currency ranges with an upper and lower, and special strings such as telephone numbers and ZIP codes You can use Replace Data Value with Object on individual data values If the data value has a type code, use Replace Type Code with Class if the value does not effect the behavior If you have conditional that depend on the type code use Replace Type Code with Subclass or Replace Type Code with State/Strategy

45 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 45 | 25 Switch Statements Most times when you see a switch statement you should consider polymorphism Use Extract Method to extract the switch statement and then Move Method to get it into the class where the polymorphism is needed If you only have a few case that effect a single method then polymorphism is overkill. In this case Replace Parameter with Explicit Methods is a good option If one of your conditional cases is null, try Introduce Null Object

46 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 46 | 25 Parallel Inheritance Hierarchies Is really a special case of shotgun surgery In this case every time you make a subclass of one class, you have to make a subclass of another The general strategy for eliminating the duplication is to make sure that instances of one hierarchy refer to instance of another If you use Move Method and Move Field, the hierarchy on the referring class disappears

47 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 47 | 25 Lazy Class Each class you create costs money and time to maintain and understand A class that is not carrying its weight should be eliminated If you have subclasses that are not doing enough try to use Collapse Hierarchy and nearly useless components should be subjected to Inline Class

48 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 48 | 25 Speculative Generality You get this smell when someone says "I think we need the ability to do this someday" and you need all sorts of hooks and special cases to handle things that are not required This smell is easily detected when the only users of a class or method are test cases If you have abstract classes that are not doing enough then use Collapse Hierarchy Unnecessary delegation can be removed with Inline Class Methods with unused parameters should be subject to Remove Parameter Methods named with odd abstract names should be repaired with Rename Method

49 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 49 | 25 Temporary Field Sometimes you will see an object in which an instance variable is set only in certain circumstances This can make the code difficult to understand because we usually expect an object to use all of its variables Use Extract Class to create a home for these orphan variables by putting all the code that uses the variable into the component You can also eliminate conditional code by using Introduce Null Object to create an alternative component for when the variables are not valid

50 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 50 | 25 Message Chains Message chains occur when you see a client that asks one object for another object, which the client then asks for yet another object, which the client then asks for yet another object, etc. This smell may appear as a long line of getThis methods, or as a sequence of temps Navigating this way means the client is structured to the structure of the navigation The move to use in this case is Hide Delegate at various points in the chain

51 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 51 | 25 Middle Man One the major features of Objects is encapsulation Encapsulation often comes with delegation Sometimes delegation can go to far For example if you find half the methods are delegated to another class it might be time to use Remove Middle Man and talk to the object that really knows what is going on If only a few methods are not doing much, use Inline Method to inline them into the caller If there is additional behavior, you can use Replace Delegation with Inheritance to turn the middle man into a subclass of the real object

52 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 52 | 25 Inappropriate Intimacy Sometimes classes become far too intimate and spend too much time in each other's private parts Use Move Method and Move Field to separate the pieces to reduce the intimacy If the classes do have common interests, use Extract Class to put the commonality in a safe place or use Hide Delegate to let another class act as a go- between

53 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 53 | 25 Alternative Classes With Different Interfaces. Most of the time you can use Rename Method on any methods that do the same thing but have different signatures for what they do If this does not go far enough that means the classes are not yet doing enough so keep using Move Method to move behavior to other classes until the protocols are the same If you have to redundantly move code to accomplish this, you may be able to use Extract Superclass

54 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 54 | 25 Incomplete Library Class Library builders have a tough job The problem is that if the library is insufficient for your needs it is usually impossible to modify a library class to do something that you would like it to do If there are just a couple of methods that you wish the library class had, use Introduce Foreign Method If there is more extra behavior you need, use Introduce Local Extension

55 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 55 | 25 Data Class Classes that have fields, getting and setting methods, And nothing else Such classes are dumb data holders If in a previous life the classes were public fields, apply Encapsulate Field

56 Leiden University. The university to discover. Leiden University. The university to discover. “Software Engineering” (B.Sc. Computer Science / Fall 2011) 56 | 25 Refactoring Catalog Each refactoring is described in a particular way: Each refactoring is given a specific Name. A short summary is given in which situation you need to refactor to achieve a better result. More indepth discussion on the motivation The mechanics of how to perform the refactoring. (process in steps) Worked out example


Download ppt "Leiden University. The university to discover. Leiden University. The university to discover. Leiden University. The university to discover. Software Engineering."

Similar presentations


Ads by Google