//****************************************************************************//
//*********** Evaluating Good Designs - November 10th, 2017 *****************//
//**************************************************************************//

- So, we'll wrap up the SOLID principles today, and then we'll move on to our final, broader topic: how do we decide if one design is better than another?

- So, we were talking about the Interface Segregation Principle
    - We had the example of an online Go game that had 3 different types of clients that could connect: the PlayerClient, the ChatClient, and CommentatorClient
        - Instead of having ALL of these depend on an "IClient" interface, we instead break the specifics into a separate interface for each client type
            - "Otherwise, if we put them ALL in one interface, we'd have to implement the 'SendPlayerMove()' method or whatever on ALL of these clients, even though they'd never use them"
        - Another example from Uncle Bob: let's say that we're building a "secret door" like from all those cheesy spy movies, and we want the door to sound an alarm if it's open for too long
            - So, we have a "TimedDoor" interface...but what if we just want to make a regular door? Then we would have to include a time too! 

- "Now, when should we use abstract classes and when should we use interfaces? Well, in some languages it doesn't matter; they're basically identical, or they only have one of the two. In Java, though, there are some key differences:"
    - Abstract classes can have implemented methods (technically Java 8 let's you put some code in interfaces, but meh)
    - Classes can use multiple interfaces vs just one abstract class
    - ALL methods in an interface MUST be implemented, but we can have non-abstract methods on an abstract class that classes are NOT required to implement
        - "This is suprisingly useful for backwards compatability - if you change your interface in your super-popular game engine and suddenly everyone's code breaks because they didn't implement the 'drawSprite()' method, that's gonna be a problem"
- In general, a lot of times the choice of interface vs abstract is just up to us - it doesn't make too much of a difference - but in certain situations, ESPECIALLY if other people's code is depending on ours, the choice can be critical

- Classes vs attributes
    - Basically, should our attributes be a primitive or a class?
    - "Well, like so many things in design, it depends...but BEWARE of primitive obsession, where you try to do EVERTHING with primitives"
        - Take the example of a "balance" variable in your Accounting class...wouldn't it be better to have this as a separate "Money" class, so we can do currency conversions, instead of just having it be a double that means...something?

- Determining a good design
    - "In 3312, one of the things students ALWAYS do is plop down a couple different designs on my desk and say 'Professor, is this a good design?'"
    - Example interview questions I've heard that deal with design:
        - What is good vs bad design?
        - What are some tradeoffs involved with software features?
        - Design an ATM for children.
- "So, what makes one design better than another?"
    - It has NOTHING to do with functionality, if it "gets the job done" - "as I'm sure you know, you can have an absolute mess of code and still have it work fine from the user's perspective"
        - Several studies have show that 50-80% of long-term software costs are related to dealing with maintenance
    - One way to assess it is an acronym called FURPS - "Functionality/Traceability", "Usability", "Reliability", "Performance", "Security/Sustainablity"
        - A quick note on performance: "premature optimization is the root of all evil!" You should optimize when you NEED it, not just "because you can"
        - More on this in Chpt 7.4 in Larman
    - One thing that we need to worry about is something called TRACEABILITY
        - Two big problems in all software projects:
            - Feature Creep
                - Usually caused by the customer asking for extra design features they didn't originally ask for
                - "If you keep adding small features to your app here and there that you didn't originally plan for, your project deadline can get out of control"
            - Gold Plating
                - "Ya know, this Rat Report loading is a little boring - I'll add a 3D rat dancing in the background as a loading screen"
                - Adding stuff that you didn't originally plan costs money to test and verify, so DON'T let your dev team run away with these sort of things
                    - "Easter eggs are a common example of these sort of things"
        - Traceability means for EVERY FEATURE we have in the app, we write out all our design requirements and say "what requirements does this help cover"?
            - If a feature doesn't help cover any requirements, or pitifully few, we should consider cutting it
    - On SAFETY - Nancy Leveson at MIT wrote a FANTASTIC book and did some awesome lectures on this, so look at that if you're interested in software safety
        - "Sadly, at Tech, the closest thing we have to software safety classes is sneaking into the ISYE building"
- We can also evaluate design based on a number of different QUALITY FACTORS:
    - Maintainability 
    - Testability 
    - Reliability ("the mean time between failure") 
    - Availability ("does our design have to be up 24 hours a day, or can it be taken down for maintenance on Sundays?") 
    - Precision/Accuracy (how many decimal places do we need; are our computations correct to an acceptable degree of error?)
        - (A story about this) - in the Cold War, we had Patriot missile defense systems, which were designed to be taken up and down every few days to be relocated due to the threat of bombers. But in the Gulf War, since there was no threat of Soviet bomber planes or anything like that, these missile defense systems were just left at the camp for weeks on end. Well, it turns out that there was tiny error in the software where the radar would drift 0.000000095 degrees off every 0.1 second - an acceptable error for its orginal setup-takedown purpose, but COMPLETELY unacceptable when we left it running for weeks on end. The end result: a missile came towards a camp, all the Patriot defense systems missed, and 25 people were killed/wounded
    - Security
    - Performance
    - Extensibility (how easy is it to add new features?)
    - Portability ("Can it also run on iPhone and Android?")
    - Usability
    - Interoperability (can we talk to other systems, e.g. pulling data from New York's rat report servers?)
    - etc.

- So, next time, we'll talk about how you can use these principles to do a design review of your program, and assess if the design is good or bad