๐Ÿ“Š DEVASC Topics 1.4-1.6

Software Development Methods, Code Organization & Design Patterns

1.4 Compare Software Development Methods

๐Ÿ“š Overview: Software development methodologies are frameworks that structure the development process. The three main approaches are Waterfall, Agile, and Lean.

Development Methods Comparison

graph TB A[Software Development Methods] --> B[Waterfall] A --> C[Agile] A --> D[Lean] B --> B1[Sequential Phases] B --> B2[Heavy Documentation] B --> B3[Fixed Requirements] B --> B4[Long Release Cycles] C --> C1[Iterative Development] C --> C2[Customer Collaboration] C --> C3[Adaptive Planning] C --> C4[Short Sprints] D --> D1[Eliminate Waste] D --> D2[Continuous Improvement] D --> D3[Fast Delivery] D --> D4[Respect for People] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#ff6b6b,stroke:#c92a2a,color:#fff style C fill:#51cf66,stroke:#2f9e44,color:#fff style D fill:#339af0,stroke:#1864ab,color:#fff

Waterfall Model

graph TD A[Requirements] --> B[Design] B --> C[Implementation] C --> D[Testing] D --> E[Deployment] E --> F[Maintenance] style A fill:#667eea,color:#fff style B fill:#667eea,color:#fff style C fill:#667eea,color:#fff style D fill:#667eea,color:#fff style E fill:#667eea,color:#fff style F fill:#667eea,color:#fff

๐ŸŒŠ Waterfall

Sequential & Linear

  • โœ“ Pros:
  • Clear structure
  • Easy to understand
  • Well-documented
  • Works for fixed requirements
  • โœ— Cons:
  • Inflexible
  • Late testing
  • No customer feedback
  • High risk

๐Ÿ”„ Agile

Iterative & Incremental

  • โœ“ Pros:
  • Flexible & adaptive
  • Continuous feedback
  • Fast delivery
  • Customer collaboration
  • โœ— Cons:
  • Less predictable
  • Requires discipline
  • Documentation lighter
  • Scope creep risk

โšก Lean

Value-Focused & Efficient

  • โœ“ Pros:
  • Waste elimination
  • Fast time-to-market
  • Cost-effective
  • Continuous improvement
  • โœ— Cons:
  • Requires culture shift
  • May sacrifice features
  • Needs experienced team
  • Measurement overhead

Agile Sprint Cycle

graph LR A[Sprint Planning] --> B[Daily Standups] B --> C[Development] C --> D[Sprint Review] D --> E[Sprint Retrospective] E --> A style A fill:#51cf66,stroke:#2f9e44,color:#fff style B fill:#51cf66,stroke:#2f9e44,color:#fff style C fill:#51cf66,stroke:#2f9e44,color:#fff style D fill:#51cf66,stroke:#2f9e44,color:#fff style E fill:#51cf66,stroke:#2f9e44,color:#fff

Detailed Comparison Table

Aspect Waterfall Agile Lean
Approach Sequential phases Iterative sprints Continuous flow
Planning Upfront & detailed Adaptive & ongoing Just-in-time
Requirements Fixed at start Evolving Minimal viable
Customer Involvement Beginning & end Continuous Frequent
Testing After development Throughout Continuous
Delivery Single release Incremental releases Continuous delivery
Best For Fixed scope projects Evolving projects Startups, MVPs
Team Size Any size Small to medium Small teams

Agile Manifesto Values

๐Ÿ‘ฅ Individuals over Processes
๐Ÿ’ป Working Software over Documentation
๐Ÿค Customer Collaboration over Contracts
๐Ÿ”„ Responding to Change over Plans

Lean Principles

1. Eliminate Waste

Remove anything that doesn't add value to the customer

2. Build Quality In

Prevent defects rather than finding them later

3. Create Knowledge

Learn continuously and share knowledge

4. Defer Commitment

Decide as late as possible with maximum information

5. Deliver Fast

Shorten cycle time and deliver quickly

6. Respect People

Empower the team and respect their expertise

๐Ÿ’ก Choosing the Right Method:
  • Use Waterfall for: Well-defined projects, regulatory environments, fixed budgets
  • Use Agile for: Complex projects, evolving requirements, frequent releases
  • Use Lean for: Startups, MVPs, resource constraints, rapid innovation
  • Many organizations use hybrid approaches combining elements from multiple methodologies

1.5 Benefits of Organizing Code

๐Ÿ”„ Overview: Organizing code into functions, classes, and modules improves maintainability, reusability, and readability. It's a fundamental principle of software engineering.

Code Organization Hierarchy

graph TB A[Application] --> B[Modules/Packages] B --> C[Classes] C --> D[Methods] D --> E[Functions] B --> B1[Separate files/folders] C --> C1[Related data & behavior] D --> D1[Class-specific operations] E --> E1[Reusable operations] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#51cf66,stroke:#2f9e44,color:#fff style C fill:#339af0,stroke:#1864ab,color:#fff style D fill:#ff6b6b,stroke:#c92a2a,color:#fff style E fill:#ffd43b,stroke:#fab005,color:#000

1. Functions/Methods

โœ… Benefits

  • Reusability: Write once, use many times
  • Modularity: Break down complex problems
  • Readability: Named operations are self-documenting
  • Testing: Easy to test individual functions
  • Maintenance: Changes in one place

๐Ÿ“ Example: Without Functions

# Calculate area - repeated code
length1 = 10
width1 = 5
area1 = length1 * width1
print(area1)

length2 = 8
width2 = 4
area2 = length2 * width2
print(area2)

โœ… Example: With Functions

def calculate_area(length, width):
    return length * width

# Reusable and clear
area1 = calculate_area(10, 5)
area2 = calculate_area(8, 4)
print(area1)
print(area2)

2. Classes

classDiagram class NetworkDevice { +String hostname +String ip_address +String status +connect() +disconnect() +send_command(cmd) } class Router { +List interfaces +configure_ospf() +show_routing_table() } class Switch { +List vlans +configure_vlan() +show_mac_table() } NetworkDevice <|-- Router NetworkDevice <|-- Switch style NetworkDevice fill:#667eea,color:#fff style Router fill:#51cf66,color:#fff style Switch fill:#339af0,color:#fff

โœ… Class Benefits

  • Encapsulation: Bundle data with methods
  • Inheritance: Reuse and extend behavior
  • Polymorphism: Same interface, different implementations
  • Abstraction: Hide complex details
  • Organization: Group related functionality

๐Ÿ“ Class Example

class NetworkDevice:
    def __init__(self, hostname, ip):
        self.hostname = hostname
        self.ip = ip
        self.status = "disconnected"
    
    def connect(self):
        self.status = "connected"
        return f"Connected to {self.hostname}"
    
    def get_info(self):
        return {
            "hostname": self.hostname,
            "ip": self.ip,
            "status": self.status
        }

# Usage
router = NetworkDevice("R1", "192.168.1.1")
router.connect()
print(router.get_info())

3. Modules

graph TB A[Application] --> B[network_utils.py] A --> C[database.py] A --> D[api_client.py] A --> E[config.py] B --> B1[connect_device] B --> B2[send_command] B --> B3[parse_output] C --> C1[connect_db] C --> C2[query] C --> C3[insert] D --> D1[get_request] D --> D2[post_request] E --> E1[load_config] E --> E2[save_config] style A fill:#667eea,color:#fff style B fill:#51cf66,color:#fff style C fill:#339af0,color:#fff style D fill:#ff6b6b,color:#fff style E fill:#ffd43b,color:#000

โœ… Module Benefits

  • Separation of Concerns: Each module has a specific purpose
  • Namespace: Avoid naming conflicts
  • Reusability: Import and use in multiple projects
  • Maintainability: Find and fix code easily
  • Collaboration: Team members work on different modules

๐Ÿ“ Module Structure

# network_utils.py
def connect_device(ip, username, password):
    # Connection logic
    pass

def send_command(device, command):
    # Command execution
    pass

# main.py
import network_utils

device = network_utils.connect_device(
    "192.168.1.1", "admin", "pass"
)
result = network_utils.send_command(
    device, "show ip route"
)

Code Organization Principles

DRY - Don't Repeat Yourself
KISS - Keep It Simple, Stupid
YAGNI - You Ain't Gonna Need It
Single Responsibility Principle
Separation of Concerns
High Cohesion, Low Coupling

Complete Example: Well-Organized Code

# config.py
DATABASE_URL = "postgresql://localhost/mydb"
API_KEY = "your-api-key"

# database.py
import psycopg2
from config import DATABASE_URL

class Database:
    def __init__(self):
        self.conn = None
    
    def connect(self):
        self.conn = psycopg2.connect(DATABASE_URL)
    
    def query(self, sql):
        cursor = self.conn.cursor()
        cursor.execute(sql)
        return cursor.fetchall()

# api_client.py
import requests
from config import API_KEY

class APIClient:
    def __init__(self, base_url):
        self.base_url = base_url
        self.headers = {"Authorization": f"Bearer {API_KEY}"}
    
    def get(self, endpoint):
        url = f"{self.base_url}/{endpoint}"
        return requests.get(url, headers=self.headers)

# main.py
from database import Database
from api_client import APIClient

# Clean, organized, and maintainable!
db = Database()
db.connect()
results = db.query("SELECT * FROM devices")

api = APIClient("https://api.example.com")
response = api.get("devices/status")
๐ŸŽฏ Best Practices:
  • Functions should do one thing and do it well
  • Classes should represent real-world concepts
  • Modules should have clear, single purposes
  • Use meaningful names that describe purpose
  • Keep functions and methods short (under 50 lines)
  • Document your code with docstrings and comments

1.6 Common Design Patterns

๐ŸŽจ Overview: Design patterns are reusable solutions to common software design problems. MVC and Observer are two of the most widely used patterns.

MVC Pattern (Model-View-Controller)

graph TB U[User] --> V[View] V --> C[Controller] C --> M[Model] M --> C C --> V V1[Presentation Layer
UI Components] --> V C1[Business Logic
User Input Handler] --> C M1[Data Layer
Database Access] --> M style U fill:#667eea,color:#fff style V fill:#51cf66,color:#fff style C fill:#339af0,color:#fff style M fill:#ff6b6b,color:#fff

๐Ÿ“ฑ Model

Data & Business Logic

  • Manages application data
  • Contains business rules
  • Notifies views of changes
  • Database operations
  • Independent of UI

๐Ÿ‘๏ธ View

Presentation Layer

  • Displays data to user
  • UI components
  • Receives updates from model
  • Sends user input to controller
  • No business logic

๐ŸŽฎ Controller

Application Logic

  • Handles user input
  • Updates model
  • Selects view
  • Mediates between M & V
  • Application flow control

MVC Workflow

sequenceDiagram participant U as User participant V as View participant C as Controller participant M as Model U->>V: 1. Interacts with UI V->>C: 2. Sends user action C->>M: 3. Updates data M->>M: 4. Processes business logic M-->>C: 5. Returns result C->>V: 6. Updates view V-->>U: 7. Displays updated UI

MVC Example Code

# Model - Data and business logic
class DeviceModel:
    def __init__(self):
        self.devices = []
    
    def add_device(self, hostname, ip):
        device = {"hostname": hostname, "ip": ip, "status": "active"}
        self.devices.append(device)
        return device
    
    def get_all_devices(self):
        return self.devices
    
    def get_device(self, hostname):
        return next((d for d in self.devices if d["hostname"] == hostname), None)

# View - Presentation
class DeviceView:
    def display_devices(self, devices):
        print("\\n=== Network Devices ===")
        for device in devices:
            print(f"{device['hostname']}: {device['ip']} - {device['status']}")
    
    def display_device(self, device):
        if device:
            print(f"Device: {device['hostname']}")
            print(f"IP: {device['ip']}")
            print(f"Status: {device['status']}")
        else:
            print("Device not found")

# Controller - Application logic
class DeviceController:
    def __init__(self):
        self.model = DeviceModel()
        self.view = DeviceView()
    
    def add_device(self, hostname, ip):
        device = self.model.add_device(hostname, ip)
        print(f"Added device: {hostname}")
    
    def show_all_devices(self):
        devices = self.model.get_all_devices()
        self.view.display_devices(devices)
    
    def show_device(self, hostname):
        device = self.model.get_device(hostname)
        self.view.display_device(device)

# Usage
controller = DeviceController()
controller.add_device("Router1", "192.168.1.1")
controller.add_device("Switch1", "192.168.1.2")
controller.show_all_devices()
controller.show_device("Router1")

MVC Advantages

๐Ÿ”€ Separation of Concerns
โ™ป๏ธ Reusability
๐Ÿงช Easy Testing
๐Ÿ‘ฅ Parallel Development
๐Ÿ”ง Maintainability
๐ŸŽจ Multiple Views

Observer Pattern

graph TB S[Subject/Observable] --> O1[Observer 1] S --> O2[Observer 2] S --> O3[Observer 3] S --> S1[State Change] S1 --> N[Notify All Observers] N --> O1 N --> O2 N --> O3 O1 --> U1[Update] O2 --> U2[Update] O3 --> U3[Update] style S fill:#667eea,color:#fff style O1 fill:#51cf66,color:#fff style O2 fill:#51cf66,color:#fff style O3 fill:#51cf66,color:#fff

๐Ÿ“ก Subject (Observable)

  • Maintains list of observers
  • Provides methods to attach/detach observers
  • Notifies observers of state changes
  • Doesn't know observer details

๐Ÿ‘๏ธ Observer

  • Subscribes to subject
  • Implements update interface
  • Receives notifications
  • Reacts to state changes

Observer Pattern Flow

sequenceDiagram participant S as Subject participant O1 as Observer 1 participant O2 as Observer 2 O1->>S: subscribe() O2->>S: subscribe() Note over S: State changes S->>O1: notify() S->>O2: notify() O1->>O1: update() O2->>O2: update()

Observer Example Code

# Observer Pattern Implementation

class NetworkMonitor:
    """Subject/Observable"""
    def __init__(self):
        self._observers = []
        self._device_status = {}
    
    def attach(self, observer):
        self._observers.append(observer)
    
    def detach(self, observer):
        self._observers.remove(observer)
    
    def notify(self, device, status):
        for observer in self._observers:
            observer.update(device, status)
    
    def set_device_status(self, device, status):
        self._device_status[device] = status
        print(f"[Monitor] {device} status changed to {status}")
        self.notify(device, status)

class EmailAlert:
    """Observer 1"""
    def update(self, device, status):
        if status == "down":
            print(f"[Email] Alert! {device} is DOWN - sending email...")

class SMSAlert:
    """Observer 2"""
    def update(self, device, status):
        if status == "down":
            print(f"[SMS] Alert! {device} is DOWN - sending SMS...")

class Logger:
    """Observer 3"""
    def update(self, device, status):
        print(f"[Logger] Logging: {device} - {status}")

# Usage
monitor = NetworkMonitor()

# Attach observers
email_alert = EmailAlert()
sms_alert = SMSAlert()
logger = Logger()

monitor.attach(email_alert)
monitor.attach(sms_alert)
monitor.attach(logger)

# State changes trigger notifications
monitor.set_device_status("Router1", "up")
print()
monitor.set_device_status("Switch1", "down")

Observer Pattern Advantages

๐Ÿ”“ Loose Coupling
๐Ÿ“ข Broadcast Communication
๐Ÿ”Œ Dynamic Relationships
๐Ÿ“ˆ Scalability
๐ŸŽฏ Event-Driven
โ™ป๏ธ Reusability

When to Use Each Pattern

Pattern Use When Examples
MVC Building user interfaces with separate data and presentation Web applications, Desktop GUIs, Mobile apps
Observer Need to notify multiple objects about state changes Event systems, Monitoring tools, Pub-Sub messaging
๐ŸŽฏ Pattern Benefits Summary:
  • MVC: Separates concerns, makes testing easier, enables multiple views of same data
  • Observer: Enables loose coupling, supports broadcast communication, dynamic subscriptions
  • Both patterns promote reusability, maintainability, and scalability
  • Commonly used in frameworks (Django, React, Angular, Vue)
โš ๏ธ Considerations:
  • MVC: Can be complex for simple applications, requires discipline to maintain separation
  • Observer: Can cause performance issues with many observers, debugging can be harder
  • Don't overuse patterns - use them when they solve a real problem

๐Ÿ Interactive Python Interpreter

๐Ÿ’ป Live Python Environment: Write and execute Python code directly in your browser! Practice functions, classes, and code organization concepts.

Sample Code Templates

โœ๏ธ Python Code Editor
๐Ÿ“ค Output
โณ Loading Python interpreter...
โœจ Features:
  • Real-time Python execution in your browser
  • Practice functions, classes, and OOP concepts
  • Try MVC and Observer pattern examples
  • Great for DEVASC exam preparation
  • No installation required
โš ๏ธ Limitations:
  • Cannot import external libraries
  • No file system access
  • Limited to basic Python features

Quick Reference

Supported Features

  • โœ“ Functions & Classes
  • โœ“ Inheritance
  • โœ“ Lists & Dictionaries
  • โœ“ Loops & Conditionals
  • โœ“ Print & String formatting

Keyboard Shortcuts

  • Tab - Indent
  • Ctrl+Enter - Run Code
  • Arrow Keys - Navigate tabs
โ† Back to Topics

DEVASC 200-901 โ€ข Section 1.0: Software Development and Design (15%)

Created by Ratnesh Kumar CCIE x3