1 / 34

Introduction

Introduction. Advanced OOP CS 440/540 Spring 2014 Kenneth Chiu. Requirements. What are they? What kinds are there? Functionality Performance Platform/dependencies How are they specified? API Documentation Input files, output files Performance metrics. Design. What is a good design?

garvey
Download Presentation

Introduction

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction Advanced OOPCS 440/540Spring 2014Kenneth Chiu

  2. Requirements • What are they? What kinds are there? • Functionality • Performance • Platform/dependencies • How are they specified? • API • Documentation • Input files, output files • Performance metrics

  3. Design • What is a good design? • What is a bad design? • What makes one design better or worse than another? • Faster • Easier to understand • Easier to modify • Is sometimes a slower executing design better than a faster executing design? • Can we objectively measure how good a design is?

  4. Why Is Software Complex? • The problem itself is complex. • Difficulty of managing the process. • Two different teams may not be completely in sync on the way that two pieces of code interact, leading to complexity. • The flexibility of software. • Creeping featurism. • Changing requirements. • The world itself changes. • Which changes the requirements. But the world does not change all at once in a predictable way, so usually changes are handled incrementally. • What’s wrong with incremental changes? • Why not design it right in the first place? • “Accidental” vs. essential • Accidental: Interface not quite right might require an adaptor. • Essential: Problem domain is complex.

  5. Managing Complexity • This course is about managing complexity. • Once you get beyond the basics, that’s what programming is about. • Have you ever said: “I didn’t have time to make it simpler.” • It’s hard to make things simple. • Can we eliminate complexity? • What strategies can we use to manage complexity? • Complexity should be localized as much as possible. • This helps lead to the things we think of as a good design. • How is an airplane structured? • Decomposition, but how? • Algorithmic • OO

  6. Code Reuse • Why is code reuse good? • How does it help us manage complexity? • What’s wrong with copy-and-paste? • It concentrates (localizes) complexity. • How do we get code reuse? • Parameterization is crucial.

  7. How do we get code reuse? • i = j*a + j*b;…i = j*a + j*b; • i = f(j, a, b);…i = f(j, a, b); • #define xyzzy() i = j*a + j*bxyzzy();…xyzzy();#undefxyzzy

  8. How do we get code reuse? • for (inti = 0; i < 10; i++) { // Code fragment using three // variables. // …}// …for (inti = 0; i < 100; i++) { // Same code fragment. // …} • loop(10, /* Pass variables */);…loop(100, /* Pass variables */);

  9. Consider a case like this. How do we get code reuse? • bool less(inti, int j) { return i < j;}bool greater(inti, int j) { return i > j;}void doit(int op1, int op2,bool (*cmp)(int, int)) {// … (Fragment A) if ((*cmp)(op1, op2)) { // … (Fragment B) } // … (Fragment C)}// …doit(i, j, &less);doit(k, l, &greater); • // … (Fragment A)if (i < j) { // … (Fragment B)}// … (Fragment C)// … (Fragment A, repeated)if (k > l) { // … (Fragment B, repeated)}// … (Fragment C, repeated)

  10. Another way: • fragA();if (i < j) {fragB();}fragC();// …fragA();if (k > l) {fragB();}fragC(); • // … (Fragment A)if (i < j) { // … (Fragment B)}// … (Fragment C)// … (Fragment A, repeated)if (k > l) { // … (Fragment B, repeated)}// … (Fragment C, repeated) • What if the fragments need access to local variables?

  11. We can pass those as parameters. • fragA(&i, j, k, &l);if (i < j) {fragB(a, b, &c);}fragC(&x, &y);// …fragA(&i, j, k, &l);if (k > l) {fragB(a, b, &c);}fragC(&x, &y);

  12. Or, in the case where we factored out the comparison function: • bool less(inti, int j) { return i < j; }bool greater(inti, int j) { return i > j; }void doit(int&i, int &j, int &k,double &x, double &y,int&a, int &b, int &c,int op1, int op2, bool(*cmp)(int, int)) { // … (Fragment A if ((*cmp)(op1, op2)) { // … (Fragment B } // … (Fragment C}// …doit(i, j, i, j, k, l, x, y, a, b, c, less);doit(k, l, i, j, k, l, x, y, a, b, c, greater);

  13. Can wrap the parameters in an object. • inti, j;double x, y;int a, b, c;struct Helper { Helper(int &i_, int &j_, int &k_, int &l_, double &x_, double &y_,int &a_, int &b_, int &c_) : i(i_), j(j_), k(k_), x(x_), y(x_), a(a_), b(b_), c(b_) {}int &i, &j; double &x, &y;int &a, &b, &c; void fragA() { /* … */ } void fragB() { /* … */ } void fragC() { /* … */ }} h(i, j, k, l, x, y, a, b, c);

  14. It’s usually a bit cleaner looking and concise to just put the variables inside the struct. • struct {inti, j, k; double x, y;inta, b, c; void fragA() { /* … */ } void fragB() { /* … */ } void fragC() { /* … */ }} h;h.i = 0; h.j = 0; h.k = 0;h.x = 3.14; h.y = 2.2;h.a = 2; h.b = 3; h.c = 5; • h.fragA();if (h.i< h.j) {h.fragB();}h.fragC();// …h.fragA();if (h.k> l) {h.fragB();}hlp.fragC();

  15. So now, rather than this: • fragA(&i, j, k, &l);if (i < j) {fragB(a, b, &c);}fragC(&x, &y);// …fragA(&i, j, k, &l);if (k > l) {fragB(a, b, &c);}fragC(&x, &y); • We have this: • h.fragA();if (i < j) {h.fragB();}h.fragC();// …h.fragA();if (k > l) {h.fragB();}hlp.fragC();

  16. Rather than passing local variables to helper functions, or storing them in helper objects, we can use a lambda (C++11) to automatically capture them. • std::function<bool()> ij_less = [&]() { return i < j; };std::function<bool()> kl_greater = [&]() { return k > l; };auto doit = [&](std::function<bool()> &cmp) { // ... (Fragment A) if (cmp()) { // ... (Fragment B) } // ... (Fragment C)};doit(ij_less);doit(kl_greater); • doit([&]() { return i < j; });doit([&]() { return k > l; });

  17. We can also use lambdas if we want to turn the fragments into functions. • auto fragA= [&]() { /* … */ };auto fragB= [&]() { /* … */ };auto fragC= [&]() { /* … */ };fragA();if (i < j) { fragB(); }fragC();fragA();if (k > l) { frag B(); }fragC();

  18. Probably the nicest way is to use lambda’s just for the comparisons: • for (auto cmp: std::vector<std::function<bool()>>{ [&]() { return i < j; }, [&]() { return k < l; }, }) { // … (Fragment A) if (cmp()) { // … (Fragment B) } // … (Fragment C)}

  19. We can also just use a macro. • #define xyzzy_doit(op1, op2, cmp) \/* … (Fragment A) */ \if (op1 cmp op2) { \/* … (Fragment B) */ \} \/* … (Fragment C) */ • xyzzy_doit(i, j, <)xyzzy_doit(k, l, >) • Why the funny prefix? • This is actually pretty clean looking. What’s the downside?

  20. Hierarchy • What is it? • A ranking of abstractions. Example? • Employee, manager. • Why? • Maximizes other reuse, improves abstractions. • If we just had Under and Grad, there would be no way to write code that didn’t care about the difference.

  21. Example • A hierarchy for dishes. • By country? • By style? • By content? • Often no one best hierarchy, without considering use cases. • MI can help resolve conflicting use cases.

  22. Two kinds of hierarchy • Consider: • An engine is part of a truck. • A diesel engine is a kind of engine. • First is considered part-of, second is considered is-a. • What do they correspond to? • Object hierarchies • Class hierarchies • So, can you have an object hierarchy without a class hierarchy? How about a class hierarchy without an object hierarchy? • These two hierarchies are orthogonal.

  23. Nature of an Object • What is an object, in OOP? • What is or is not an object? • red? • airplanes? • processes? • Figuring these out is part of analysis phase. • What qualities should objects have? • Abstraction • Encapsulation • Modularity • Hierarchy

  24. When to Make Things a Separate Class • A checking account: • Has a monthly fee. • Does not pay interest. • A savings account: • Has no monthly fee. • Pays monthly interest. • Should we make these separate classes?

  25. To design, first figure out what the operations are on your objects and what state they should have. • Then figure out how to abstract/encapsulate. Is there a cost to encapsulation? • Could you do OOP before C++/Java? • Objects are the fundamental building blocks, not algorithms.

  26. Summary of Classification/Hierarchies • Given any domain (such as dishes), there are many different ways to classify/organize the entities. • In code, we can only have a single class organization. • So we have to pick something. • MI can be used to alleviate. • Other aspects have to implicit, rather than explicit. • Or sometimes can be represented in the object hierarchy.

  27. Abstraction • What is it? • Abstraction is usually performed over a set of similar classes. • Abstraction is simplifying things. • What’s the minimal set of public state and operations that your objects (conforming to the same interface) need to provide to the rest of your code? • Principle of least commitment. • Abstractions should be minimal.

  28. Abstraction is more than just creating a list of operations. • Sometimes there are multiple ways to represent the same thing. • What’s the abstraction of a 2-D point? • class Point {get_x();get_y();set_x(x);set_y(y);}; • class Point {get_theta();get_r();set_theta(t);set_r(r);} • How do we solve this? • Represent internally in one of these. Provide all methods. But if we pick the wrong internal representation, then there will be a high conversion cost. • Consider these to be two different abstractions. Pick one of them. • Some things are “too abstract” to hope for a computer representation that is ideal.

  29. Encapsulation • What is it? • Hiding the implementation or other details. • Is there a difference between abstraction and encapsulation? • Can you abstract without encapsulating? • Can you encapsulate without abstracting? • Flip sides of the same coin.

  30. Waterfall Model • Requirements • Analysis • Design • Implementation

  31. Iterative Development • Give up trying to get the design right from the beginning. • Instead, accept that it’s going to take multiple iterations, and try to make streamline that process.

  32. Defensive Programming • Most programs are riddled with bugs. • Most bugs (like cockroaches) are hidden, unrevealed. • When long-hidden bugs show themselves, they are hard to exterminate. Why? • Place where bug shows itself is far removed from where bug actually occurs. • The bug was actually put into the code a long time ago. • Moral: Exterminating bugs is easiest when you catch them in their nest, and when you catch them early. • The purpose of defensive programming is to force bugs to show themselves as early as possible, and as close to the origin of the bug as possible. • Think about what programmers using your code might do, long after you wrote the code. • They may interpret things slightly differently, and use or modify your code in the wrong way. • Try to force such bugs to reveal themselves early and quickly.

  33. Robustness • What does “robust” mean? • You can have source robustness. • Portable • Likely to catch errors that other programmers do. • Is this robust? • class String { public: String(const char *s) : str(strdup(s)) { } ~String() { free(str); } private: const char *const str;}; • You can have run-time robustness. • Likely to respond well to abnormal conditions. • Example conditions?

  34. Let’s say that you are writing a 100 line program. • One of the functions has a potential problem, but you estimate that the chance of it happening is only 1 in 1,000,000 every time the program is run. • You figure it’s okay to ignore. • Good idea? • If there are 10,000 such functions, the probably of failure becomes 1 out of 100.

More Related