Software Engineering
Software Engineering
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
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
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
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
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
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
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
10
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