Software Development Midterm Study Guide (Farley: Modern Software Engineering Preface + Ch. 1–3 Themes)

Use this as a checklist + practice workbook. If you can answer the practice questions out loud and do the mini-exercises without “hand-waving,” you’re ready.


1) Continuous Delivery

What you must be able to explain

  • Goal: the ability to release changes safely, reliably, and frequently (on demand), not “deploy faster for fun.”
  • Core idea: reduce risk by keeping changes small, verified, and releasable.

Key terms

  • Deployment vs release: deployment = code is shipped somewhere; release = users see/experience it.
  • Small batch size: small changes are easier to review, test, debug, and roll back.
  • CI pipeline: automated build/test steps run on every change.
  • Feature flags: deploy code behind a switch so you can enable/disable safely.

What CD requires (concrete practices)

  • Automated tests (unit + integration)
  • Continuous Integration (build/test on every commit)
  • Repeatable deployments (scripts, environments that match)
  • Trunk-based development or very short-lived branches
  • Monitoring/logging so production becomes a feedback source
  • Ability to roll back quickly

Common failure patterns (know these)

  • “We do CD” but releases still hurt because tests are weak or slow
  • Big merges / long-lived branches
  • Manual, inconsistent deployments
  • Database changes that are irreversible or unsafe

Practice questions

  1. In one sentence, define Continuous Delivery.
  2. Name two practices that enable CD and explain how each reduces risk.
  3. Give one example where feature flags help (and one risk they introduce).

2) What Is Software Engineering (vs programming)

The distinction you should be able to defend

  • Programming: writing code that works now.
  • Software engineering: building and evolving a system so it keeps working as it changes—under constraints like time, teams, and uncertainty.

Engineering themes to name explicitly

  • Managing change over time (maintainability, refactoring, versioning)
  • Working in teams (communication, shared standards, reviews)
  • Validation via feedback (tests, CI, users, metrics)
  • Explicit contracts (APIs, module boundaries, schemas)

Practice questions

  1. Give a concrete example where the “programming solution” works but the “engineering solution” is different.
  2. What makes a change “safe” in an engineering sense?

3) Learning vs Guessing (Hypothesis-driven development)

What “guessing” looks like (bad)

  • “I changed 12 things and now it works.”
  • No clear success criteria.
  • No way to identify which change mattered.

What “learning” looks like (good)

  • You form an explicit hypothesis:
    • “I believe X is happening because Y; if I change Z then I expect outcome W.”
  • You run fast feedback first, then slower/realistic feedback.
  • You keep changes small and reversible.

A practical workflow you should be able to describe

  1. Reproduce the problem reliably (or define acceptance test).
  2. Hypothesis + minimal experiment (small change).
  3. Fast feedback: unit tests, lint, local run, small sample inputs.
  4. Slower feedback: integration tests, staging, canary, production metrics.
  5. Rollback plan: revert commit, disable feature flag, redeploy prior version.

Practice questions

  1. Write a hypothesis for: “API sometimes returns 500 in production.”
  2. What are two fast feedback loops and two slower ones for that scenario?
  3. What’s your rollback plan if the fix makes it worse?

4) Feedback Loops: The Center of Engineering

Core idea

Engineering improves outcomes by building tight feedback loops that reveal truth quickly.

Examples you should know (and classify fast/medium/slow)

  • Unit tests (fast)
  • Linting/formatting/type checks (fast)
  • CI build + test pipeline (medium)
  • Code review (medium)
  • Integration tests / staging smoke tests (medium)
  • Monitoring, logs, alerts (slow/continuous)
  • User feedback/support tickets (slow)

Practice questions

  1. List 3 feedback loops and what each teaches you.
  2. Why do small batch sizes make feedback loops more powerful?

5) Git Fundamentals (what you must be fluent with)

Concepts to master

  • Commit: a snapshot with a message and parent commit(s).
  • Branch: a movable pointer to a commit; a line of development.
  • Merge: combines histories; may create a merge commit.
  • Fast-forward: branch pointer moves forward because there was no divergence.
  • Merge conflict: Git can’t automatically reconcile overlapping edits.

Commands (conceptual understanding > memorization)

  • git status (what changed?)
  • git add / git commit (stage + snapshot)
  • git log (history)
  • git branch / git switch (move between lines of work)
  • git pull (fetch + integrate)
  • git merge (combine branches)
  • git revert (undo by new commit; safe for shared history)

Security scenario (must know)

If you committed a secret:

  • Immediate: revoke/rotate the key (treat it as compromised).
  • Follow-up: remove from code and prevent recurrence (env vars, secret scanning, pre-commit hooks).
  • History rewrite may be required, but rotating is still necessary.

Practice tasks

  1. Explain what “fast-forward” means without using the word “update.”
  2. Explain what a merge conflict actually indicates in the code.
  3. Describe a safe rollback strategy using Git.

6) Node.js + Express + JavaScript Fundamentals

Node.js essentials

  • Event-driven, non-blocking I/O model (good for many concurrent connections).
  • Async operations return Promises; errors can become unhandled rejections.

Express essentials (you will be tested on contracts)

  • Routes define your API surface: method + path.
  • A handler must return:
    • appropriate status codes
    • predictable JSON shape
    • consistent error format

JavaScript essentials

  • === vs ==: strict equality avoids type coercion surprises.
  • async/await: readable asynchronous flow on top of Promises.
  • If you forget await, you may:
    • send a response before work completes
    • return a Promise instead of data
    • miss errors (unhandled rejection)

Input validation (non-negotiable)

  • All input is untrusted: params/body/query.
  • Validate types, required fields, ranges, and formats.

Practice exercises

  1. Write the contract for GET /api/users/:id:
    • What’s a valid id?
    • What’s the JSON response on success?
    • What status and body on invalid id vs not found?
  2. Explain why returning 200 {error: "not found"} is a contract smell.

7) Managing Complexity: Separation of Concerns

What you should be able to articulate

Complexity grows when responsibilities are mixed. Separation of concerns is about boundaries and contracts.

A clean full-stack division (typical)

  • React:
    • UI rendering, local component state, form handling
    • calling APIs, displaying results/errors
  • Express backend:
    • request validation, authentication/authorization
    • business rules, orchestration, enforcing API contracts
  • Database:
    • data integrity constraints (FK, unique, not null)
    • schema as a source of truth for structure

Red flags (know them)

  • Business logic in React only (“security by UI”)
  • Database used as a dump with no constraints
  • API responses that vary shape unpredictably
  • Lots of duplicated logic between frontend and backend

Practice questions

  1. Where should “title must be 1..80 chars” be enforced (and why)?
  2. Give one example of the same rule being enforced in two places for good reason.

8) REST APIs and Request/Response Contracts

What a “contract” is

A contract is the agreed shape and meaning of:

  • request method/path
  • request body/query/params types
  • response body shape
  • status codes for success and error cases

REST basics (what you should know cold)

  • GET: fetch resource(s)
  • POST: create
  • PUT/PATCH: update
  • DELETE: remove

Status codes you’ll likely need

  • 200 OK (success)
  • 201 Created (created resource)
  • 400 Bad Request (invalid input)
  • 404 Not Found (missing resource)
  • 409 Conflict (constraint conflict; e.g., duplicate unique key)
  • 500 only when server failed unexpectedly (not for validation)

Practice exercise: design a task-creation endpoint

You should be able to write:

  • POST /api/tasks
  • request JSON (title required, completed optional default false)
  • success response returns id and stored fields
  • two error cases: invalid title (400), bad content-type (415) or user not found (404), etc.

9) MariaDB Basics: Schema Design (Simple but Correct)

What you must be able to do

  • Design 2–3 related tables with:
    • primary keys
    • foreign keys
    • not null constraints
    • defaults
  • Explain why constraints belong in the DB (integrity and single source of truth)

Minimum schema patterns

  • users(id, ...)
  • tasks(id, user_id, title, completed, created_at)

Constraints to know

  • NOT NULL for required fields
  • DEFAULT for safe default values (e.g., completed false)
  • FOREIGN KEY to enforce relationships
  • UNIQUE where appropriate (e.g., email)

Practice questions

  1. Why should completed be NOT NULL DEFAULT false instead of allowing NULL?
  2. What does a foreign key prevent in real life?

10) React Fundamentals: Components and State

Core ideas

  • Components render UI based on props and state.
  • State updates must be immutable (don’t mutate arrays/objects in place).
  • UI bugs often come from stale state updates or direct mutation.

Controlled components (forms)

  • Input value comes from state; onChange updates state.
  • Benefits:
    • validation, consistent UI, predictable data flow
  • Trade-offs:
    • more boilerplate, more re-renders if poorly structured

Common React pitfalls (know these)

  • Mutating state (tasks.push(...))
  • Using stale state when updates happen quickly
  • Missing keys in lists / unstable keys
  • Putting server truth in too many places (contract drift)

Practice exercises

  1. Fix this pattern mentally:
    • replace tasks.push(t); setTasks(tasks);
    • with setTasks(prev => [...prev, t])
  2. Explain why functional updates help under rapid events.

High-Value “If You Only Study One Page” Checklist

You should be able to do all of these quickly:

  • Define Continuous Delivery in one sentence and list 2 enabling practices.
  • Explain software engineering vs programming using: change, teams, feedback.
  • Describe a hypothesis-driven workflow (hypothesis + fast feedback + rollback).
  • Name 3 feedback loops and what they tell you.
  • Explain commit vs branch vs merge conflict vs fast-forward.
  • Write a clean Express route contract (statuses + JSON shapes).
  • Explain why separation of concerns reduces complexity.
  • Design a REST create endpoint including two error cases.
  • Write two MariaDB CREATE TABLEs with PK/FK/NOT NULL/DEFAULT.
  • Fix a React state mutation bug using immutable updates.

25-Minute Practice Drill (do this before the exam)

  1. Write (from memory) a contract for POST /api/tasks including:
  • request body
  • success response
  • 2 error responses with codes
  1. Sketch a minimal schema for users/tasks with constraints.
  2. Explain “learning vs guessing” using a real example from your projects.
  3. Explain:
  • === vs ==
  • what happens if you forget await
  • why input validation matters
  1. Explain what a merge conflict means and how you’d resolve it safely.
Scroll to Top