Software Engineering

12
1 Software engineering is the systematic, disciplined, quantifiable approach to developing software. Process Models Generally consists of four steps o Requirements, Design, Implementation, Testing Relative amount of time spent on each step The roles of individuals/organizations in each step The input required to process into a step The output that the step produces Whether there is iteration between steps Waterfall Model o Requirements -> Design -> Implementation -> Testing Rational Unified Process (RUP) o Inception -> Elaboration -> Construction -> Transition o Emphasis on Business Modelling and Requirements during Inception o Continued emphasis on Business Modelling and Requirement in Elaboration; Increased emphasis on Analysis & Design during Elaboration o Focus on Implementation during Construction o Test before, during, and after Construction o Deployment after Construction o Unified Modeling Language o Problems: similar to the Waterfall Model, RUPs suffer from long iterations and involve complicated requirements and design phases (UMLs take much longer to develop than User Stories) Android Views are visible components in the UI o Android passes a Canvas object to onDraw (in the view class) onDraw is called when View is displayed Placing the View in the Activity requires passing an instance of the view to setContentView or putting it in the XML file When the user interacts with the View, Android invokes its onTouchEvent method (which gets passed a MotionEvent object) Threads o Separate (concurrent) “lines of execution” that allow programs to do two or more things at the same time o Android will show an ANR error if a View does not return from handling an event within 5 seconds, or if some code running in the main thread prohibits UI events from being handled Any long-running code should run in a background thread (which cannot modify UI elements) o To start a new thread, call execute() from a class that extends AsyncTask execute() runs: onPreExecute() in the main (UI) thread doInBackground() in the background thread onPostExecute() in the main (UI) thread Multiple Activities o When new Activities are started, Intent objects are created and passed to that Activity The Intent object contains info about what the Activity is meant to do, as well as any data it needs to do it When the Launcher starts an app, it looks for the Activity with the “MAIN” action o To start a new Activity: Create an Intent object with a reference to Context (this) and the Class that represents the new Activity Add any key/value pairs to the Intent’s Bundle by calling putExtra Call startActivity or startActivityForResult and pass the intent and the request code(int) o To finish an Activity: Create an Intent object (empty constructor) Call putExtra with key/value pairs or putExtras with a Bundle object (where key/val pairs were set with putString) Call setResult with the result code (usually either RESULT_OK or RESULT_CANCELED) and the Intent Call finish() o To return from an Activity: onActivityResult is called in the calling Activity, with the request code, result code, and Intent object as parameters Use request code to figure out which Activity it is that’s returning (in case you created more than one) Use Intent object to get back any return values o Activities should be as self-contained as possible (responsible for its own persistence, instead of passing data along to the caller Activity) Agile Software Development Scrum, Kanban, Lean Software Development, Extreme Programming (XP) Focuses on self-organization and motivation instead of processes and tools

description

A comprehensive overview of the paradigms in software engineering today.

Transcript of Software Engineering

  • 1

    Software engineering is the systematic, disciplined, quantifiable approach to developing software.

    Process Models

    Generally consists of four steps

    o Requirements, Design, Implementation, Testing

    Relative amount of time spent on each step

    The roles of individuals/organizations in each step

    The input required to process into a step

    The output that the step produces

    Whether there is iteration between steps

    Waterfall Model

    o Requirements -> Design -> Implementation -> Testing

    Rational Unified Process (RUP)

    o Inception -> Elaboration -> Construction -> Transition

    o Emphasis on Business Modelling and Requirements during Inception

    o Continued emphasis on Business Modelling and Requirement in Elaboration; Increased emphasis on Analysis & Design during Elaboration

    o Focus on Implementation during Construction

    o Test before, during, and after Construction

    o Deployment after Construction

    o Unified Modeling Language

    o Problems: similar to the Waterfall Model, RUPs suffer from long iterations and involve complicated requirements and design phases (UMLs take much

    longer to develop than User Stories)

    Android

    Views are visible components in the UI

    o Android passes a Canvas object to onDraw (in the view class)

    onDraw is called when View is displayed

    Placing the View in the Activity requires passing an instance of the view to setContentView or putting it in the XML file

    When the user interacts with the View, Android invokes its onTouchEvent method (which gets passed a MotionEvent object)

    Threads

    o Separate (concurrent) lines of execution that allow programs to do two or more things at the same time

    o Android will show an ANR error if a View does not return from handling an event within 5 seconds, or if some code running in the main thread prohibits

    UI events from being handled

    Any long-running code should run in a background thread (which cannot modify UI elements)

    o To start a new thread, call execute() from a class that extends AsyncTask

    execute() runs:

    onPreExecute() in the main (UI) thread

    doInBackground() in the background thread

    onPostExecute() in the main (UI) thread

    Multiple Activities

    o When new Activities are started, Intent objects are created and passed to that Activity

    The Intent object contains info about what the Activity is meant to do, as well as any data it needs to do it

    When the Launcher starts an app, it looks for the Activity with the MAIN action

    o To start a new Activity:

    Create an Intent object with a reference to Context (this) and the Class that represents the new Activity

    Add any key/value pairs to the Intents Bundle by calling putExtra

    Call startActivity or startActivityForResult and pass the intent and the request code(int)

    o To finish an Activity:

    Create an Intent object (empty constructor)

    Call putExtra with key/value pairs or putExtras with a Bundle object (where key/val pairs were set with putString)

    Call setResult with the result code (usually either RESULT_OK or RESULT_CANCELED) and the Intent

    Call finish()

    o To return from an Activity:

    onActivityResult is called in the calling Activity, with the request code, result code, and Intent object as parameters

    Use request code to figure out which Activity it is thats returning (in case you created more than one)

    Use Intent object to get back any return values

    o Activities should be as self-contained as possible (responsible for its own persistence, instead of passing data along to the caller Activity)

    Agile Software Development

    Scrum, Kanban, Lean Software Development, Extreme Programming (XP)

    Focuses on self-organization and motivation instead of processes and tools

  • 2

    Relies on frequent, small, functional releases instead of comprehensive documentation

    Relies on customer collaboration instead of contract negotiation

    Uses quick responses to change and constant evaluation of processes instead of a plan

    Customer satisfaction is the highest priority

    Changing requirements are expected

    Test-driven development

    Frequent delivery of software

    Close cooperation between business people and developers

    Progress is measured by working software

    Sustainable development pace

    Do the simplest thing that works

    Regular reflection and adaptation

    Relies on User Stories

    o Simple descriptions of functionality that specify the who, what, and why of the requirement

    o See Documenting Requirements

    o If a task is not related to users, it is known as an engineering task

    Uses Points

    o Indication of effort needed to complete a user story

    o Velocity number of points completed per unit time

    o Important to choose a realistic velocity for each iteration (defined during each Iteration Planning Meeting)

    o Do not try to make up for lost velocity

    Extreme Programming (XP)

    o

    o o Instead of Analyzing, Designing, Coding, then Testing the entire application, work on the most important features first

    Software Configuration Management (SCM)

    o Identification, version control, change control (tracking changes to software configuration items), auditing, reporting

    o Quality control for software development

    1) Share everything (use SCM repository)

    Centralized location for all Software Configuration Items (SCIs), including code, documentation, requirements, tests, and project

    plans

    Versioning, Auditing, Dependency, Tracking (relationships between any software configuration items in that one depends on

    another. For instance, a requirement may depend on another requirement being satisfied/implemented first. A piece of code may

    depend on another being implemented first), Requirements Tracking (changes, ownership, completion status; PivotalTracker) ,

    Security

  • 3

    2) Put things back where you found them (check in code regularly)

    3) Flush (use continuous integration)

    All code is compiled as soon as it is checked in

    4) Clean up your own mess (dont break the build)

    Dont check in code that doesnt compile or pass its own tests

    Maintain visibility

    5) Wash your hands before you eat

    Use test-driven development

    Write unit tests before you implement the method

    Requirements

    High-level requirements (business requirements) generally define why the system is being built

    Low-level requirements (detailed requirements) specify how the high-level requirements will be achieved and describe what the system will do

    Gathered via interviews with the customers

    o Use close-ended, specific detailed questions

    o Use open-ended questions to allow the customer to speak freely and explore possibilities

    o Use scenarios to let the customer talk through a sequence of steps/interactions with the system

    o Use probing to force the customer to think about the justification for each requirement

    Requirements are hard to capture because people change their minds, needs change, stakeholders dont always reach consensus, hard to focus on what not

    how, people do not always say what they mean

    Documenting requirements

    o Unstructured Free-form Text

    Paragraphs of prose in which the customer describes what he wants

    Difficult to measure progress, break the requirements into subtasks, elaborate upon details

    o User Stories

    Each requirement specified in a few short sentences, describing the who, what, and why of the requirement

    Written from the users perspective

    Who are the users? What do they know? What can they learn?

    What do they want/need to do? What is their motivation?

    What is the context of using the system?

    What things must/should the machine do instead of the user? What will the user assume the machine will do?

    Discrete, but not necessarily precise

    Estimable: developers can estimate amount of work required

    Traceable: know which parts of the system satisfy a requirement

    Testable: know when its done

    Fit into a single interation

    o Use Cases

    More detailed than a user story (includes how to handle error cases, preconditions/assumptions that are made before the functionality can

    be allowed to proceed, postconditions/guarantees that are made after the Use Case is finished)

    Describe inputs (including system state) that are required for the system to perform the task and outputs (including the change of system

    state) that occur as a result of performing the task

    Describe pre-conditions (Assumptions that the system makes in order to perform the task) and post-conditions (thinks that the system

    makes as a result of performing the task)

    Describe error handling

    o Unified Modeling Language Diagrams

    Important component of RUP

    Diagrams explain the structure and behavior of a system

    The behavioral ones are used for specifying functional requirements and describe the flow of data between objects/components, how they

    should communicate, and their various state diagrams.

    Designed to be unambiguous

    Useful when working with off-site teams, but require a lot of up-front work to create

    o Formal Specifications are math-like descriptions that are very detailed, precise, and unambiguous

    Non-functional (quality) requirements and constraints

    o External quality requirements describe reliability, availability, usability, efficiency/performance, security, portability

    o Internal quality requirements describe testability, readability, understandability, modularity

    o Constraints relate to how software should be implemented and describe the accuracy of computations, memory/bandwidth/power usage (resource

    consumption management), tool/platform usage, standards, exception and user error handling

    Requirements Analysis

    o Good requirements are accessible (documents, organized), comprehensive/complete, understandable, unambiguous, consistent (no contradictions),

    testable, traceable, measurable, correct, realistic

  • 4

    Software Architecture

    Monolithic

    o Functionality implemented by part of the system cannot be reused without using the entire system

    o Tight-coupling

    Component-Based

    o Interface is separated from implementation and components are flexible to change

    Client-Server

    Software as a Service

    Service Oriented Architecture

    o An approach that involves creating number of services, where each service provides access to, or exposes, one or more resources via some

    predetermined, agreed mechanism. Services are often, but not always, distributed on a network

    o All teams expose their data and functionality through service interfaces; teams must communicate with each other through these interfaces

    o All service interfaces, without exceptions, must be designed from the ground up to be externalizable; the team must plan and design to be able to

    expose the interface to developers in the outside world

    Model-View-Controller (MVC)

    o Model data storage, integrity, consistency, queries & mutations

    Corresponds to the database some form of data persistence

    Can be a real database like MySQL, PostgreSQL, or an XML file, flat files

    Decouple the data storage and retrieval from the other aspects such as the UI

    UI does not change depending on whether the data comes from an XML file or from an Oracle DB

    Central place to do all the validations such as integrity constraints and null checks

    o View presentation assets and code

    Corresponds to the UI

    o Controller receive, interpret, and validate input; create and update views; query & modify models

    Corresponds to the business logic

    Lets the programmers use any language (no dependencies with the View or the Model Layers), but in practice this is not true

    Design Concepts

    ISO 9126 Software Quality

    o Functionality

    o Reliability

    o Usability

    o Efficiency

    o Portability

    o Maintainability (Internal Quality deals with code itself)

    Analyzability

    Readability can one look at an identifier, distinguish it from other identifiers, and understand its semantic meaning?

    Understandability can one figure out the algorithm a big chunk of code is attempting to implement?

    Changeability

    Code is easy to change in terms of effort (time, number of lines of code affected by a potential change)

    Changes do not affect other code

    Stability

    Is this code affected by changes elsewhere?

    Testability

    How easy is it to test and debug?

    Reusability

    o (Security)

    Separation of Concerns

    o A concern is a feature or behavior that is specified as part of the requirements; should be separated into smaller, more manageable pieces

    Modularity

    o Most common manifestation of separation of concerns, divide software into components/modules that address different pieces of requirements and

    then are integrated together into a complete solution

    o Components may consist of a number of classes

    o Packages are collections of classes

    o Leads to enhanced changeability, stability, testability, understandability (less code to read when trying to understand it)

    o Anti-pattern: The Blob (not enough modularity) one component/module that contains most of the functionality/data and other that are simply

    collections of field

    o Anti-pattern Super-Delegator (functional decomposition, not enough modularity) main method calls a sequence of methods in other classes that

    may only have one method or dont have any relation to each other, use object-oriented principles, and have names that are verbs

    o Anti-pattern Poltergeist (too much modularity) classes that dont seem to do much and may not be necessary, but whose functionality affects other

    classes

  • 5

    Functional Independence

    o Each module addresses a specific subset of requirements and only exposes a simple interface to other modules

    o Deals with changeability and stability

    o Allows for compartmentalization when developing in a team and reuse across projects

    o Cohesion level to which a module depends on itself

    Do all parts of a module rely on all other parts?

    o Coupling level to which a module depends on other modules

    Does on module depend heavily on another?

    Loose coupling when changing one module does not affect the other

    Tight coupling when changing either module affects the other

    o Anti-pattern Spaghetti Code Functionality goes from one component to the next, with each component relying on the other

    Aspects (cross-cutting concerns)

    o Some concerns go across functionality (logging, security, access to a data source)

    These concerns should be separated into their own components, rather than integrated here and there into the others

    o Related to changeability (if I want to change something that is used by all parts of the code, I only need to change it in one place)

    o Aspect-oriented programming aspects are woven into other functions using annotations

    o Anti-pattern - Cut & Paste Programming same code appears in multiple components

    Abstraction and Refinement

    o Abstraction focuses on what not how

    o Abstraction means people can use the functionality without knowing the details

    o Refinement means exposing more details (and control)

    o Improves analyzability

    o Procedural Abstraction refers to a sequence of instructions that a grouped together, but the name of this sequence has a meaningful name that hides

    the implementation details (a methods name should explain what it does, not how it does it)

    o Data abstraction collection of data that is given a name but hides the details

    o Refinement/Elaboration drill down from the general to the specific, where more details are revealed the further down you go

    o Control abstraction if one module depends on another, then one should be able to replace the module on which it depends with any other module

    that satisfies the same interface, including any subclass

    o Someone should be able to read where the method is called and know what it does, without having to go look at code to figure it out

    Information Hiding

    o Information in a module/component is inaccessible to other modules that have no need for it

    o Modules communicate only through exposed channels/interfaces using only the information that is needed, and not all of it

    o Deals with stability and changeability with testability as a tradeoff

    o Private can only be used by that object (and not its subclasses)

    o Protected can be used by that object or object of subclasses

    o Public world-accessible

    o None package-scoped

    o Also includes return types dont return an entire object if only its field is needed

    Object-oriented Design Principles

    o Single-responsibility principle a class should only be responsible for one thing; it should have only one reason to change (cohesion)

    o Open-closed principle open for extension, closed for modification; you should be able to extend it without having to change it

    o Liskov Substitution principle a class should be replaceable with an instance of a subclass; a subclass must honor the semantics of the base class

    o Interface segregating principle methods in an interface should be related to each other (cohesion)

    o Dependency inversion principle high-level modules should not depend on low-level modules, but rather should use abstractions

    Design Patterns

    Five steps for going from a set of requirements to a design of classes (and their fields and methods)

    o Choose the right architecture: MVC is a good place to start

    o Look for data objects by using grammatical parsing

    o Choose the right data structures and use class/libraries/components that already exist

    o Use design patterns where appropriate

    o Refactor as needed: if the design isnt right the first time, fix it until it is

    Design patterns are a general, reusable solutions to commonly occurring problems; they provide descriptions or templates for how to solve a problem that can be

    used in many different solutions

    Creational how objects are instantiated

    o Singleton

    Restricts instantiation of a class to one single object. Thus, the constructor can only be called once, and there is only one instance of the class

    Useful when there is an aspect and we want to ensure that there is only one instance that is shared by all other objects

    Analogous to making the class static, but is preferable to making everything in the class static

    o Factory Method

    Separates the code that uses an object from the code that creates it

  • 6

    Useful when you may need to change the type of object you use, but not necessarily the way in which you use it or when you may need the

    code to be flexible to use multiple types of objects in the same manner

    The factory method is a (abstract) method that is used to create the object that is needed in some class, but it is up to subclass

    implementations to determine the type of object to create

    Dependency Injection use anonymous inner classes (useful when it comes to testing, and adds flexibility to the code)

    The code that creates an object determines its dependency

    Controller c = new Controller() {Reader createReader() {}};

    The above code is an anonymous class that extends Controller and overrides createReader();

    Single controller, many reader example (one-to-many relationship between Controller and Reader classes)

    Structural how objects are composed

    o Bridge

    Many-to-many relationship

    Maintain different independent inheritance hierarchies; bridge connects them

    Many shapes, many renderers example

    Implementor an abstract class or interface that defines methods for how the data is used

    Concrete Implementor class that implements those methods in different manners

    Abstraction an abstract class that represents the data and has an instance of the Implementor as a field which is set in the Abstractions

    constructor (thus bridging the two)

    Refined Abstraction provides additional detail and then uses the Implementor as needed

    Client the user of the abstraction who dictates which Refined Abstraction and which Concrete Implementor to use together when it

    creates objects

    o Decorator

    Solves the problem of needing to anticipate various combinations in advance

    Beverage, ingredient example

    Start off with a base class/interface (component) and extend it using a Decorator class that has a component as one of its fields. For

    subclasses of the Decorator, overridden methods use the Component implementation and also add any other new functionality

    Allows the possibility of extending functionality by decorating the Component at runtime, rather than doing it with custom classes at

    compile-time.

    Favor composition of inheritance (compose objects as you need them, rather than creating big inheritance trees in advance)

    o Composite

    Use when the user (client) of the object doesnt care whether there is a single object or a collection

    Create an interface so that a collection is objects is treated by the client in the same way as a single object

    Shopping item example

    Behavioral how objects communicate

    o Observer (Publish/Subscribe)

    Use when you want one object to send messages to other objects, but you dont know (at compile-time) what those other objects will be,

    and/or the set of objects may change during execution of the program

    Generic and flexible model of connecting objects such that one is the Subject (Publisher or Observable) and is able to send messages to a

    group of Observers (Subscribers or Listeners) without knowing about them at compile-time

    Commonly used in UI libraries such as Java Swing and Android

    Observer, logger example

    o Iterator

    Allows the client code to iterate over a data structure without having to know about how data is represented internally

    The Iterator interface defines methods for iterating over a data structure. Each data structure then implements some interface that allows a

    client to get its Iterator. The different data structure define inner classes that implement the Iterator interface.

    o Strategy

    Seen in the Collections API

    Specify the algorithm (or strategy) to be used for a given task or context

    In Java, this is a replacement for something in which youd use function pointers in C/C++ (we have a basic structure of a task, but some parts

    need to be specified at the time when you run the task)

    Sorting example

    The structure of how you sort is independent of how you compare the elements

  • 7

    Analyzability

    Invariants

    o Something that is expected to always be true at a certain point of the program

    o Program Invariant

    True at arbitrary execution points; these might not be true at other points

    o Class Invariant

    True before and after each (public) method is called

    o Preconditions

    True before a method is called

    o Postconditions

    True after a method is called

    o It is good to consider invariants before starting the implementation

    o Runtime Assertion Checking

    Use the assert keyword

    o Soundness

    How can we know the invariants are right?

    o Completeness

    How can we know that weve identified all the invariants?

    o False Positive: an invariant may be violated even though the software is working correctly

    o False Negative: all invariants may be satisfied, even though the software is not working correctly

    Test Driven Development (TDD)

    o Write tests before code

    o Use TDD because:

    Wont want to write them after the code is implemented

    Tests are an executable specification: once all of them pass, you are done

    Makes you think about how the code should work, particularly with error handling

    o Unit Testing (JUnit)

    Test individual units, which are often single methods or combinations of methods

    JUnit test classes should be responsible for testing one method

    JUnit test methods should be responsible for testing one input (test case)

    Use meaningful names

    Create new objects for each test

    Readability

    o The ease with which a reader can identify and differentiate tokens (variables, method names, etc.) and their syntactic meaning

    o Use consistent whitespace and punctuation, unique and unambiguous identifier names, syntax (such as parentheses)

    o Follow coding conventions

    Understandability

    o The ease with which a reader can identify the semantic meaning of the code

    o What does the code do? What is its purpose?

    o Meaningful and descriptive identifier names, control flow, comments, unreachable code

    More on control flow

    If/else statements, continue and break statements make it hard for the reader to follow code

    Look at the number of decision points (places where code can branch from one path to another)

    o Put the normal condition first then the unexpected condition second

    o Preferable to put the positive situation first

    McCabe Cyclomatic Complexity can be calculated as the number of decision points plus one

    o An MCC of 10 or more is generally too complex

    Generally avoid nested loops/conditionals that go more than three levels

    o Follow coding conventions

    Defensive Programming

    How does code affect external quality?

    Reliability

    o The likelihood of failure-free operation what percent of the time does it do the right thing?

    Availability

    o The percent of time that the software is available for use

    Defensive programming is meant to guard against mistakes made by yourself, other programmers who use the code, and even the libraries/APIs utilized

    Generally 3 ways to deal with pre-condition failure

    o Fail quietly: dont proceed and dont notify the caller

    o Fail loudly: dont proceed, but notify the caller that it violated the preconditions

    o Failure recovery: try to proceed anyway, even if it means producing the wrong behavior

  • 8

    There are 2 important differences between checking pre-conditions and checking post-conditions

    o Cannot blame the caller if something goes wrong. If the assumptions are all true, then the code should guarantee something; therefore, any violation is

    our fault

    o Once a violation is detected, simply throwing an exception may not be enough because the state of the program may have changed, and the caller may

    not be able to fix it

    To deal with post-condition failure

    o Attempt to roll back to a previously-known good state (of course the caller should be notified that this happened)

    o If it is impractical or impossible to roll back, it may be desirable to terminate the program

    o If program termination is also not an option, then a fault tolerance technique can be used to attempt to put the program in the best state possible

    Exceptions are for things that should not happen

    Assertions are for things that should never happen

    Tradeoffs

    o Improved external quality can come at a cost in terms of internal quality

    o Whether the tradeoff is worth making depends on the type of program, position in the development stage, etc.

    Measuring and Improving Efficiency

    Code optimization is a tradeoff between

    o Execution time

    o Memory usage

    o Code size

    o Compile time

    o Correctness

    o Development effort/cost

    o Maintainability, readability, etc.

    In most cases, premature optimization is the root of all evil

    Make sure that improvement in performance does not come at the cost of all other quality factors

    Rules of thumb:

    o Use the right data structure or algorithm

    o Measure, dont guess

    o Make the common case fast (80/20 rule)

    o Be careful when using threads

    o Dont do unnecessary things (work, memory allocation, trying to outsmart the compiler)

    Important Data Structures

    o Lists make guarantees about ordering and allow for duplicate values

    LinkedLists and ArrayLists

    Search: O(n)

    Adding:

    o O(1) to add to the front, O(n) to add to the tail for linked lists

    o O(1) to add to the tail, O(n) if underlying array needs to be resized

    Access by index: O(1) for ArrayList, O(n) for Linked List

    o Sets make no guarantees about order, ensure that each value is distinct

    TreeSets and HashSets

    Adding and searching: O(log2n) for TreeSet, O(1) for HashSets (assuming reasonabily sized number of buckets, otherwise O(n))

    Java Performance Rules of Thumb

    o Avoid unnecessary work: dont call methods more than necessary

    Dont use Exceptions for control flow

    o Avoid unnecessary object creation

    o Know the API: dont reinvent the wheel

    Compiler Optimization

    o No need for:

    Inlining: replace simple function calls with the code itself

    Dead Code Elimination: remove unreachable code

    Constant folding: combine literals

    Strength reduction: use simple arithmetic operations

    Loop unrolling: call loop body directly if number of loops can be determined and is small

    Lazy Evaluation

    o Delay computation until you know you need the result

    o Create an object only when you need it

    Refactoring

    Make the software easier to understand and modify

  • 9

    o Eliminate duplicate code

    o Communicate its purpose without external documentation

    Attempts to optimize code often causes more harm than good from an understandability standpoint appropriately-named variables

    Use the Replace Data Value with Object pattern

    o Message Chain

    Avoid stacking calls: a.doB().doC().doD() because it means that the caller needs to know all the underlying relationships

    Use the Hide Delegate pattern: create a method doD in class A so the caller doesnt have to know how it works

    Testing

    Goal is to find bugs, not to prove correctness

    Can only prove the existence of errors and not their absence

    Ask:

    o Why: test objective; what do we hope to accomplish?

    o How: test selection; what will we observe and how do we choose it?

    o How much: test adequacy; how many observation do we have to make?

    o What: which part(s) of the system do we need to test?

    o When: at what point in the process do we conduct the tests?

    o Where: where does the testing occur?

    Types:

    o Unit Test: test smallest pieces of code

    o Integration Test: test combinations of units

    o System Test: test full system from users perspective

    o Acceptance Test: customer decides whether or not the system meets their needs

  • 10

    Validation vs. Verification:

    o Was the right thing built?

    o Was the thing built right?

    Dynamic vs. Static analysis:

    o Executing the code (in an actual environment with actual input) vs. analyzing it as text (without compiling/running it)

    Failure: external behavior that is deemed to be incorrect with respect to the desired/expected behavior

    Error: incorrect internal state that led to the failure

    Fault: static defect in code that led to the error (a fault is also referred to as a bug)

    o Manifested as a failure when it is executed and leads to an error state

    o The error state must propagate to external/observable behavior

    o The oracle must be able to detect that the external/observable behavior is incorrect

    Test Oracles

    o True Positive (TP) there is a fault; oracle says there is a failure

    o True Negative (TN) there is no fault; oracle says there is no failure

    o False Positive (FP) there is no fault; oracle says there is a failure

    o False Negative (FN) there is a fault; oracle says there is no failure

    o Completeness no false negatives

    o Soundness no false positives

    o Accuracy (TP + TN) / (TP + FP + TN + FN)

    o Precision TP / (TP + FP)

    Testability

    o A piece of software is easy to test if:

    Controllability it is easy to control the inputs

    Observability it is easy to determine whether the outputs are correct

    Sensitivity the likelihood that a fault will lead to failure for a given statement (how often a statement is executed; probability that a fault

    will lead to an error state; probability that the error state will lead to failure)

    o Built-in Tests

    Address issues related to observability and controllability

    Set/reset methods: public methods that can modify private fields and set them to any desired state, regardless of their current state

    Reporter: public method that can access private fields that are otherwise not exposed

    Assertions: check the state of variables at different parts of the code (not necessarily at the end)

    Downside: violates encapsulation/information hiding

    Testing Strategies

    o Test requirements lead to measurable criteria

    o A test set is expected to cover some part of the criteria

    o Coverage level is the percentage of the criteria that are covered by a given test set

    o Infeasibility: when some aspect of the requirement cannot be satisfied because the criteria is impossible to cover

    o Options: do we generate tests given a certain desired cover level or do we generate tests, see what the coverage level is, and keep going if were not

    satisfied?

    o Five General Strategies:

    Exhaustive Testing try all possible inputs

    Random Testing randomly select inputs

    Black-Box Testing select inputs based on coverage of the specification space (possible inputs/outputs)

    Equivalence Partitioning

    o Divide input space into Equivalence Classes which assume that similar inputs will produce similar test results

    o Should test using Boundary Conditions, which are values that lie on the boundary between equivalence classes

    o Single Fault Assumption:

    There is only one fault in the code

    For inputs a, b, c, d, if some value of a reveals the fault, then it will do so regardless of the values of b, c, or d

    Weak Normal Equivalence Class

    o This implies that when we have multiple inputs, we assume we dont need to test all

    combinations

    o Only need to cover each inputs equivalence class

    o Fewest things to cover (just the individual equivalence classes)

    o Fewest number of test cases to get 100% coverage

    o Pairwise Normal Equivalence Class

    Bugs may be caused by pairs of variables

    Most things to cover (more pairs than combinations)

    Fewer test cases to get 100% coverage

    o Strong Normal Equivalence Class

    Faults are only revealed through combinations of all variables, and not particular values of any one variable

    o Robustness Testing

    Must consider:

  • 11

    Values that are outside the nominal range and may be considered unexpected input

    Values may not be addressed directly in the specification

    Values that are likely to crash the program or cause some other unexpected behavior

    o Equivalence classes determined by output domain

    Use the output space in order to determine equivalence classes

    Look at the domain of possible output values, break it up into equivalence classes, and then

    identify equivalence classes on the input space that lead to those outputs

    White-Box Testing select inputs based on coverage of the code itself (treating it as a graph)

    Consider how much of the code is being executed if you havent executed code, how do you know it works?

    Control Flow Graph a directed graph showing all the statements and the paths between them

    Statement Coverage the percentage of statements that are executed by a test case, or collection of test cases

    Branch Coverage the percentage of branches that are executed. A branch is an edge (arrow) between a decision point and the

    subsequent statement

    Path Coverage the percentage of paths that are executed. A path is a sequence of statements from the beginning to the end (or

    to a return statement)

    o Path coverage is said to subsume branch and statement coverage because 100% path coverage ensures 100%

    branch/statement coverage (but not vice versa)

    o Not all paths are feasible because their path conditions may not be satisfiable

    o If a program contains a loop, then the number of paths may be infinite or uncountable

    In this case, talk about the path conditions for specific paths or path conditions to reach a specific statement

    Fault-Based Testing select inputs that indicate the absence of certain faults

    Privacy

    Cultural differences exist, causing legal issues such as Privacy Laws

    o Censorship

    o Goal is to try to understand what different groups of people want for privacy

    What are developers and users perceptions of privacy?

    Privacy Concerns

    o Data Aggregation the system discovers additional information about the user by aggregating data over a long period of time.

    o Data Distortion the system might misrepresent the data or user intent.

    o Data Sharing the collected data might be given to third parties for purposes like advertising.

    o Data Breaches malicious users might get access to sensitive data about other users

    Reducing Privacy Concerns

    o Privacy policy, license agreements describing what the system will/wont do with data

    o Privacy Laws describing which national law the system is compliant with

    o Anonymizing all data ensuring that none of the data has any personal identifiers

    o Technical Details describing the algorithms/source code of the system in order to achieve higher trust (encryption)

    o Details on Usage describe how different data are used

    Qualitative Feedback Concerns

    o Authorities and intelligent services

    o APIs, Program correctness, viruses

    o Unusable and nontransparent policies

    o Lack of control

    Qualitative Feedback Reducing Concerns

    o Easy and fine-grained control over data

    o Certification from independent trust organization

    o Transparency and open source

    o Trust and education

    Different Types of Data

    o Content of documents (eg. Email body)

    o Metadata (eg. Date)

    o Interaction (eg. Mouse click)

    o User location (eg. City where email was sent)

    o Name or personal data (eg. Email address)

    o User Preferences (eg. Settings)

    Privacy Framework

    o Anonymization

    o Data usage details

    o Default encryption

    o Fine-grained control over data

    o Interaction data first

    Do users understand their current privacy settings?

  • 12

    Can user understanding of privacy be improved using crowdsourced data?

    Are there tools for configuring privacy that are preferred over the currently provided tools?

    Privacy Settings

    o List of all privacy settings

    o Coarse grained

    o Short survey

    o Crowdsourced

    Compare your settings to others

    Mimic others

    Others trusted friends, certain networks, all friends

    Privacy Testing

    o Code/API Bugs how can we detect if privacy settings that are in place remain the same as the software evolves and changes over time? (eg., if my

    photos are currently only shared with my friends, how do I know that they wont automatically get shared with everyone due to a software bug?)

    o Policy Changes how can we detect system wide policy changes that might cause privacy settings to change? (eg., if my photos are private right now,

    how do we detect if there a policy change that makes all photos publicly accessible)

    o Social Testing leverage ones friends on these websites to detect privacy violations

    Ask a friend to see whats visible

    Monitor this periodically

    Notify user if something changes

    Can detect over-sharing this piece of information should have been private, but it can be viewed by others

    Can detect under-sharing this piece of information should have been public, but it cannot be viewed by others

    Advantages:

    Dont need access to source code

    Can be done by an end-user

    Reasons:

    Added more information manually

    Changed privacy settings either deliberately or accidentally

    Didnt do anything there is a bug in the code or API, possibly due to code changes

    Didnt do anything the social system made a wide policy change where this information for many or all of its users is now visible