UNIT-3 SOFTWARE ENGINEERING
Object-Oriented Design (OOD) is a method of designing software by breaking it into interacting objects that
model real-world entities. OOD focuses on classes, objects, their attributes, behaviors, and their
relationships.
OOD uses the principles of object-oriented programming (OOP) to produce a flexible, modular, and
maintainable design.
1. Abstraction
Definition
Abstraction is the process of representing only the essential features of an entity and hiding all irrelevant
details.
Purpose
• Reduces complexity.
• Helps designers focus on “what” an object does, not “how” it does it.
Example
A BankAccount class showing:
• deposit()
• withdraw()
• getBalance()
But hiding internal storage structure, security checks, or database logic.
Importance
• Makes the system easier to extend.
• Improves clarity in design.
• Supports modular architecture.
2. Encapsulation
Definition
Encapsulation is bundling data (attributes) and operations (methods) inside a single unit called a class, along
with controlling access using visibility modifiers.
How it works
• Public: accessible outside the class.
• Private: available only within the class.
• Protected: accessible within class + subclasses.
Benefits
• Protects data from accidental modification.
• Supports modularity.
• Maintains object integrity.
Example
class Student:
private name
private marks
public setMarks()
public getMarks()
3. Inheritance
Definition
Inheritance allows a new class (child) to acquire properties and behavior of an existing class (parent).
Types
1. Single inheritance – One parent, one child
2. Multilevel inheritance – Parent → Child → Grandchild
3. Hierarchical inheritance – One parent, multiple children
4. Multiple inheritance – One child, multiple parents (not in all languages)
Purpose
• Code reusability
• Reduces redundancy
• Supports hierarchical classification
Example
class Animal
class Dog extends Animal
Real Use
A GUI design where a base Window class is extended by Button, TextBox, etc.
4. Polymorphism
Definition
Polymorphism means “many forms.”
It allows the same operation to behave differently depending on the situation.
Types
1. Compile-Time Polymorphism
• Method overloading
• Operator overloading
2. Run-Time Polymorphism
• Method overriding
• Dynamic binding
Example (Overriding)
Animal a = new Dog();
[Link](); // Produces bark
Importance
• Increases flexibility in design.
• Supports dynamic behavior.
• Helps implement interfaces and abstract classes.
5. Modularity
Definition
Modularity is dividing the entire system into separate components (modules) that can be developed, tested,
and maintained independently.
Features
• Each module represents a specific responsibility.
• Modules communicate with defined interfaces.
Benefits
• Easier debugging and testing.
• Enhances maintainability.
• Improves team productivity (different modules handled by different developers).
Example
An e-commerce app may have independent modules like:
• Payment module
• Product catalog
• Authentication
• Order management
6. Reusability
Definition
Reusability refers to using existing software components (classes, modules, functions) in new applications or
systems.
Ways to achieve reusability
• Inheritance
• Composition (has-a relationship)
• Using libraries
• Using frameworks
Advantages
• Reduces development time
• Reduces cost
• Improves reliability (reused code is well tested)
Example
A Logger class used across multiple applications.
7. Class and Object Concepts
Class
Blueprint or template for creating objects.
Defines:
• Attributes (data)
• Methods (behavior)
Object
Instance of a class.
Has:
• State (values)
• Behavior (actions)
• Identity (unique memory location)
Relationship
• A class defines structure.
• An object embodies actual values.
8. Relationships Between Objects
1. Association
A general relationship between two classes.
Example: Teacher — Student
2. Aggregation (Has-A)
A weak ownership relationship.
Example: Department has Teachers (teachers can exist without the department).
3. Composition
A strong ownership relationship.
Example: House contains Rooms (rooms cannot exist without the house).
4. Dependency
One class uses another temporarily.
Example: Printing service uses a Printer object.
5. Inheritance
Defines “is-a” relationship.
9. Message Passing
Objects communicate by sending messages (method calls).
Message passing supports:
• Encapsulation
• Dynamic binding
• Loose coupling
Example
[Link]();
[Link](1000);
10. OOD Principles (SOLID)
Modern design is heavily guided by SOLID principles:
S – Single Responsibility Principle
O – Open/Closed Principle
L – Liskov Substitution Principle
I – Interface Segregation Principle
D – Dependency Inversion Principle
Design Notation and Specification –
Object-Oriented Design (OOD) uses formal notations and specifications to represent system structure,
behavior, and interactions.
The most widely used notation is UML (Unified Modeling Language), which provides a standardized,
visual approach to describe the architecture of an object-oriented system.
Design notation and specification ensure:
• Clarity in communication
• Standard documentation
• Reduced ambiguity
• Better maintainability
• Easier understanding of system structure and behavior
1. UML (Unified Modeling Language)
UML is a graphical language used for modeling, visualizing, specifying, and documenting the components
of a software system.
It contains diagrams, symbols, and notations that represent different aspects of design.
UML diagrams are grouped into Structural and Behavioral categories.
A. Structural Diagrams
These diagrams model the static, structural elements of the system.
1. Class Diagram
Purpose
Represents classes, attributes, methods, and relationships in the system.
Notation
• Class: rectangle divided into three parts → Class Name, Attributes, Methods
• Relationships:
o Association (plain line)
o Aggregation (hollow diamond)
o Composition (solid diamond)
o Inheritance/Generalization (triangle arrow)
o Dependency (dashed arrow)
What it specifies
• Data structure
• Functional responsibilities
• Hierarchies
• Object collaboration
2. Object Diagram
Purpose
Represents objects and their links at a specific moment in time (snapshot of system at runtime).
Notation
• Instances represented with object name : ClassName
• Values of attributes shown inside the object box
Uses
• Understanding sample runtime data
• Testing and validation
• Representing prototype or example scenarios
3. Component Diagram
Purpose
Shows how software components are organized and how they interact.
Components
• Libraries
• Executables
• Files
• Modules
Used heavily in large-scale systems.
4. Deployment Diagram
Purpose
Shows hardware/software mapping and runtime environment.
Notation
• Nodes (hardware devices)
• Artifacts (software components deployed on nodes)
B. Behavioral Diagrams
These diagrams focus on dynamic behavior of the system.
1. Use Case Diagram
Purpose
Represents functional requirements from the user’s point of view.
Notation
• Actors (stick figures)
• Use cases (ovals)
• Relationships: include, extend, generalization
• System boundary (rectangle)
What it specifies
• User interactions
• High-level system functionality
• External actors and their roles
2. Sequence Diagram
Purpose
Shows message flow and interaction between objects in time order.
Notation
• Lifelines (vertical lines)
• Activation bars
• Messages (arrows)
• Return messages
• Asynchronous calls
What it specifies
• Order of calls
• Responsible objects
• Data exchange
3. Activity Diagram
Purpose
Represents workflows, operations, or business processes.
Notation
• Initial node
• Activities
• Decisions (diamonds)
• Parallel bars (fork/join)
• Final node
Uses
• Modeling algorithms
• Describing use-case flows
• Representing concurrent tasks
4. State Machine (Statechart) Diagram
Purpose
Shows the lifecycle of an object based on events and transitions.
Notation
• States
• Transitions
• Events
• Actions
What it specifies
• Object behavior
• Reaction to events
• State transitions (e.g., Idle → Processing → Completed)
2. Design Specification Techniques
Design specification defines how the system will behave, how components will interact, and how inputs
produce outputs.
Specifications usually include:
A. Structural Specification
Describes system architecture in terms of classes, objects, and relationships.
Includes:
• Class structure
• Object relationships
• Inheritance diagrams
• Aggregation/composition
• Packages
Tools
• UML Class Diagrams
• Object Diagrams
B. Behavioral Specification
Describes how the system behaves over time or based on events.
Includes:
• Control flow
• Event-driven behavior
• State changes
• Functional flows
Tools
• Sequence Diagrams
• Activity Diagrams
• State Machine Diagrams
C. Functional Specification
Represents functional requirements and system capabilities.
Includes:
• Use cases
• Input/output descriptions
• Preconditions
• Postconditions
• Scenarios of usage
Tools
• Use Case Diagrams
• Use case narratives
• Flow-of-events documents
D. Interface Specification
Defines communication and interaction rules between components.
Includes:
• Public methods
• Parameter types
• Return types
• Exceptions
• Constraints
Example
Interface PaymentService
-------------------------
+ processPayment(amount: float): boolean
+ refund(amount: float): boolean
E. Constraints and Contracts Specification
Formal rules that must be satisfied.
Includes:
• Pre-conditions (must be true before method runs)
• Post-conditions (must be true after method runs)
• Invariants (must always be true)
Often described using:
• OCL (Object Constraint Language)
• Assertions
• Design by Contract (DbC)
3. Importance of Design Notation and Specification
1. Standard communication tool
All team members understand the system using standard UML symbols.
2. Eliminates ambiguity
Graphical models are clearer than long textual descriptions.
3. Supports verification and validation
Design models help evaluate correctness before coding.
4. Enhances maintainability
Changes in design can be understood and applied easily.
5. Reduces development cost and errors
Clear design → Fewer bugs → Faster development.
4. Summary
Design notation and specification help in:
• Understanding system structure
• Representing dynamic behavior
• Defining interfaces
• Modeling system requirements
• Documenting architecture for future use
UML is the most powerful tool for modeling object-oriented systems and is universally used in industry and
academics.
Debugging Process —
1. Definition & Goal
Debugging is the systematic process of finding, diagnosing (root cause), fixing, and preventing defects (bugs)
in software so the program meets its specification and behaves correctly.
Goal: remove defects while minimizing side effects and regression.
2. High-level Phases
1. Problem discovery / Report — bug is observed by user, test, or monitoring.
2. Information gathering — collect data needed to reproduce and analyze.
3. Fault isolation — narrow code/location that causes the behavior.
4. Fault confirmation — confirm root cause and reproduce reliably.
5. Fix design & apply fix — implement minimal, correct change.
6. Testing & regression — verify fix and ensure no new bugs introduced.
7. Documentation & follow-up — record details and preventive measures.
3. Phase-by-phase Detail
3.1 Problem discovery / Report
• Sources: user reports, automated tests (unit/integration), CI pipelines, monitoring/alerts, crash reports,
bug bounty reports.
• Essential info to capture in the report:
o Steps to reproduce (precise)
o Observed behavior (error messages, stack traces)
o Expected behavior
o Environment (OS, version, config, hardware, network)
o Input data / sample payloads
o Time and logs around the event
• Good bug reports speed up debugging drastically.
3.2 Information Gathering
• Reproduce locally or in a controlled environment.
• Collect:
o Logs (application, system, access)
o Stack traces and core dumps
o Configuration files and environment variables
o Database state or snapshots (if safe)
o Network traces (tcpdump, Wireshark) for network bugs
o Resource metrics (CPU, memory, disk I/O)
o Recent deploys/commits (use git blame, CI history)
• Tools: log aggregators (ELK/Elastic, Splunk), APM (New Relic, Datadog), monitoring
(Prometheus/Grafana).
3.3 Fault Isolation (Narrowing the search)
• Reproduce systematically — reduce inputs until minimal reproducer.
• Divide-and-conquer / Binary search:
o Disable modules/features to find area.
o Bisect commits (git bisect) to find the commit introducing the bug.
• Instrumentation:
o Add logging (with correlation IDs).
o Use assertions and invariants.
• Dynamic debugging:
o Attach a debugger (gdb, lldb, pdb, Visual Studio Debugger).
o Set breakpoints, watchpoints, step through code.
• Static analysis: linters, type checkers, static analyzers (clang-tidy, SonarQube) to find suspicious code
patterns.
• Re-run tests: run relevant unit/integration tests; add new tests to capture the failure.
3.4 Fault Confirmation
• Once you suspect the fault location:
o Create a minimal test case that reproduces it.
o Confirm that changing the suspected line(s) changes the behavior.
o Reproduce across environments (dev, staging) to rule out environment-specific causes.
• Use assertions and unit tests to lock the bug down.
3.5 Root Cause Analysis (RCA)
• Ask why multiple times (5 Whys technique) to reach root cause (not just symptom).
• Categorize cause: logic error, race condition, incorrect assumption, incorrect config, resource
exhaustion, integration mismatch.
• Tools: post-mortem debugging for crashes, heap profilers (valgrind, massif), flamegraphs for CPU.
3.6 Designing and Applying a Fix
• Prefer small, localized changes; keep behavior semantics unchanged outside fix scope.
• Follow project style and testing practices.
• Write tests (unit/integration/regression) that fail before the fix and pass after.
• Code review: get peers to review for side effects.
• If immediate hotfix needed in production, coordinate rollback strategy and follow post-deploy RCA.
3.7 Testing & Regression
• Run complete test suite (unit, integration, end-to-end).
• Perform regression testing to ensure fix did not break other features.
• For performance or concurrency fixes, run stress tests and load tests.
• If fix is deployed, monitor closely (canary/feature flags) before full rollout.
3.8 Documentation & Prevention
• Update bug tracker with steps, cause, fix, and related commits.
• Add or update tests and documentation.
• Consider preventive actions: more robust input validation, better error handling, improved logging or
monitoring, coding guidelines.
4. Techniques & Strategies
Reproduce-first rule
Never attempt to fix until the bug can be reproduced reliably.
Minimal Reproducer
Strip input and state to minimal values needed to reproduce — helps speed diagnosis.
Logging best practices
• Use structured logs (JSON), include correlation/trace IDs.
• Log at appropriate levels (ERROR, WARN, INFO, DEBUG).
• Ensure logs have timestamps, contexts, and unique identifiers.
Conditional breakpoints and watchpoints
Stop only on specific conditions to avoid overwhelming the debugger.
Rubber duck debugging
Explain code/problem to a colleague or an inanimate object — often reveals the answer.
Binary/Commit bisection
Use git bisect to find the offending commit quickly.
Read stack traces bottom-up
Start at the lowest frame in your code (where the error originates) and work outward.
5. Common Bug Types & How to Approach Them
5.1 Logic Bugs
• Symptom: incorrect outputs, failed assertions.
• Fix: unit tests, step-through debugging, inspect algorithm correctness.
5.2 Off-by-one / boundary errors
• Symptom: incorrect loops, array index out of bounds.
• Fix: carefully check loop conditions, indices, and boundary tests.
5.3 Null / None dereference
• Symptom: NullPointerException / AttributeError.
• Fix: validate inputs, add guards, use option types or nullable annotations.
5.4 Concurrency / Race Conditions / Deadlocks
• Symptom: non-deterministic failures, hangs under load.
• Fix: reproduce under stress, use thread sanitizer (TSAN), add synchronization, prefer immutable data,
redesign for message-passing.
• Tools: Helgrind, ThreadSanitizer, concurrency profilers.
5.5 Memory Leaks
• Symptom: sustained memory growth, OOM crashes.
• Fix: use heap profilers (valgrind massif, heaptrack), check long-lived references, caching logic, close
resources.
5.6 Performance Issues
• Symptom: high latency, CPU spikes.
• Fix: profile (flamegraphs, perf, VisualVM), optimize hot paths, cache, index DB queries.
5.7 Integration / API Contract Mismatch
• Symptom: failing API calls, serialization errors.
• Fix: verify schema/contract (OpenAPI/JSON Schema), add versioning, ensure backward
compatibility.
5.8 Configuration / Environment
• Symptom: works locally but fails in prod.
• Fix: check environment variables, environment-specific behavior, dependency versions, feature flags.
6. Tools Overview (examples)
• Debuggers: gdb, lldb, pdb, WinDbg, Chrome DevTools
• Logging/Aggregation: ELK Stack (Elasticsearch, Logstash, Kibana), Splunk
• Profilers: perf, VisualVM, JProfiler, py-spy, flamegraph
• Static analyzers / Linters: pylint, mypy, ESLint, SonarQube
• Dynamic analysis: Valgrind, AddressSanitizer, ThreadSanitizer
• Tracing / APM: Jaeger, Zipkin, OpenTelemetry, New Relic, Datadog
• Network tools: tcpdump, Wireshark, curl, Postman
• Version bisect: git bisect
• Testing frameworks: pytest, JUnit, NUnit, Selenium for end-to-end