150 likes | 155 Views
Learn the principles of designing straight-line code, such as making dependencies obvious through passing arguments and return values, and grouping related items for better organization.
E N D
Principles of straight-line code • Make dependences obvious: (e.g., through passing arguments, return values) firstResult = doThing1(); secondResult = doThingY(firstResult); • Vs. doThing1(); doThingY();
Grouping related items (example) • Ordering implicit, but emphasizes grouping MarketingDatamarketingData = new MarketingData(); marketingData.ComputeQuarterly(); marketingData.ComputeAnnual(); marketingData.Print(); SalesDatasalesData = new SalesData(); salesData.ComputeQuarterly(); salesData.ComputeAnnual(); salesData.Print();
Which is better? This code takes an array of strings, it processes all of the strings before a dash one way and all of the remaining strings another way. Assume there is only one dash in the array of strings. A booleandashFound = false;for (String arg : args) { if (arg.equals("-")) {dashFound = true; } else if (!dashFound) { process1(arg); } else { process2(arg); }} C Control flow is fine for both D Control flow is problematic for both B inti = 0;while(i < args.length && !args[i].equals("-")) { process1(args[i]);i++;}i++; // skip the dashfor( ; i < args.length ; i++) { process2(args[i]);}
Which is better? A public int[] copyIntArray(int[] input) {int [] copy = new int[input.length];inti = 0; for (int value: input) { copy[i++] = value; } return copy;} C Control flow is fine for both D Control flow is problematic for both B public int[] copyIntArray(int[] input) {int [] copy = new int[input.length];for (inti = 0; i < input.length; i++) { copy[i] = input[i]; } return copy;}
Which is best? A if (getAmountOfGasInTank() >= gasNeeded(destination)) { // avoid unnecessary stops; reduce wear on engine } else { fillGasTank(); } if (getAmountOfGasInTank() < gasNeeded(destination)) { fillGasTank(); } else { // avoid unnecessary stops; reduce wear on engine } B if (gasNeeded(destination) < getAmountOfGasInTank()) { // avoid unnecessary stops; reduce wear on engine } else { fillGasTank(); } C if (gasNeeded(destination) >= getAmountOfGasInTank()) { fillGasTank(); } else { // avoid unnecessary stops; reduce wear on engine } D
Design is hard • Design is an art, not a science • Large/infinite design space, not enumerable • Requirements, constraints, trade-offs, and priorities • You get better with practice / experience / seeing good design / hearing critiques of others designs
Virtues of a good design (software) • Manages complexity • Loose coupling • Reusability • Ease of maintenance • Standard techniques • Extensibility • High Fan-in • Low-to-medium Fan-out
Good Design Manages Complexity • “Seven plus or minus two” (Miller’s Law) • The goal of all software-design techniques • Break complicated problems into simple problems • Separation of concerns • Focus on one at a time
Keep Coupling Loose • small interfaces (few methods, few arguments/method) • obvious (interactions through parameter passing) • flexible
Abstract Data Types • Define a class based around conceptual structures • Encapsulation / information-hiding • Make interfaces more informative (self-documenting) • Easier to reason about correctness • Treat even simple items as ADTs • Good for extensibility
Inheritance can provides 2 things • Shared interface: • Public methods • Ensure methods have consistent meaning in derived class • Liskov Substitution Principle • Shared implementation • Code in shared super class, not replicated in each derived • Could be private data/methods
hasA vs. isA relationship Which is a candidate for inheritance? A) hasA relationship B) isA relationship C) both hasA and isA relationships D) neither hasA and isA relationships
Inheritance vs. Interfaces • Inheritance should be a isA relationship • Interfaces are for capabilities (“mixin”s)
Designing Good Interfaces • Sufficiently Expressive • General • Minimal