DRY 11: DRY—Don’t Repeat Yourself • Every piece of knowledge should have a single, unambiguous, authoritative representation within a system • Duplication is evil! • Why? – Things change – If you have the same thing in several places, when you change one, you have to change all the others – And you can’t always find them all! What not to duplicate • Data – If you represent the same data in two places (or in two ways), you have just taken on the job of keeping the two representations in agreement • Code – If you code the same task in two places (or in two ways), you have just taken on the job of keeping the two code segments in agreement How duplication arises • Same information must be represented in many ways, or in several places • Required by documentation standards • Required by the language • As a result of bad design • Taking shortcuts • Poor communication among team members Multiple copies of data • Sometimes the same information must be stored in two places (say, a client and a server) • Sometimes you need the same information in two different programming languages • Best solution: Have one authoritative repository, and generate all the needed copies from it – Remember, programs can create code Example • Suppose you must have a table of numbers in your program, and also in a document – Solution #1: Add code to your program to write out the table in a form you can use in the document – Solution #2: Same as #1, but hot link to the table from your document (if possible) – Solution #3: Write a program that takes the table from the document and produces code you can insert into your program – Solution #4: Keep the master table in a separate place, and generate both the program and the document Documentation standards • Comments should not repeat code – They should add higher-level information—what the code is doing, and why, but not how it does it • If code requires explanation, it’s bad code—fix it! • Your documentation should agree with your code – Untrustworthy comments are worse than none – This is much easier if your comments are high level – This is why javadoc is so wonderful—it’s always correct! Language requirements • Some languages, such as Ada, require you to duplicate information – Ada has: • An interface part, where you provide all the function headers • An implementation part, where you provide all the functions (with the same headers) – The advantage is that it forces you to hide the implementation from the users – The disadvantage is that you need the identical information in two places • There’s not much you can do about this Bad design • A Truck has a capacity, a license number, and a driver • A DeliveryRoute has a route, a Truck, and a driver • One of our drivers calls in sick and we need to change drivers – Where do we change this information? – Solution: Refactor (redesign) the program! Copy-paste programming • Suppose, as you are coding, you find you need to do the same thing as you did somewhere else – So you take this shortcut: you copy and paste code • Later you find you need to do almost the same thing again – So you copy the code, paste it in, and adjust it • Later still, you find you need to change that code – Which copies are the same, and which almost the same? • Never take a shortcut when you’re in a hurry! How to avoid copy-paste • Often the best solution is to write a method – Call the method whenever you want to perform the computation – There is nothing wrong with short methods • If you want to do almost the same thing, parameterize (add parameters to) the method Duplication for efficiency • Suppose you have this class: class Point { double x, y; ... } • And you discover that some of your users want to have polar coordinates (ρ and θ) • You can’t discard x and y, because the class is already in use • So you end up with double x, y, rho, theta; • Now what if a user changes, say, x? Meyer’s Uniform Access Principle • • Bertrand Meyer: “All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.” Translation into Java: 1. Make your variables private 2. Use getters and setters Redoing the Point example, I • Suppose you had started with: class Point { private double x, y; void setX(double x) { this.x = x; } void setY(double y) { this.y = y; } double getX() { return x; } double getY() { return y; } } • Does this help solve the problem? Redoing the Point example, II • To add ρ and θ: – Do not add fields rho and theta; instead, do double getRho() { return Math.sqrt(x*x + y*y); } double getTheta() { return Math.acos(x / rho); } void setRho(double rho) { x = rho * Math.cos(theta); y = rho * Math.sin(theta); } void setTheta(double theta) { x = rho * Math.cos(theta); y = rho * Math.sin(theta); } – Is there anything else that needs to be done? – Can you think of another way to do this? Poor communication • Different team members might implement the same functionality • How do we avoid this? – Good communication! • • • • Exchange ideas with co-workers Read your co-workers code Let others read your code Have code walkthroughs – Have a clear design – Have a strong technical project leader – Have a clearly understood division of responsibilities 12: Make it easy to reuse • Your co-workers won’t use your code unless: – They know about it – It’s easy to access – It’s easier to use your code than to write their own version of the same thing • You won’t even reuse it yourself unless: – It’s easy to use – It’s general enough to support reuse Summary • DRY—Don’t repeat yourself! – This principle is so important that I’ve given almost an entire set of slides to it • Make it easy to reuse The End