Software Engineering

Software Models

Software models are used to prevent Technical Debt, a poor hard to understand implementation may cost a lot of hours in future to fix it. An hour saved now, could cost 20+ hours later.

Requirements Importance

Spending time strategically upfront, reduces cost and time later on

Time Upfront Cost Overrun 0% 200% 3% 100% 5% 50% 10-20% 40%

Requirements vs Specifications

Requirements: A non-technical definition of something the user requires from the system

  • Should be understood by just anybody. So no JARGON
  • Ability to submit a ‘request for treatment’ medical form

Specification: Technical definition of what is required from the system

  • Keep it simple, not trying to design it
  • Send AES 256 encrypted form data from the front-end to the back-end server

User Requirements (Example)

  • The user should be able to upload a video to the website System Specification (Example)
  • The uploader should accept H264, MOV & MPG, files for upload (Video Format)
  • The uploader should compress the video and save 3 different copies on server
  • A link to the compressed video should be sent via email to user after completion

Non-Functional vs Functional Requirements

Functional: Pertain to the function of the system Non-Functional: Areas that don’t directly affect the function of the program

Categories of non functional requirements

  1. Product - Must have behaviors of the product (referring to the code,servers)
  2. Organizational - Company policies, standards, styles, rules (E.g. Project will be developed using SCRUM methodology)
  3. External - External laws, regulations, trends. Product must use SSL due to XYZ law…

WRSPM

A reference model for understanding the connection between requirements and specifications and the real world

World: World assumptions which are used to develop the system Requirements: Define the problem at hand in terms of a user of system Specifications: Define technical requirements of the system Program: NULL Machine: NULL

Software Architecture Intro

  • Very top level of design, link between idea and reality. Bad architecture is something that can’t be fixed with good programming
  • Software Architecture is all about breaking up larger systems, into smaller focused systems
  • Good Architecture is indeed hard, but once coding has begun, architecture mistakes are almost impossible to fix
  • Good Architecture allows faster development & smarter task allocation. Reduces overall idle time

Design Patterns

  1. Pipe & Filter Pattern: Takes an input, and filter the data and output it
  2. Client-Server Pattern: Client makes requests to the server & server serves response
  3. Master-Slave Pattern: Master manages the most updated form of data/state. For e.g. in hardware usb-drive, the processor will instruct the driver for the usb-drive to do an action (copy data etc …). In software, the Controller acts as a master that gives orders out and collects data. To prevent any form of information flow between slaves. In short, it is why state management is important
  4. Layered Pattern: Allow classification of different parts of the program such as separating the front-end & back-end and assigning the respective engineer to work on each and allows for easier identification of any problems

Software Architecture Process

  • Control how a program is decomposed and how it interacts with itself, and the outside world
  • Break project into subsystems and modules
    • Subsystem, independent system which holds independent values
    • Module, Component of a subsystem which cannot function as a standalone
  • Think about the various quality attributes of the software such as
    • Dependability,Durability,effectiveness,vulnerability etc…

Design Modularity

Requirements -> Specifications -> Architecture -> Design

  • Design is when we apply our plan and idea to real world solutions
  • Design is two things:
    1. Activity : Working to design the software
    2. Product : A document, or set of documents detailing design of software

Stages of Design

  1. Break larger problem into smaller problems
  2. Understand each problem
  3. Identify potential solutions
  4. Describe solution abstractions
  5. Repeat until everything is abstracted
  6. Component design
  7. Data structure design
  8. Algorithm design

Modularity

  1. Coupling - How well modules work together
  2. Cohesion - How well a modules meet a singly designed goal

Goals of Modularity

  1. Abstraction: (E.g)Machine language Abstracted to assembly and then abstracted to Java
  2. Decomposability: Take part of code out that won’t break the code to ensure maintainability
  3. Composability: Put the code back into the code easily
  4. Module Understandability: Jump into a module to immediately understand the context of it (E.g.) 1 module named Update Database
  5. Continuity: A place to store data. E.g. Local Variables stored in a single folder like api keys, so for that constant you only need to change it at one place
  6. Protectability: Keep a small number of entry points to say the database

Information Hiding

  • Hide complexity in a ‘black box’

Data Encapsulation

  • Hide the implementation details from the user and only provide a set of tools to manipulate the data

Summary of Information Hiding & Data Encapsulation

Both of these work to hide the implementation details, and protect the integrity of the data. We want to control the flow of data, and provide the user with an easy to use experience.

Imagine on Facebook if you needed to know how to code to submit a new status update, no one would use it. So we encapsulate that function, providing the user with an area to enter in a status message. Once the user hits submit, all the code activates to make that status update permanent. All the user needs to do is enter text into the box and click a button.

Therefore, we can take the most complex of code and make it accessible to anyone. This makes code easier to maintain. We also don’t need to know the entire codebase to make a change, only part of the program we are working on. Encapsulation of all the other levels of the program, make things easy to test and change.

Coupling

  • Details how dependent each module is on every other module
  • Tight coupling makes it hard to maintain code
  • Example: Let’s say there are 1,000 files, each file uses information and calls from 10 other files. Minimally, we will have to update 10 files
  • The more dependent our program is, the more and more modules we will have to rewrite for every change

Tight Coupling

Strong dependence between modules, changes will be hard to make and bugs difficult to track down

  1. Content Coupling - When one module modifies or relies on the inner workings of another module
  2. Common Coupling - When a bunch of modules have access to manipulate the same global data, should 10 files read and write to this global data, the data may be easily corrupt
  3. External Coupling - When several modules have direct access to the same I/O or 800 files calling to the same API to Google. A better way would be to use a controller and call it from there

Medium Coupling

  1. Control Coupling - when data is passed that influences the internal logic of another module.
  2. Data Structure Coupling - When multiple modules share the same data-structure. If multiple modules update the same Array, what if we decide to change to a linked list? We will have to update every module

Loose Coupling

  1. Data Coupling - When two modules share the same data, only data is passed back and forth, and modules are processing the data and making their decisions independently
  2. Message Coupling - Messages or commands passed between modules. This is when we send a message to another modules that tells it to start/stop
  3. No Coupling - No communication between modules which is undesirable and unrealistic

Cohesion

  1. Functional Cohesion: When a module support activities needed for one and only one problem-related task Determine Monthly Payment, Compute Intercept of Graphs
  2. Object Cohesion: When all activities only modify a single object Mortgage Payment, User

Deployment Planning

Deployment planning depends on the size of the change. Areas to look at include: Database activities, 3rd party Software integration, Network, backups. We need to look at how can we turn back to a previous version of a software should something fail in the current one

Testing

  • Testing is the process of finding errors Test Data: Inputs designed to test the system Test Case: Ways we operate the system with the given data Oracle: The set of ‘good’ outcomes
  • Bugs Bugs can be both a defect, or deviation from expected behavior
  • Levels of Bugs Failure: The event by which the code deviates from expected behavior Error: The part of code that leads to the failure Fault: What the outcome actually was

Testing can be used to show the presences of bugs, but never to insure the absence of them Verification (Are we building the right thing?): Are we building the right product in correlation to the product specification Validation (Are we building the thing right): Are we building the product that is in line with what the customer wants? (*This step is difficult as it requires a lot of communication)

Unit Testing

Testing to focus on the smallest unit of the software. Isolating and testing at a smaller scale

  1. Integration Testing

Integration testing (sometimes called integration and testing, abbreviated I&T) is the phase in software testing in which individual software modules are combined and tested as a group. Integration testing is conducted to evaluate the compliance of a system or component with specified functional requirements

  1. Incremental Testing

Testing when you create a module, do some tests, create another module , and do more tests.

  1. Top-Down Testing

Stub - A template of the model that will be implemented. Typically returns hard-coded values

  1. Bottom-Up Testing

Driver - Templates which execute commands and initialize needed variables

  1. Back To Back Testing

A test which compares a known good, to a new version. After running the tests, compare the test output with the previous version and view the expected changes to the output

Automatic vs Manual Testing

Manual testing, can be done on paper or excel where the tester figure what needs to be done and does it and tick on checkboxes

Automated testing, using software to test things like 15 millions calls on a function or feature to stress test it since those kinds of tests can’t be done manually.

Manual: Quick, Easy Automatic: Requires pre-planning, expensive but over the long run it may be worthwhile

Blackbox Testing

Boundary Values - Input in high and low ranges. Should these pass, it’s assumed everything in between passes Cause Effect Graphing - Test different causes to make sure different effects happen. Pair-wise Testing - Multiple parameters are tested together to check all conditions State-based Testing - Checking input to check state changes

White box Testing

Control Flow - Set up test cases which covers all branch conditions and different statements Data Flow - Covering all variables. Designing test cases to cover different variable declarations and uses

SCRUM

Product Owner: Person who has ownership of the product, figure out the vision of stakeholders (executives), and create a product backlog Scrum Master: Mediate disputes, facilitate meetings, keep things in order and keep the team productive Development Team: Effective size of the team would be 3 - 9 developers.