0% found this document useful (0 votes)
9 views41 pages

CS504 Final Term Lectures

Lecture 20 discusses interaction diagrams that model the dynamic behavior of object-oriented systems through message exchanges among objects. It covers types of UML interaction diagrams, specifically sequence and collaboration diagrams, and their purposes in modeling interactions, verifying use cases, and identifying class responsibilities. The lecture also details message types, labeling, and the importance of architectural design in software systems.

Uploaded by

Noble Ch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views41 pages

CS504 Final Term Lectures

Lecture 20 discusses interaction diagrams that model the dynamic behavior of object-oriented systems through message exchanges among objects. It covers types of UML interaction diagrams, specifically sequence and collaboration diagrams, and their purposes in modeling interactions, verifying use cases, and identifying class responsibilities. The lecture also details message types, labeling, and the importance of architectural design in software systems.

Uploaded by

Noble Ch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 41

CS504 Final Term lectures

Lecture 20

Certainly! Here's your original content reformatted for easier memorization without removing any key
points:

Lecture No. 20 – Interaction Diagrams: Depicting the Dynamic


Behaviour of the System

Overview

A series of diagrams are used to describe the dynamic behavior of an object-oriented system, in terms of
messages exchanged among objects to accomplish a purpose.
These diagrams often model how a use case is realized through message sequences between objects.

Purpose of Interaction Diagrams

 Model interactions between objects


 Help understand how a use case/system works
 Verify if a use case is supported by existing classes
 Identify responsibilities/operations and assign them to classes

Types of UML Interaction Diagrams

UML provides two mechanisms to document dynamic behaviour:

1. Sequence Diagrams – Time-based view


2. Collaboration Diagrams – Organization-based view

Sequence Diagrams
🔸 Purpose

Illustrate how objects interact, emphasizing time-ordering of messages.


Used to model:

i. Simple sequential flow


ii. Branching
iii. Iteration
iv. Recursion
v. Concurrency

Focus is on objects/classes and message exchanges among them to carry out a scenario’s functionality.

Layout

 Horizontal (X-Axis): Objects/Classes


 Vertical (Y-Axis): Time
 Events arranged in time sequence

Notation

 Boxes: Represent objects or classes


 Solid Lines (→): Messages between objects
 Dotted Lines: Life-lines of objects (duration of activity)
 Activation Boxes: Show duration of message execution
 Condition Boxes: Conditions before a message is invoked

Example:
member:LibraryMember sends message to book:Book
→ Only if condition [ok] is true

Object Naming Syntax

Format: [instanceName] : [className]

 Use consistent class names (match class diagram)


 Include instance names if:
o Object is referred in messages
o Multiple objects of the same class exist in the diagram

🔸 Messages Between Objects

 A message = operation call (can be network/internal)


 Message from obj1 to obj2 requires:
o Association between the objects
o obj2 is in global or local scope of obj1
o Or obj1 = obj2 (for self-calls)

🔸 Self-Calls

 Object can send messages to itself


 Example: member:LibraryMember sends mayBorrow() to itself

Message Labeling

 At minimum: message name


 Optional: arguments, conditions, iteration
 Prefer brief textual description if an actor is the sender/receiver

Activation Box

Represents the time taken by receiver object to process the message

Lecture 21

Here is your entire content reformatted in an organized, structured, and memorization-friendly format,
keeping every point intact:

Message Types in Sequence Diagrams


1. Types of Messages

i. Synchronous
ii. Asynchronous
iii. Create
iv. Destroy

2. Synchronous Messages

 Represent call events


 Denoted by solid/full arrows
 Represent nested flow of control (e.g., operation call)
 Caller waits for callee to complete before proceeding
 Return values: shown using dashed arrow with label
o Return value shown only when:
 It's not obvious (e.g., getTotal())
 It's used elsewhere (e.g., passed as a parameter)
o Prefer modeling as:
 ok = isValid()

3. Asynchronous Messages

 Represent signals
 Denoted by half arrow
 Caller does not wait for the callee to finish
 Used in:
o Multi-threaded or multi-processing apps
 Typical actions:
o Create a new thread
o Create a new object
o Communicate with an already running thread

4. Object Creation & Destruction

 Creation: <<create>> message


 Destruction: <<destroy>> message
 An object can destroy itself
 Avoid modeling destruction unless memory management is critical
 Impacts on life lines must be considered

Sequence Diagrams & Logical Complexity


 Use only when they add value
 Golden rule: Keep it small and simple
 Handle conditional logic carefully:
o If simple, include in the diagram
o If complex, use separate diagrams like flow charts
Collaboration Diagrams
 Depict dynamic behavior with respect to organizational structure (boundaries)
 Show interactions between objects and external systems (e.g., UI)
 Messages are numbered (1, 2, 3...) to show sequence

Components

 Objects
 Messages
 Show synchronous, asynchronous, create, and destroy messages (same as sequence diagrams)
 Loops can also be modeled
Comparison: Sequence vs. Collaboration Diagrams

Feature Sequence Diagram Collaboration Diagram


Focus Flow of time Object organization + control flow
Message sequence clarity Easier to understand More difficult to follow
Object structure clarity Less emphasized Clearly shown
Control complexity Hard to model complex logic Can get very complex quickly

Evaluating Object-Oriented Design Quality


Key Attributes

 Encapsulation
 Delegation
 Coupling & Cohesion
o Good OO design = high cohesion, low coupling

Centralized vs. Distributed Control Example

❌ Bad Design (Distributed Intelligence)

 Separate objects: DesiredTemp, ActualTemp, Occupancy


 Regulator queries each one separately

Furnace
Heat Flow Regulator
→ desiredTemp()
→ actualTemp()
→ anyonePresent()

✅ Better Design (Encapsulated)

 Combine into a single Room object


 Regulator communicates only with Room

Furnace
Heat Flow Regulator
→ Room
- desiredTemp()
- actualTemp()
- anyonePresent()

🔁 Best Design (Delegated Control)

 Move logic into Room (e.g., doYouNeedHeat())

Furnace
Heat Flow Regulator
→ Room
- doYouNeedHeat()

 Reduces coupling
 Improves cohesion
 Fewer messages = simpler protocol

Protocol Simplification Example

Instead of:

 SetMinimumValue(int aValue)
 SetMaximumValue(int aValue)
Use:

 SetLimits(int minValue, int maxValue)

✅ Consolidation = fewer messages, simpler interface

⚠️Caution:

 Use heuristics wisely


 Avoid combining unrelated operations into one function

Lecture 22

Here is your lecture content fully reformatted for clarity, structure, and memorability, without altering any
information.

Lecture No. 22 – Software and System Architecture


Introduction
When building a house, different experts (architect, plumber, electrician, etc.) view the structure differently.
Each of these perspectives contributes to the overall architecture.

✅ Similarly, software architecture captures the overall structure of a software system.

Architectural Design

 Identifies sub-systems of a system


 Defines control and communication framework
 Output: Software Architecture Description

Historical Foundations of Software Architecture


 Edsger Dijkstra (1968)
→ Proposed layered structure: each layer communicates only with adjacent layers
→ Emphasized structure over functionality
→ Benefit: easier development & maintenance
 David Parnas
→ Introduced:

i. Information hiding modules


ii. Program families

Program family:

A group of programs treated as a collective for design efficiency e.g., GUIs in video games and software tools

 Design Philosophy:
o Make early decisions on architectural elements that remain constant
o Make late decisions on changeable things (like constants)

🔹 What is Software Architecture?


There is no universally accepted definition, but all focus on structure.

System Definition (as per UML 1.3 and IEEE 610.12-1990)

A system is a collection of connected units/components organized to achieve specific tasks.

Key Definitions of Software Architecture


Source Definition
Organizational structure of a system. Decomposed into parts (classes, components,
UML 1.3
subsystems) with interfaces, relationships, and constraints.
Bass, Clements, Structure(s) of the system, software components, their externally visible properties, and
Kazman (1997) relationships. Focuses on abstraction and analyzability.
Garlan & Perry Structure of components, their interrelationships, and principles/rules guiding their
(1995) design/evolution.
Architectural design is defining hardware/software components and interfaces for a
IEEE Glossary
development framework.
Architecture = computational components (e.g., client-server, databases) and their
Shaw & Garlan
interactions (e.g., procedure call, protocols, multicast).

✅ Despite differences, all definitions emphasize structure and non-functional design concerns.

Purpose of Architectural Design


 Links specification with detailed design
 Provides abstract solution
 Captures critical decisions under constraints
 Defines non-functional requirements
 Describes environment
 Conducted in parallel with specifications

Why is Architecture Important?


1. Mutual Communication

 Shared abstraction across all stakeholders


 Enables:
o Understanding
o Consensus
o Communication
 Helps in expressing and resolving diverse concerns

2. Early Design Decisions

 Architecture embodies the first structural decisions


 Influences:
o Development
o Deployment
o Maintenance
 Enables early analysis

Implementation should conform to the architecture:

 Defined components
 Prescribed interactions
 Component responsibilities

Work Breakdown Structure (WBS)

 Architecture defines how tasks and teams are organized


 Used for:
o Planning & scheduling
o Budgeting
o Communication
o File organization
o Integration/testing

Once module structure is formalized, it becomes difficult and expensive to change

✅ So: Extensive analysis before freezing architecture is critical


Quality Attribute Prediction

 Architecture can be evaluated early


 Enables risk mitigation
 Prevents “random” architecture selection

3. Reusable Abstraction

 Architecture = graspable model of system structure


 Promotes reuse across systems (esp. product lines)

E.g., GUI framework reused in different applications

 Defines:
o What is fixed across product family
o What is variable

Trade-off: Slight loss of optimality in exchange for:

 Reduced risk
 Lower development cost
 Easier maintenance

Architectural Attributes (Non-functional Requirements)


Attribute Guideline
Performance Localize operations → minimize inter-subsystem communication
Security Use layered architecture; critical components in inner layers
Safety Isolate safety-critical components
Availability Introduce redundancy (backup components)
Maintainability Use simple, fine-grained, self-contained modules

Architectural Design Process


Like any design task, it's creative and iterative

🧩 Activities:

1. System Structuring
o Decompose into principal sub-systems
o Identify interactions
o Represent with block diagrams

🔹 Sub-system: Independent system component


🔹 Module: Provides services but not a standalone system

2. Control Modeling
o Define control relationships among components
3. Modular Decomposition
o Further decompose sub-systems into modules

Would you like this reformatted content:

 As PDF?
 In slides (PowerPoint format)?
 With flashcards for review?
 Or summarized as key points only?

Let me know how you plan to use it!

Lecture 23
Here is a clean, well-structured and easy-to-memorize version of Lecture No. 23: Architectural Views. All
points are preserved, but formatted for readability and memorization.

📘 Lecture 23: Architectural Views in Software


Architecture

🔶 What is Software Architecture?


High-level structure of software composed of architectural elements designed to meet both functional and
non-functional requirements.

📐 Perry & Wolfe’s Architecture Formula


Software Architecture = {Elements, Forms, Rationale}

Element Types:

1. Data elements – store and carry information


2. Processing elements – transform the data
3. Connecting elements – link components (can be data or processing elements)

🔄 Boehm’s Modified Formula


Software Architecture = {Elements, Forms, Rationale/Constraints}

🧭 Krutchen’s 4+1 Architectural View Model


A software system must satisfy multiple stakeholders. Hence, architecture should be viewed from different
perspectives.

🧩 The 5 Views:

1. Logical View
o Object model
o Focus: Functionality for end-users
2. Process View
o Concurrency & synchronization
o Focus: Performance, scalability, throughput
3. Development View
o Software organization in development environment
o Focus: Software management & structure
4. Physical (Deployment) View
o Mapping of software to hardware
o Focus: System engineering & topology
5. Use Case (Scenarios) View
o Functional requirements validation
o Ties all views together

📊 Krutchen’s Diagram Summary


View Focus Area Stakeholders
Logical End-user functionality End users
Process Runtime performance aspects Integrators, sys engineers
Development Code organization Programmers, PMs
Physical System topology, installation System engineers
Use Case View Scenarios, behavior, requirements All stakeholders

🔁 Clements' Modified 4+1 View Model


Adds a new view and slightly renames others:

📌 Views:

1. Functional View
o Key abstractions, domain functions
o For: Domain engineers, end-users
o Use: Understand functionality, modifiability, reusability
2. Development View
o Files, directories
o For: Managers, programmers
o Use: Maintenance, testing, config management
3. Code View (Extension)
o Classes, objects, layers, subsystems
o For: Programmers, designers
o Use: Portability, maintainability
4. Concurrency View
o Threads, parallel processes
o For: Testers, integrators
o Use: Performance optimization, synchronization
5. Physical View
o CPUs, sensors, devices
o For: System engineers
o Use: Installation, availability, scalability, security

🧪 Use Case (Scenario) View


 Scenarios:
o Use cases (functional behavior)
o Change cases (adaptability)
 Uses:
o Validate the architecture
o Communicate design
o Understand dynamic behavior

📋 View Comparison Summary


View Components Users Purpose
Functional Functions, abstractions, domains Engineers, end-users Modifiability, reuse
Code Classes, modules, functions Programmers, designers Maintainability, portability
Development Files, directories Managers, config managers Maintenance, version control
Physical Hardware: CPUs, storage, networks Hardware/system engineers Performance, installation
Concurrency Processes, threads Integrators, testers Performance, availability

🛠 What Are Views Used For?


 Achieve quality attributes (performance, scalability, etc.)
 Serve as engineering & documentation tools
 Used for:
o Design analysis
o Communication (developers, managers, clients)
o Maintenance & evolution

✅ Annotations (e.g., rationale, scenarios) improve view usefulness.

🔗 Structural Reasoning at Architecture Level


Different system properties (beyond functionality) like:

 Physical distribution
 Communication
 Synchronization
Must be reasoned architecturally, using appropriate structures:

Structure Type Purpose


Uses Extendability, scalability
Calls Reduce bottlenecks
Module Improve modifiability

🏗 Hierarchical Views
Each architectural view can be nested or hierarchical:

View Subdivision Example


Functional Functions → sub-functions
Development Directories → files
Code Modules → submodules
Concurrency Processes → threads
Physical Computers → processors

🧱 Architectural Styles
A system may conform to standard architectural styles to simplify design.

Each Style Includes:

1. Components
o e.g., databases, modules
2. Connectors
o Coordination & communication mechanisms
3. Constraints
o Rules for valid component integration
4. Semantic Models
o Help understand system behavior from its parts

⚠️Large systems are often heterogeneous and mix multiple styles.

Would you like this restructured content:

 As a PDF document?
 Converted into flashcards for revision?
 Turned into a PowerPoint presentation?
 Made into a mind map?

Let me know how you plan to use it for study or teaching!


Lecture 24

Here's your provided Lecture No. 24 (Sections 8.7–8.11) content fully reformatted for clarity, structure, and
improved readability, without changing the original meaning:

Lecture No. 24 – Architectural Models and Styles

🔹 8.7 Architectural Models

During architectural design, various types of architectural models are developed, similar to analysis models.
These include:

 Static Structural Models:


Show the major system components and their relationships.
 Dynamic Process Models:
Represent the process structure and how components interact over time.
 Interface Models:
Define the interfaces between subsystems, specifying how components communicate.

🔹 8.8 Architectural Styles

Architectural design is often based on specific patterns known as architectural styles. Each style has its own
characteristics and attributes that suit particular requirement scenarios.

Common Architectural Styles:

 Data-centered architectures
 Client-server architecture and its variations
 Layered architectures
 Reference architectures

🔸 Data-Centered Architecture (Repository Model)

In systems where subsystems need to exchange large amounts of data, there are two approaches:

1. Shared Central Database (Repository):


All subsystems access a centralized repository.
2. Distributed Databases:
Each subsystem maintains its own database and explicitly shares data with others.

Use Case:

Repository model is often used in mainframe-based applications.

📌 Advantages:

 Efficient sharing of large data sets


 Subsystems are independent of data production
 Centralized management (e.g., backups, security)
 Provides a global system view through a repository schema

⚠ Disadvantages:

 All subsystems must agree on a common data model (often a compromise)


 Difficult and costly to evolve data models
 Limited management policy customization
 Hard to distribute the repository efficiently
🔸 8.9 Client-Server Model

The client-server model aims to distribute both data and processing, shifting from older mainframe models.

Background:

 Previously, data processing and storage were done on one central mainframe.
 Users interacted via dumb terminals (minimal processing power).
 With cheaper, more powerful machines, workload distribution became viable.

How It Works:

 Clients request services.


 Servers provide services like printing, data management, etc.
 Communication happens over a network.
 Clients and servers are logical processes, not necessarily separate physical machines.

Key Characteristics:

 Clients know the servers, but servers don’t need to know all clients
 No fixed 1:1 mapping of processes to processors

🔸 8.10 Client/Server Software Components

A typical client-server system consists of:

Major Components:

 User Interaction / Presentation Layer


 Application Subsystem (implements requirements)
 Database Management Subsystem
 Middleware (handles connectivity and communication protocols)

Representative Server Types:

Server Type Functionality


File Servers Clients request file records; server sends them over the network
Database Servers Clients send SQL queries; server processes and returns results
Transaction Servers Clients invoke remote procedures; server executes them and returns results
Groupware Servers Support collaboration (text, images, video, bulletin boards, etc.)

📌 Client-Server Characteristics

✅ Advantages:

 Utilizes networked systems efficiently


 Reduces need for expensive hardware
 Improves performance and scalability
 Easier to add or upgrade servers
 Simplifies data distribution

❌ Disadvantages:

 No standard data-sharing method (subsystems may use different formats)


 Data interchange may be inefficient
 Redundant management required on each server
 No central service registry (difficult to discover services/servers)

🔸 8.11 Representative Client/Server Configurations


There are multiple ways to implement a client-server system. Two common models are:

Thin Client Model:

 Used to migrate legacy systems


 GUI is on client, core logic remains on the server
 Drawback: Heavy load on server and network

Fat Client Model:

 Leverages powerful client machines


 Shifts more processing to the client
 Suitable when client capabilities are known

Drawbacks:

 More complex management


 Applications must be installed/updated on each client individually

Let me know if you'd like this:

 As a PDF or Word document


 Converted into slides
 With diagrams for each model (e.g., repository, client-server)
 Or broken into quiz-style flashcards for quick study

Lecture 25

Here is your Lecture No. 25 (Sections 9 & 8.12–8.15) content, fully reformatted for clarity and structure,
while keeping the original meaning intact:

Lecture No. 25 – Advanced Architectural Models

🔹 9. Zero Install Architecture

Traditional fat-client architecture creates challenges for installation and maintenance, especially with many
client machines.

Key Idea:

 No installation required on the client side


 Minimal or no client-side processing
 Trade-off: Utilize client processing power vs. reduce maintenance overhead

Difference from Classical Thin-Client:

 Thin-client: Entire processing on a single server


 Zero-install: Server-side processing is distributed across multiple servers

Example:

 Web-based applications
Changes to the app are reflected immediately by updating server-side pages.
Users always get the latest version without needing updates on their devices.

🔹 N-Tier Architecture

N-tier architecture aims to strike a balance between fat-client and thin-client models.
Key Features:

 Distributes data and application logic across multiple servers


 Improves scalability and performance
 Common servers:
o Web Server
o Application Server
o Database Server

🔸 Three-Tier Architecture (a specific N-tier model)

Each architectural layer runs on separate processors, providing:

 Better performance than thin-client


 Easier management than fat-client
 High scalability (more servers can be added as needed)

Tiers:

1. Presentation Layer – Client/browser interface


2. Application Layer – Business logic
3. Database Layer – Data storage and management

🔹 N-Tier Generalization

N-tier architecture extends the three-tier concept.


It allows more than three layers to further optimize performance and distribution by assigning different
subsystems to different servers.

🔹 8.12 Data Flow (Pipes and Filters) Architecture

This architecture is similar to data flow diagrams.

Concept:

 Data is processed through a series of filters


 Each filter is a processing step
 Pipes carry data between filters

Key Characteristics:

 Each filter operates independently


 Filters don’t need knowledge of others
 Promotes reusability and modularity

Types:

 Batch Sequential:
Single path of execution, no alternatives or parallel paths.

🔹 Layered Architecture

Layers are arranged from user-facing to hardware-facing components.

Example: Operating System

 Each layer provides services to the layer above


 Outer layers only interact with the interface of inner layers, not their internal logic
Benefits:

 Encapsulation of complexity
 Improved portability and maintainability

Typical Layers:

1. User Interface Layer


2. Application Layer
3. Utility Layer
4. Core Layer (close to hardware)

🔹 8.13 Reference Architectures

A reference architecture is not a concrete system, but a standard model for designing and evaluating
systems.

Uses:

 Defines protocols and design guidelines


 Serves as a benchmark or comparison framework

Example: OSI Model

A 7-layer model for communication systems:

1. Physical
2. Data Link
3. Network
4. Transport
5. Session
6. Presentation
7. Application

Impact:

The Internet's success is largely due to systems conforming to shared reference architectures like OSI.

🔹 8.14 Partitioning the Architecture

Partitioning helps in distributing responsibilities for ease of maintenance and testing.

Types of Partitioning:

✅ Horizontal Partitioning

 Divides the system into branches by functionality


 Control modules coordinate communication between branches

Partition 1 Partition 2 Partition 3


(Function A) (Function B) (Function C)

✅ Vertical Partitioning (Factoring)

 Stratifies decision-making and worker logic


 Top layers handle decisions
 Bottom layers execute actions

Top Partition (Decision Makers)


-------------------------------
Bottom Partition (Workers)
🔹 8.15 Analyzing Architecture Design

Architectural decisions often involve trade-offs between conflicting system qualities.

Steps for Architectural Analysis:

1. Collect scenarios (realistic use cases)


2. Elicit requirements, constraints, and environment details
3. Describe architectural patterns/styles used:
o Module view
o Process view
o Data flow view
4. Evaluate quality attributes (e.g., performance, security) independently
5. Identify sensitivities of these attributes to design choices

Finally, critique candidate architectures by examining how sensitive their design is to changes or trade-offs.

Would you like this:

 Exported as a PDF, Word file, or presentation?


 Illustrated with diagrams for each architecture?
 Turned into flashcards or a quiz for study purposes?

Lecture 26

Here is your Lecture No. 26 – Introduction to Design Patterns from CS504: Software Engineering – I
reformatted clearly and professionally for readability and study purposes:

Lecture No. 26 – Introduction to Design Patterns

📌 What Are Design Patterns?

“Each pattern describes a problem which occurs over and over again in our environment, and then
describes the core of the solution to that problem... without ever doing it the same way twice.”
— Christopher Alexander, A Pattern Language (1977)

While Alexander referred to architecture (buildings/towns), his ideas apply equally to object-oriented software
design.

🔹 Definition:

“Design patterns are descriptions of communicating objects and classes that are customized to solve a general
design problem in a particular context.”

They help developers reuse knowledge, solve recurring problems, and document experience for future
projects.

🧾 Purpose of Documenting Design Patterns:

 Reuse proven design solutions


 Prevent reinventing the wheel
 Share design knowledge
 Enhance code maintainability and readability
📝 Standard Format for Documenting Design Patterns Includes:

1. Motivation / Context
2. Prerequisites
3. Program Structure
4. Participants
5. Consequences (Pros/Cons)
6. Examples

📜 Historical Background

 1970s: Christopher Alexander introduced the concept in building architecture.


 1987: Re-emerged in software at the OOPSLA conference.
 1995: Erich Gamma, Helm, Johnson, and Vlissides published
“Design Patterns: Elements of Reusable Object-Oriented Software” — the GoF book.

Also influenced by earlier programming efforts:

 STL (Standard Template Library) in C++


 Algorithms and data structures
 Peter Coad’s OOA/D Patterns
 Frameworks (cooperative class sets for system design)

❌ Anti-Patterns:

 Represent common mistakes in analysis/design


 Help identify and avoid bad practices

GoF Design Pattern Format (Template)


Component Description
Name Meaningful identifier; serves as an idiom
Problem Statement describing intent, goals, and objectives
Context Preconditions and situations in which pattern is applicable
Forces Constraints, conflicts, and motivations behind the design
Solution Description of structure, participants, interactions (static/dynamic)
Examples Real-world implementations showing pattern usage
Resulting Context State after applying the pattern; positive/negative consequences
Rationale Justification, how the solution resolves forces and meets goals
Related Patterns Connections to other patterns (useful for extension or substitution)
Known Uses Real-life examples to show it’s a proven solution

🧩 Classification of Design Patterns

🔹 1. Creational Patterns

 Purpose: Manage object creation mechanisms


 Goal: Make system independent of object instantiation

Type Description
Class-Creational Use inheritance to decide what class to instantiate
Object-Creational Delegate instantiation to another object
Examples:

 Abstract Factory
 Factory Method
 Singleton
 Builder
 Prototype

🔹 2. Structural Patterns

 Purpose: Deal with object composition and structure


 Combine objects/classes to form larger structures

Type Description
Class-Structural Aggregation of classes
Object-Structural Aggregation of objects

Examples:

 Adapter
 Bridge
 Composite
 Decorator
 Facade
 Flyweight
 Proxy

🔹 3. Behavioral Patterns

 Purpose: Define communication patterns between objects/classes


 Help distribute object responsibilities, intelligence, and logic

Type Description
Class-Behavioral Use inheritance to share behavior
Object-Behavioral Use composition to share behavior

Examples:

 Chain of Responsibility
 Command
 Interpreter
 Iterator
 Mediator
 Memento
 Observer
 State
 Strategy
 Template Method
 Visitor

In the upcoming section, one example pattern from each category will be explained using the GoF pattern
format.

Would you like a summary table, PDF version, or visual aids (e.g., diagrams for each pattern type) to go with
this content?

Lecture 27
Here is a well-formatted and organized version of Lecture No. 27 from CS504: Software Engineering – I,
covering the Observer, Singleton, and Façade design patterns:

📚 Lecture No. 27 – Design Patterns

🔁 Observer Pattern
🔖 Name

 Observer

🎯 Intent

 Define a one-to-many (or many-to-many) dependency between objects.


 When one object (subject) changes state, all its dependents (observers) are notified and updated
automatically.

Also referred to as a Publish-Subscribe mechanism.

⚙️Motivation

 Promotes separation of concerns: different parts of a system (like data and GUI) can operate
independently.
 Supports dynamic and automatic updates to dependent objects.

Example: MVC (Model-View-Controller) in Smalltalk:

 Model = data
 View = GUI
 Controller = mediator
 Observer Pattern enables synchronization between model and views.

📝 Description

 Use when multiple views of a single state are needed.


 Example: Spreadsheet and bar chart representing the same data source.

✅ Consequences

 Simplifies consistency across views.


 Enables independent reuse of data and views.
 Can be inefficient when frequent updates are needed (performance optimization becomes difficult).

🧱 Structure
+--------------------+
| Subject |
|--------------------|
| + Attach(o) |
| + Detach(o) |
| + Notify() |
+--------------------+
|
+-------+--------+
| |
+------------------+ +---------------------+
| Observer | | ConcreteObserver |
|------------------| |---------------------|
| + Update() | | - observerState |
+------------------+ | + Update() |
+---------------------+
^
|
+---------------------+
| ConcreteSubject |
|---------------------|
| - subjectState |
| + GetState() |
| + SetState() |
+---------------------+

👥 Participants

Component Responsibility
Subject Maintains a list of observers and notifies them of state changes.
Observer Defines the interface for receiving updates.
ConcreteSubject Stores the actual state and notifies observers when it changes.
ConcreteObserver Maintains state consistent with the subject and updates itself accordingly.

Singleton Pattern
🎯 Intent

 Ensure a class has only one instance, and provide a global access point to it.

📌 Applicability

Use Singleton when:

 There must be exactly one instance of a class.


 The single instance must be easily accessible globally.
 You need to control the number of instances.
 The instance must be extensible via subclassing.

🧱 Structure
+---------------------+
| Singleton |
|---------------------|
| - static _instance |
|---------------------|
| + Instance() |
| + SingletonOp() |
+---------------------+

👥 Participants

 Singleton:
o Provides a static method for access.
o Ensures only one instance exists.
o May create and manage the unique instance.

💻 Example Code (C++)


class Singleton {
public:
static Singleton* Instance();
protected:
Singleton(); // Constructor is protected
private:
static Singleton* _instance;
};

// Implementation
Singleton* Singleton::_instance = 0;

Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}

Clients call Singleton::Instance() to access the single instance.

🧱 Façade Pattern
🎯 Intent

 Provide a unified interface to a set of interfaces in a subsystem.


 Façade simplifies usage by acting as a higher-level interface.

📌 Applicability

Use Façade when:

 You want a simple interface for a complex subsystem.


 There are many dependencies between clients and the subsystem.
 You want to decouple subsystems from clients.
 You want to layer your subsystem architecture.

🧱 Structure
+------------+
| Client |
+------------+
|
v
+------------+
| Façade |
+------------+
/ | \
/ | \
Sub1 Sub2 Sub3

👥 Participants

Component Responsibility
Façade Knows which subsystems are responsible for a request and delegates to them.
Subsystem Classes Implement specific subsystem functions; unaware of Façade.

🧩 Summary of Patterns

Pattern Type Purpose


Observer Behavioral Maintain consistency between related objects automatically.
Singleton Creational Ensure only one instance of a class exists.
Façade Structural Provide a simplified interface to a complex system.
Would you like a visual PDF version or summary flashcards to go along with these notes?

Lecture 28

Here is your content reformatted for clarity and structure, without changing any wording:

Lecture No. 27 – Observer Pattern

Name

 Observer

Basic Intent

 It is intended to define a many-to-many relationship between objects so that when one object changes
state, all its dependents are notified and updated automatically.
 Dependence/publish-subscribe mechanism in programming languages:
o Smalltalk being the first pure Object-Oriented language in which observer pattern was used in
implementing its Model View Controller (MVC) pattern. It was a publish-subscribe mechanism
in which views (GUIs) were linked with their models (containers of information) through
controller objects.
o Therefore, whenever underlying data changes in the model objects, the controller would notify
the view objects to refresh themselves and vice versa.
o MVC pattern was based on the observer pattern.

Motivation

 It provides a common side effect of partitioning a system into a collection of cooperating classes that
need to maintain consistency between related objects.

Description

 This can be used when multiple displays of state are needed.

Consequences

 Optimizations to enhance display performance are impractical.

Example Scenario

Many graphical user interface toolkits separate the presentational aspects of the user interface from the
underlying application data. Classes defining application data and presentations can be reused independently.
They can work together, too.

Both a spreadsheet object and bar chart object can depict information in the same application data object using
different presentations. The spreadsheet and the bar chart don’t know about each other, thereby letting you reuse
only the one you need. But they behave as though they do. When the user changes the information in the
spreadsheet, the bar chart reflects the changes immediately, and vice versa.

Structure
Subject

 Attach(Observer)
 Detach(Observer)
 Notify()

Observer

 Update()

ConcreteObserver

 Update()
 observerState

ConcreteSubject

 GetState()
 SubjectState

Workflow

return SubjectState
for all o in observers
o -> Update()
observerState = subject -> GetState()

Participants

Subject

 Knows its observers. Any number of Observer objects may observe a subject.
 Provides an interface for attaching and detaching Observer objects.

Observer

 Defines an updating interface for objects that should be notified of changes in a subject.

ConcreteSubject

 Stores state of interest to ConcreteObserver objects.


 Sends a notification to its observers when its state changes.

ConcreteObserver

 Maintains a reference to a ConcreteSubject object.


 Stores state that should stay consistent with the subject’s.
 Implements the Observer updating interface to keep its state consistent with the subject’s.

Singleton Pattern

Intent

 It ensures that a class only has one instance and provides a global point of access to it.

Applicability

 When there must be exactly one instance of a class and it must be accessible to clients from a well-
known access point.
 When controlling the total number of instances that would be created for a particular class.
 When the sole instance should be extensible by subclassing and clients should be able to use an
extended instance without modifying their code.
Structure

Singleton

 static instance()
 SingletonOperation()
 GetSingletonData()

static uniqueInstance
singletonData
return uniqueInstance

Participants

Singleton

 Defines an instance operation that lets clients access its unique instance.
 May be responsible for creating its own unique instance.

Singleton Pattern Example

class Singleton {
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
};

Singleton* Singleton::_instance = 0;

Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}

Clients access the singleton exclusively through the Instance member function.

Façade Pattern

Intent

 Provides a unified interface to a set of interfaces in a subsystem.


 Façade defines a higher-level interface that makes a subsystem easier to use.

Applicability

 When you want to provide a simple interface to a complex subsystem.


 When there are many dependencies between clients and implementation classes.
 To decouple the system from clients and other subsystems.
 To layer your subsystem.

Abstract Example of Façade


Structuring a system into subsystems helps reduce complexity. A common design goal is to minimize
communication and dependencies between subsystems. One way to achieve this is to introduce a façade object
that provides a single, simplified interface to the more general facilities of a subsystem.

Structure

Façade

 Delegates client requests to appropriate subsystem objects.

Subsystem Classes

 Implement subsystem functionality.


 Handle work assigned by the Façade object.
 Have no knowledge of the Façade (i.e., they keep no references to it).

If you'd like the next section (on Self-Documenting Code and Naming Conventions) reformatted as well, just let
me know!

Here’s a comparative summary of all interaction diagram patterns and concepts discussed in your lecture
on "Interaction Diagrams – Depicting Dynamic Behavior of the System" in a tabular format for easy
memorization and revision:

✅ Comparison of UML Interaction Diagram Concepts

Collaboration Message Between Activation


Aspect Sequence Diagram Self-Calls
Diagram Objects Box
Shows Indicates
Shows object Models Models message
interaction based execution
Purpose interaction in time communication an object sends
on object duration of a
sequence between objects to itself
organization message
Emphasizes the Highlights
Emphasizes
Time-order of Structure/links need for internal
Focus processing
messages between objects association & operations of an
time
visibility object
Drawn as a
Shown as arrows Shown as looped
Objects on X-axis, Objects as nodes narrow
Layout from sender → arrow back to
Time on Y-axis with links vertical
receiver same object
rectangle
Starts when
Emphasizes how May include Shows object
Vertical timeline message is
Visualization objects are conditions, behavior
showing message flow received, ends
connected iterations dependency
when done
Object must be Drawn on the
Object Box with Box with object Objects must be
able to reference object’s
Representation instance:ClassName name known/accessible
itself lifeline
Models
Better for Ensures object Helps analyze
Use Case Better for complex recursive or
overview of behavior is valid performance
Suitability time-based scenarios repeated
interactions within structure or blocking
internal logic
Should comply Helps see
Call, Return, Used in utility
Similar, but with OOP synchronous
Message Types Conditional, Iterative, methods,
focus on links scope/association or delayed
Recursive validation logic
rules calls
N/A (but
Yes – with Conditional
Not as Yes – via message duration
Conditions/Loops [condition] and * for logic can be
expressive label reflects
iteration modeled
complexity)
Strengths Clear temporal Clear structural Encourages proper Great for Clarifies
visualization of understanding of OOP interaction explaining system timing,
Collaboration Message Between Activation
Aspect Sequence Diagram Self-Calls
Diagram Objects Box
internal
process flow collaboration design concurrency
responsibilities
May be misused if
Misleading if Can clutter
Can become crowded Less emphasis object
Limitations overused for diagram if too
with many objects on time sequence accessibility is
basic operations many overlaps
ignored

✅ Quick Summary Notes

 Sequence Diagrams = What happens, when, and in what order?


 Collaboration Diagrams = Which objects are involved and how are they connected?
 Messages = Must respect visibility, scope, and association rules
 Self-Calls = Internal message for reuse or recursion
 Activation Box = Shows duration of task execution by the object

Let me know if you’d like:

 📄 This table as a PDF or printable sheet


 🎓 Turned into a quiz or flashcards
 🧠 Included in your exam notes or cheat sheet

Lecture 29

Here is a simplified and easy-to-memorize format for Lecture No. 29: File Handling Tips & Coding
Practices in Java and C++, categorized and bullet-pointed for quick revision:

📘 Lecture 29 Summary – Java & C++ Tips

🔹 10.4 File Handling Tips

✅ File Extensions

 C++ Header: .h
 C++ Source: .c++ (preferred), .C, .cc, .cpp
 Example: MyClass.c++, MyClass.h

✅ Class Declaration

 Each class → its own .h file (same name as class)


 Private helper classes → inner classes
 No method definitions in .h (except inline)

// ❌ Wrong in header
int getValue() { return value_; }

✅ Avoid Special Characters

 No TAB, page break characters


 They create issues across platforms/editors

🔹 Include Guards (C++)

Use to avoid multiple inclusions:

#ifndef MODULE_FILENAME_H
#define MODULE_FILENAME_H
// content
#endif

🔹 Class & Interface Layout

1. Documentation
2. class or interface declaration
3. Static Vars: public → protected → package → private
4. Instance Vars: same order
5. Constructors
6. Methods (any order)

🔹 10.5 Java & C++ Code Practices


✅ Types

 Always use explicit type casts


 float f = (float) intVal; // ✅ Good
 Use public → protected → private order in classes

✅ Variables

1. Initialize where declared


2. Single purpose only (no dual meaning)
3. Avoid public class variables (except structs)
4. Group related vars, separate unrelated ones:
5. float x, y, z; // related ✅
6. float janRev, febRev, marRev; // related ✅
7. Minimize variable scope
8. No global variables
9. Avoid implicit checks:
10. if (val != 0.0) // ✅

🔁 Loops

1. Only loop control in for header:


2. for (i = 0; i < 100; i++) sum += value[i];
3. Init loop vars just before the loop
4. Avoid do-while loops
5. Avoid break / continue unless more readable
6. Empty loop: use for(;;) not while(true)

🔄 Conditionals

1. Break complex conditions into booleans:


2. boolean isFinished = (n < 0) || (n > max);
3. if (isFinished) { ... }
4. Keep normal case in if, error in else
5. Separate line for conditionals:
6. if (isDone)
7. cleanup();
8. Avoid assignments inside conditions:
9. file = openFile("data.txt");
10. if (file != null) { ... }

🔸 Miscellaneous

1. Avoid magic numbers, use named constants


2. Float constants → always with .0
3. double speed = 3.0e8; // ✅
4. Use 0.5, not .5 (clearer)
5. In C++, always specify return type
6. int getValue(); // ✅
7. Avoid goto, unless no readable alternative

🔁 Quick Recap Mnemonics


Area Rule Tip
Files Match .h with class name MyClass.h for class MyClass
Loops Avoid do-while, break, continue Use for(;;) for infinite loops
Variables No global or public class vars Private + Accessors
Conditionals Split complex logic Use temp booleans
Types Explicit casting only No assumptions!
Formatting Avoid special chars (TAB, etc.) Cross-platform safe

Let me know if you'd like this turned into a printable cheat sheet or flashcards for even easier memorization.

Lecture 30

Here's an easy-to-memorize summary of:

✅ Lecture No. 309

10.6–10.8: Layout, Comments, Expressions, Shortcuts in Java & C++

🔹 10.6 COMMENTS (Less is More)

Rule Tip
Language Write all comments in English
⚠️Avoid lies Comments can become outdated → prefer self-explanatory code

↪️Indentation
✅ Use // Even for multi-line comments, not /* */
Comments should be aligned with code
🧠 Rewriting > Commenting Rewrite tricky code instead of over-commenting

🔹 10.7 EXPRESSIONS & STATEMENTS

🔸 Layout

Rule Tip
⬅️Indentation Use 2 spaces for indentation (clear yet compact)
📏 Readable expressions Code should read like a sentence
❗ Avoid ! in logic Use natural logic → if (x >= y) not if (!(x < y))

🔸 Parentheses

Do Don't
if ((x & MASK) == BITS) if (x & MASK == BITS)
Add brackets to clarify logic Don’t rely on operator precedence

🔸 Complex Logic? Break It!

// ❌ Hard to read
*x += (*xp = (2*k < (n-m) ? c[k+1] : d[k--]));

// ✅ Clear version
if (2*k < n - m)
*xp = c[k+1];
else
*xp = d[k--];
*x = *x + *xp;

🔹 10.8 SHORTCUTS & CRYPTIC CODE — ❌ AVOID!

Example Why It's Bad Better Alternative


x *= a + b;
Looks like x = x*a + b → x = x * (a + b);
confusing
subkey >> (bitoff -
(bitoff>>3)<<3) Obscure mask logic subkey >> (bitoff & 0x7);
a = a >> 2; Reader thinks bit magic a = a / 4;
Add comments or clearer
(rear + 1) % MAX_SIZE Circular logic needs clarity
names

✅ KEY MEMO TIPS

🧠 Prefer clarity over cleverness


🧾 Use meaningful names instead of comments
⚙️Write code like it’ll be read more than written
🔍 Add parentheses to prevent invisible bugs
🪓 Break long statements into small steps

Let me know if you'd like a one-page cheatsheet, flashcards, or visual infographic for this!

Here’s a detailed clarification of all the patterns and tips discussed in Sections 10.6, 10.7, and 10.8 of your
lecture:

🔶 10.6 — COMMENTS (Less is More)


🎯 Key Concept:

Use minimal but meaningful comments — let your code explain itself.

Aspect Explanation
All comments must be written in English to maintain consistency and readability in
🔤 Language
professional environments.
Too many comments make the code noisy. If the code is self-explanatory, no
❌ Avoid over-
comment is needed. Example:✅ totalPrice = unitPrice * quantity; (clear
commenting
enough, no comment needed)
🚫 Don’t rely on
Rewrite confusing code instead of adding comments to explain it. Comments don’t
comments to explain bad
fix confusing logic.
code
✅ Use // for all Even if it’s a multi-line comment. Avoid using /* */ because:- It’s error-prone-
comments Not ideal in nested comments
📐 Align comments with Keep comments at the same indentation level as the code to improve structure and
code clarity.
Outdated or incorrect comments are dangerous — they mislead future developers.
⚠️Don’t let comments lie
Always update or delete old ones.

🔶 10.7 — EXPRESSIONS AND STATEMENTS


🧱 Code Layout

Aspect Explanation
✨ Readable Write code that flows like natural language. This makes it easier for others (and your
expressions future self) to understand.
↔️Use consistent Avoid cramming code. Use 2 spaces per indentation level. This is more compact and
Aspect Explanation
spacing readable than 4.
Don’t use !(x < y) — instead, use x >= y which is clearer and closer to natural
❗ Avoid negated logic
language.

🔁 Parentheses Usage

 Use parentheses to clarify precedence even if you know how operators associate.
 Avoid code that requires memorizing operator precedence.

Example Explanation
✅ if ((x & MASK) == BITS) Clear and predictable
❌ if (x & MASK == BITS) This is misleading and may behave unexpectedly due to precedence rules

🧩 Break Complex Expressions

Long or cryptic expressions = hard to understand and harder to debug.

❌ Complex Expression (Confusing)

*x += (*xp = (2*k < (n-m) ? c[k+1] : d[k--]));

✅ Simplified (Understandable)

if (2 * k < n - m)
*xp = c[k+1];
else
*xp = d[k--];
*x = *x + *xp;

💡 Why?: The simplified version separates control logic, pointer assignment, and arithmetic into steps —
easy to debug and maintain.

🔶 10.8 — SHORTCUTS & CRYPTIC CODE — AVOID!


🔥 Don't Be Over-Smart

Clever or cryptic code might impress you, but confuses others — and even you later.

Pattern Why It's Bad Better


x *= a + b;
Looks like x = x*a + b but it’s x = x * (a + b);
actually x = x * (a + b)
a = a >> 2;
May confuse readers; looks like bit- a = a / 4;
level hack
subkey >> (bitoff - Complex mask operation, hard to subkey >> (bitoff & 0x7);
(bitoff >> 3) << 3) understand
(rear + 1) % MAX_SIZE
Used in circular buffers; still unclear Add comment: // move to next slot
without context in circular buffer

🧠 Final Summary (Quick Revision)


✅ Do This ❌ Not This
Use self-explanatory variable names Write lots of unnecessary comments
Break complex logic into steps Use one-liner smart code
Add parentheses even if not strictly needed Rely on operator precedence
Write readable logic Use negated conditions
Use // for all comments Use /* */ especially for multiple lines

Let me know if you want:


 A printable PDF summary
 Flashcards for quick revision
 Practice questions based on this lecture

Lecture 31

Here’s a detailed clarification of the coding style concepts discussed in Lecture No. 319 — focusing on:

1. switch statements
2. Magic numbers
3. Use (or abuse) of zero

🔶 1. switch Statement — Prefer Clarity Over Cleverness


📌 Problem with fall-through

❌ Confusing version:

switch(c) {
case '-': sign = -1;
case '+': c = getchar();
case '.': break;
default:
if (!isdigit(c)) return 0;
}

 This version relies on fall-through (the control falling through one case into the next), which is hard to
understand, especially for beginners.
 It’s bug-prone because a missing break can unintentionally affect logic.

✅ Better version (explicit breaks):

switch(c) {
case '-':
sign = -1;
c = getchar();
break;
case '+':
c = getchar();
break;
case '.':
break;
default:
if (!isdigit(c)) return 0;
break;
}

 Here, every case is clearly separated.


 No accidental fall-through.

✅ Even Better: Use if-else for clarity

if (c == '-') {
sign = -1;
c = getchar();
}
else if (c == '+') {
c = getchar();
}
else if (c != '.' && !isdigit(c)) {
return 0;
}

 This version is easier to understand and allows more flexible logic.


 Especially preferred when different branches have different logic.
🔶 2. Magic Numbers — ❌ Avoid Hardcoded Numbers
📌 What are Magic Numbers?

Magic numbers are numeric values hardcoded into the program with no explanation of their meaning or
purpose.

❌ Problematic code:

fac = lim / 20;


for (i = 0; i < 27; i++) {
col += 3;
k = 21 - (let[i] / fac);
...
}
draw(23, 1, '*');

 ❓ What is 20? Why 27? What does 21 mean?


 These numbers might be meaningful to the programmer, but are not self-explanatory to others (or even
yourself later).

✅ Refactored using Named Constants

enum {
MINROW = 1,
MINCOL = 1,
MAXROW = 24,
MAXCOL = 80,
LABELROW = 1,
NLET = 26,
HEIGHT = MAXROW - 4,
WIDTH = (MAXCOL - 1) / NLET
};

fac = (lim + HEIGHT - 1) / HEIGHT;


if (fac < 1) fac = 1;

for (i = 0; i < NLET; i++) {


if (let[i] == 0) continue;
for (j = HEIGHT - let[i] / fac; j < HEIGHT; j++) {
draw(j - 1 + LABELROW, (i + 1) * WIDTH, '*');
}
}
draw(MAXROW - 1, MINCOL + 1, ' ');

 Now it's clear what each number represents.


 The code is easier to read and modify.

🔶 3. Use (or Abuse) of 0


📌 Problem: Overuse of plain 0

❌ Old-Style C Practice:

flag = 0; // is it a boolean?
str = 0; // is this a null pointer?
name[i] = 0; // is this string termination?
x = 0; // integer or float?

 Here, the same literal 0 is used to mean:


o false
o NULL
o '\0'
o 0.0

🧠 This leads to ambiguity and makes the programmer guess the intent.
✅ Better: Use explicit constants and types

flag = false; // boolean


str = NULL; // pointer
name[i] = '\0'; // string termination
x = 0.0; // floating-point
i = 0; // integer

 Now, the code is self-explanatory.


 It’s easier for others to understand what’s being done and why.

✅ Best Practices Summary


Concept Good Practice Avoid
switch usage Always use break; prefer if-else when logic is complex Fall-through cases unless intentional
Magic numbers Replace with named constants or enums Hardcoding numbers
Use of zero Use false, NULL, '\0', 0.0 Using 0 for all types

💡 Rule of Thumb:

“Code should communicate intent, not just functionality.”

Would you like a refactored version of any example in your own code or a printable cheatsheet for all these
rules?

Lecture 32

Here’s a detailed clarification and summary of the coding principles covered in Lecture No. 329, focusing
on:

🔷 10.9 Clarity Through Modularity


✅ Principle:

Break large functions into smaller, logically meaningful ones to improve readability, maintainability, and
reuse.

📌 Example 1: selectionSort without modularity (less clear)


void selectionSort(int a[], int size) {
int i, j, temp, min;
for (i = 0; i < size - 1; i++) {
min = i;
for (j = i + 1; j < size; j++) {
if (a[j] < a[min])
min = j;
}
temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}

 Everything is packed into one block.


 Logic is harder to follow.

✅ Improved: Modular version


void swap(int &x, int &y) {
int temp = x;
x = y;
y = temp;
}

int minimum(int a[], int from, int to) {


int min = from;
for (int i = from + 1; i <= to; i++) {
if (a[i] < a[min])
min = i;
}
return min;
}

void selectionSort(int a[], int size) {


for (int i = 0; i < size; i++) {
int min = minimum(a, i, size - 1);
swap(a[i], a[min]);
}
}

 🎯 Each function is clear and focused.


 🔁 Reusable functions (swap, minimum).
 📚 Easier to read, debug, and test.

📌 Example 2: quickSort before modularization (harder to follow)


void quickSort(int a[], int left, int right) {
int i = left - 1, j = right + 1;
int pivot = a[(left + right)/2];

if (left < right) {


do {
do i++; while (a[i] < pivot);
do j--; while (a[j] > pivot);
if (i < j) swap(a[i], a[j]);
} while (i < j);

swap(a[left], a[j]);
quickSort(a, left, j);
quickSort(a, j + 1, right);
}
}

✅ Modular quickSort
void quickSort(int a[], int left, int right) {
if (left < right) {
int p = partition(a, left, right);
quickSort(a, left, p - 1);
quickSort(a, p + 1, right);
}
}

int partition(int a[], int left, int right) {


int pivot = a[left];
int i = left + 1;
int j = right;

while (i <= j) {
while (i <= right && a[i] < pivot) i++;
while (j >= left && a[j] >= pivot) j--;
if (i < j) swap(a[i], a[j]);
}

swap(a[left], a[j]);
return j;
}

 🎯 Logic is now split into digestible chunks.


 👓 Easier to understand.
 🔁 partition is reusable elsewhere if needed.
🔷 10.10 Short-Circuiting in && and ||
✅ Principle:

Short-circuiting prevents unnecessary or unsafe evaluation.

// Correct use of short-circuiting


while (ptr != NULL && ptr->data < myData) {
// safe to access ptr->data
}

❌ Incorrect order — leads to runtime error (crash):


while (ptr->data < myData && ptr != NULL) {
// ERROR: Accessing ptr->data before checking if ptr is NULL
}

🔍 Why it matters:

 In a && b, if a is false, b is not evaluated.


 In a || b, if a is true, b is not evaluated.
 This can be used to guard unsafe operations (like dereferencing pointers).

🔷 10.11 Operand Evaluation Order and Side Effects


✅ Principle:

Avoid writing expressions where function evaluation order and side effects impact correctness.

📌 Side Effect:

A function changes a value outside its scope, in addition to returning a value.

❌ Problem Example:
int f1(int &x) {
x = x * 2;
return x + 1;
}

int f2(int &y) {


y = y / 2;
return y - 1;
}

a = 3;
c = f1(a) + f2(a); // Problem!

❗ Undefined behavior:

C++ does not guarantee order of f1(a) vs f2(a).

 If f1 runs first:
o a becomes 6 → f1(a) = 7
o then f2(a) = 2 → c = 7 + 2 = 9
 If f2 runs first:
o a becomes 1 → f2(a) = 0
o then f1(a) = 3 → c = 0 + 3 = 3

🧠 Solution:

 Never write functions with side effects on shared data inside compound expressions.
 Split such expressions into separate statements:

int r1 = f1(a);
int r2 = f2(a); // May already be changed by f1
c = r1 + r2;

✅ Summary Table
Topic Good Practice Avoid
Modularity Break logic into small functions Long, monolithic functions
Short-circuiting Use guards (e.g., ptr != NULL && ptr->data Unsafe order (e.g., ptr->data < x
(&&) < x) && ...)
Combining functions with shared side
Side effects Avoid side effects in expressions
effects
Evaluation Order Break into separate statements for clarity Relying on unspecified evaluation order

Would you like a visual cheat sheet or code conversion of your own examples based on these practices?

Lecture 33

Here’s a detailed clarification and summary of Lecture No. 339, focusing on:

🔷 Common Coding Mistakes Due to Side Effects


Side effects occur when operations (especially in expressions) do more than just return a value — such as
modifying variables. This can lead to unpredictable behavior, particularly in C/C++ where evaluation order
is often unspecified.

⚠️Common Mistakes

1. Post-Increment in Indexing

array[i++] = i;

 ❗ Unclear whether i is incremented before or after assignment.


 If i = 3, then:
o array[3] = 4 or
o array[3] = 3 depending on evaluation.

2. Multiple Side-Effect Assignments

array[i++] = array[i++] = x;

 ❌ Evaluation order is undefined.


 Outcome depends on how the compiler handles i++.

3. Misuse of the Comma , Operator

int i, j = 0; // Only j is initialized to 0. i is uninitialized!


a = b, c = 0; // Only c = 0; a = b evaluated separately

 ✅ , used in declarations is OK:


 int x = 1, y = 2; // Both initialized
 ❌ But mixing , and assignment leads to misleading code.

✅ Guidelines to Avoid Side Effects


Rule # Guideline
1️⃣ Never use , except in declarations
2️⃣ Avoid initializing multiple variables in a single statement
3️⃣ Avoid multiple assignments in a single statement
4️⃣ Be cautious with functions that change parameter values
5️⃣ Avoid functions that both modify input and return a value

🔷 Performance Considerations
✅ 80/20 Rule (Pareto Principle)

80% of execution time is spent in 20% of the code.

 Profile the code first — don’t blindly optimize everything.


 Target bottlenecks (a.k.a. hot spots) for optimization.

📊 Performance Profiling Example: isspam function

Cycles Calls Function


11.3B 4.83M strchr
1.52B 4.61M strncmp
648M 2.17M strstr
456M 2.17M strlen
21.9M 28.5M isspam

🔍 Observations:

 Majority of time is spent in library string functions.


 All three (strchr, strncmp, strlen) were called from strstr.

🛠 Optimization Strategy

Step 1: Replace strstr with a custom version

 Gained some speed, but now 99.8% of time is spent in new strstr.

Step 2: Replace strchr, strncmp, strstr with a more efficient version using memcmp.

 🔁 Reduced loops, used a more direct memory comparison.

Cycles Function Notes


880M memcmp Replaced several string calls
665M isspam Faster overall execution
140K strlen Called only 652 times now

📌 Loop Optimization Example


for (j = i; j < MAX_FIELD; j++)
clear(j);

❌ Problem:

 MAX_FIELD = 200, but often only 2–3 fields needed to be cleared.


 50% of time wasted in this loop.

✅ Optimized:

for (j = i; j < maxField; j++)


clear(j);
 Used actual maxField count instead of constant.
 🔽 Execution time dropped by half.

✅ Summary Table: Common Pitfalls & Solutions


Mistake / Problem Why It’s a Problem Solution / Best Practice
array[i++] = i; Evaluation order ambiguous Avoid side effects in expressions
array[i++] = array[i++] = x; Unspecified behavior Split into multiple, clear steps
int i, j = 0; Only j initialized Declare and initialize separately
Misleading usage of ,
a = b, c = 0; Avoid mixed assignments
operator
Mixing assignment + side-effect in Use pure functions or isolate side
Creates unexpected behavior
functions effects
Optimizing everything blindly Wastes time Use profiling to target bottlenecks
Looping over unnecessary range Wastes CPU cycles Optimize loop boundaries

Would you like a visual summary, checklist, or practice quiz for these topics?

Lecture 34

Here's a detailed clarification and summary of Lecture No. 349: Portability, focusing on how to write C/C+
+ code that works reliably across different platforms and compilers.

🔷 Why Portability Matters


 Porting software between different systems can be costly.
 Writing portable code from the beginning helps minimize effort during migration.
 Avoid platform-dependent features and stick to standardized code constructs.

✅ Key Guidelines for Writing Portable C/C++ Code


1. Stick to the Standard

✅ Recommended ❌ Avoid
ANSI/ISO standard C++ Compiler- or vendor-specific extensions
Use STL (Standard Template Library) Custom libraries tied to platforms

2. Use Function Prototypes

Even though C++ allows old-style declarations, always use proper prototypes:

double sqrt(); // ❌ Old C-style — avoid


double sqrt(double); // ✅ ANSI-compliant

3. Watch Out for Data Type Sizes

Data types like int, long, short vary in size across platforms:

int i = j + k; // May overflow if int is 2 bytes

✅ Solution: Use fixed-size types from <cstdint> like:

#include <cstdint>
int32_t i, j, k;
4. Be Careful with Evaluation Order

Evaluation order for expressions like:

a = b++ + func(c++);

... is unspecified, leading to different behavior on different compilers.

✅ Best Practice: Avoid expressions with side effects in the same statement.

5. Signedness of char

The char type may be signed or unsigned depending on the compiler.

char c = getchar();
if (c == EOF) // ❌ Might fail if c is unsigned

✅ Use int for getchar():

int c = getchar();
if (c == EOF)

6. Right Shift Ambiguity

The meaning of >> is compiler-dependent:

 Arithmetic Shift: Sign bit is preserved (used for signed numbers)


 Logical Shift: Zeros are filled in (used for unsigned numbers)

Java addresses this with:

 >> for arithmetic shift


 >>> for logical shift

✅ Best Practice: Avoid shifting signed numbers if behavior is unclear.

7. Byte Order (Endianness)

 Little-endian (e.g., Intel): LSB at lowest address


 Big-endian (e.g., Motorola): MSB at lowest address

🚫 Don't use binary format for data exchange between systems.

✅ Use portable formats:

 Text (CSV, JSON, XML)


 Consider internationalization (I18n); don’t assume ASCII or English

8. Structure Alignment

Different compilers/platforms align structure members differently:

struct X {
char c;
int i;
};

 Address of i may not be right after c.


 Typecasting and pointer arithmetic across structure members is non-portable.

✅ Best Practice: Don’t assume specific layout in memory.


9. Bit Fields

Bit fields are non-portable due to:

 Signedness ambiguity
 Bit ordering (left-to-right vs right-to-left)
 Field overlaps if too large
 Max bits depends on integer word size

Example:

struct packed_struct {
unsigned int f1:1;
unsigned int type:4;
unsigned int funny_int:9;
};

✅ Recommendation: Avoid using bit fields for portable code.

🧾 Summary Table of Portability Hazards and Recommendations


Area Hazard / Non-Portable Behavior Portable Practice
Language Standard Using non-standard extensions Stick to ANSI/ISO C++ and STL
Function Prototypes Old-style declarations Use complete, typed function prototypes
Data Type Sizes int may be 2 or 4 bytes Use <cstdint> types (e.g. int32_t)
Expression Evaluation Side effects + undefined order Break expressions into simple steps
char Signedness char may be signed or unsigned Use int for getchar()
Right Shift Operator Logical vs arithmetic shift ambiguous Avoid shifting signed integers
Byte Order Endianness varies across platforms Use text or well-defined formats
Structure Alignment Member layout varies Avoid pointer math inside structs
Bit Fields Layout, order, signedness not standard Avoid using bit fields

Would you like a checklist for writing portable code or a quiz to test your understanding of these concepts?

Lecture 35

Here's a detailed comparison table of all the coding patterns and practices discussed across your provided
lectures:

✅ Comparison of Coding Patterns & Guidelines

Bad Practice / Problematic Good Practice /


Aspect Reason / Benefit
Style Recommended Style
Using fall-through behavior in Use explicit break after each Avoids confusion and cryptic
Switch Fall-
switch cases without break case, or replace switch with if behavior; improves
Through
statements. statements. readability.
Hardcoded numeric values like Use named constants (e.g.,
Magic Enhances code clarity and
20, 27, 21, etc. without HEIGHT, NLET) or enums to
Numbers makes maintenance easier.
explanation. represent such numbers.
Assigning 0 to flags, pointers, or
Use false, NULL, '\0', 0.0 to Promotes self-documenting
Use of Zero characters directly (flag = 0;
clearly express intent. code and semantic clarity.
str = 0;)
Portability – Using non-standard extensions Stick to ANSI/ISO standard C+ Maximizes portability across
Language Use or platform-specific features. + and use STL where possible. compilers and platforms.
Use stdint.h types like
Portability – Assuming fixed sizes for int, Prevents overflow and
int32_t, or ensure portability
Data Types short, etc. ensures predictable behavior.
via careful type selection.
Signedness of Using char directly to store Use int for reading characters char may be signed or
Bad Practice / Problematic Good Practice /
Aspect Reason / Benefit
Style Recommended Style
return values from getchar() or unsigned, so EOF might
char and comparing with EOF.
for EOF checks. never match.
Relying on left-to-right Prevents undefined behavior
Order of Write side-effect-prone code in
evaluation in expressions with due to compiler-specific
Evaluation clear, sequential statements.
side effects. evaluation order.
Assuming >> behaves the same Be explicit; avoid ambiguous
Right Shift Improves clarity and avoids
for all types/platforms shift operations or use safe
Operator platform-specific bugs.
(arithmetic vs logical). masks.
Exchanging binary data across Use text formats for data Ensures correct data
Byte Order /
machines without considering exchange; be aware of byte- interpretation across
Endianness
byte order. order differences. heterogeneous systems.
Assuming struct members are Avoid manual alignment
Alignment in Prevents undefined behavior
tightly packed; using pointer assumptions; use standard
Structs and misaligned access.
arithmetic within them. access mechanisms.
Implementation-defined
Using bit-fields for compact data Avoid or minimize use of bit
Bit Fields behavior; unsafe across
storage. fields for portable code.
compilers and architectures.
Mixing normal code with error- Use structured exception
Exception Clean separation of logic and
handling logic, catching handling (try, catch, throw)
Handling – error-handling; supports
everything in main() or relying and define clear exception
General robust error tracking.
on return codes. types.
Not accounting for multiple
Exception Be aware of all exceptional Ensures predictability and
hidden paths introduced by
Complexity paths and document them. reliability.
exceptions.
No consideration of what Provide Basic, Strong, or No- Prevents resource leaks,
Exception
happens if an exception is Throw guarantees depending partial side effects, or
Safety Levels
thrown mid-function. on context. corrupted states.
Compute results first; emit side
Strong Emitting side effects (like
effects only after all operations Ensures full commit or full
Exception output) before all error-prone
that might throw have rollback behavior.
Safety operations are complete.
succeeded.
Maintains exception
Returning by value after side Use auto_ptr or smart
Return Values neutrality and ensures no side
effects; might throw and cause pointers to transfer ownership
and Exceptions effects if an exception is
inconsistencies. safely.
thrown.

🧠 Key Takeaways

 Always prioritize clarity and maintainability over clever tricks or micro-optimizations.


 Follow standardized coding styles and conventions to ease debugging, testing, and portability.
 Ensure exception safety by identifying potential throw points and managing side effects carefully.
 Replace raw data and magic values with descriptive constants or enums.
 Keep your code platform-neutral, especially when working with file I/O, memory layout, and data
exchange.

If you'd like, I can turn this into a downloadable table (PDF or CSV) or further expand any of the sections.

You might also like