Software Engineering Principles

Chapter 7
Software Construction and Collaborative Development

Bachelors Program in Full Stack Development
Software Engineering Principles   •   Bachelor

Software Construction and Collaborative Development

Introduction

Software construction is the disciplined activity of turning requirements and designs into executable, maintainable, secure, and testable software. Although programming is central to construction, professional construction involves much more than writing statements that make a program run. It includes selecting appropriate abstractions, applying coding standards, handling failures, designing interfaces, managing dependencies, documenting decisions, and coordinating changes across a team.

In a modern full-stack project, construction occurs simultaneously at several levels. A developer may implement a user-interface component, expose a REST endpoint, validate data at a service boundary, write database queries, configure a build pipeline, and review another developer’s code. These activities are interdependent: a weak API contract can create defects in both the front end and back end; an unmanaged dependency can introduce a security vulnerability; and an ineffective branching strategy can make technically correct work difficult to integrate.

This chapter presents software construction as both a technical and social process. It emphasizes practices that improve correctness, maintainability, security, and team flow. The goal is not to prescribe one programming language or one tool, but to develop transferable engineering judgment.

Learning Objectives

By the end of this chapter, you should be able to:

  1. Explain the purpose of coding standards and apply them consistently.
  2. Use defensive programming and structured error handling to make software robust.
  3. Design clear, stable, and usable APIs.
  4. Select suitable version-control and branching practices for a team.
  5. Conduct constructive code reviews and use pair programming effectively.
  6. Explain how static analysis and automated checks support quality.
  7. Manage software dependencies responsibly.
  8. Produce technical documentation that supports users, developers, and maintainers.
  9. Analyze collaborative construction practices in a realistic development scenario.

1. Construction as an Engineering Discipline

A construction activity should satisfy more than functional requirements. A useful implementation should also have qualities such as:

  • Correctness: it produces the required results for valid inputs.
  • Robustness: it behaves safely when inputs, services, or assumptions fail.
  • Maintainability: future developers can understand and modify it.
  • Testability: important behavior can be verified efficiently.
  • Security: it resists misuse and protects data.
  • Performance: it uses computational and infrastructure resources appropriately.
  • Observability: failures and important system behavior can be diagnosed.

These qualities often conflict. Highly optimized code may be harder to understand; extensive validation may increase latency; and a rapidly changing API may enable short-term delivery while creating long-term integration costs. Software engineers therefore make explicit trade-offs rather than treating construction as merely an implementation phase.

A practical construction workflow commonly includes:

  1. Clarifying the requirement and acceptance criteria.
  2. Understanding relevant architecture and interfaces.
  3. Implementing a small, coherent change.
  4. Running local tests and automated quality checks.
  5. Reviewing the change with another developer.
  6. Integrating it into the shared codebase.
  7. Monitoring the result and correcting defects.

The workflow is iterative. Feedback from testing or review may reveal that the original interpretation of a requirement was incomplete.

2. Coding Standards and Readable Code

Coding standards are agreed conventions for formatting, naming, structure, documentation, and the use of language features. They reduce unnecessary variation so that developers can focus on behavior rather than deciphering style differences.

2.1 What standards should cover

A team standard may define:

  • indentation and line length;
  • naming conventions for variables, functions, classes, files, and constants;
  • preferred control-flow constructs;
  • rules for comments and public documentation;
  • error-handling conventions;
  • logging and sensitive-data rules;
  • import ordering and dependency usage;
  • test naming and organization;
  • rules enforced automatically by formatters and linters.

Standards should be specific enough to be actionable but not so restrictive that they impede legitimate design decisions. Automated formatting is particularly valuable because it removes low-value arguments from code review.

2.2 Readability and meaningful structure

Readable code communicates intent. A function should generally have one coherent purpose, a meaningful name, and a manageable level of complexity. The following example is easier to understand than a compressed alternative:

function calculateOrderTotal(items, taxRate) {
  const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  return subtotal + subtotal * taxRate;
}

The function name identifies the operation, the intermediate value makes the calculation visible, and the parameters express the required data. Readability does not mean that every expression must be expanded. It means that the organization of the code helps a competent reader form an accurate mental model.

Comments should explain rationale, constraints, or non-obvious behavior. A comment that merely repeats syntax adds little value. For example, “increment counter” above counter++ is redundant, whereas an explanation of why a retry is limited to three attempts may be important.

2.3 Consistency versus local optimization

A project may contain a technically valid but unconventional implementation. Before changing it, a developer should ask whether consistency, compatibility, or performance justifies the difference. Standards are defaults, not substitutes for judgment. Exceptions should be documented when they affect future maintenance.

3. Defensive Programming

Defensive programming assumes that inputs, collaborators, external services, and environmental conditions may violate expectations. It does not mean adding arbitrary checks everywhere. It means identifying trust boundaries and protecting important invariants.

3.1 Preconditions, postconditions, and invariants

A precondition is something that must be true before an operation begins. A postcondition is something that should be true after successful completion. An invariant is a property that remains true throughout a defined part of execution.

For a function that transfers money between accounts, possible conditions include:

  • precondition: the amount is positive and the source account exists;
  • invariant: the source and destination accounts are not the same;
  • postcondition: if the operation succeeds, the debit and credit are recorded consistently.

Validation should occur near the boundary where untrusted data enters the system. A browser form may perform early validation for usability, but the server must validate independently because clients can be modified or bypassed.

3.2 Common defensive techniques

Important techniques include:

  • validating type, range, format, and allowed values;
  • rejecting unexpected fields where appropriate;
  • using parameterized database queries;
  • checking authorization separately from authentication;
  • limiting resource use, such as upload size or request duration;
  • handling null, missing, or empty values deliberately;
  • avoiding assumptions about network availability;
  • using timeouts and bounded retries;
  • preserving data integrity through transactions;
  • failing safely rather than exposing internal details.

Defensive checks should produce useful outcomes. A validation failure should identify what the caller can correct, while an internal failure should be logged for diagnosis without revealing secrets or implementation details to an external user.

4. Error Handling and Reliability

Errors are not all alike. Treating every failure as an exception, a generic HTTP 500 response, or a simple log message reduces system quality.

4.1 Categories of failure

A useful classification is:

Failure categoryExampleSuitable response
Input errorInvalid email formatReturn a clear validation response
Authentication or authorization errorExpired token or insufficient roleReject access without leaking sensitive information
Business-rule violationAttempt to reserve an unavailable itemReturn a domain-specific message
External transient failureTemporary database or network timeoutRetry selectively or fail gracefully
Internal programming defectUnexpected null referenceRecord diagnostic details and alert the team
Configuration or deployment failureMissing encryption keyStop safely and require operational correction

A good error-handling strategy defines which layer is responsible for detecting, translating, logging, and presenting an error. Lower layers should preserve useful context; higher layers should present an appropriate contract to callers.

4.2 Exceptions and explicit results

Exceptions are suitable when an operation cannot continue normally and the language or framework supports structured propagation. Explicit result types can be clearer when failure is an expected alternative, such as parsing user input or looking up an optional record. The important principle is consistency: callers should know how failures are represented and should not need to guess whether a function returns a special value, throws an exception, or terminates the process.

Errors should not be silently swallowed. This pattern is dangerous:

try {
  await saveProfile(profile);
} catch (error) {
  // Ignore failure
}

If failure is intentionally non-critical, the code should record the reason or provide a defined fallback. Otherwise, the application may report success when the data was not saved.

4.3 Logging and observability

Logs should support diagnosis. A useful event usually includes a timestamp, severity, operation, correlation identifier, and relevant non-sensitive context. Passwords, access tokens, payment-card data, and private personal information should not be logged casually. Structured logs are easier to search and aggregate than unstructured prose.

Retries require care. Retrying a non-idempotent operation, such as charging a payment card, may duplicate its effect unless an idempotency key or equivalent protection is used. Exponential backoff can reduce pressure on a failing service, but retry limits and total timeouts are necessary to prevent indefinite waiting.

5. API Design

An application programming interface (API) is a contract through which software components communicate. A good API defines available operations, input and output representations, error behavior, security requirements, and compatibility expectations.

5.1 Characteristics of a strong API

A well-designed API is:

  • Explicit: behavior and data requirements are documented.
  • Consistent: similar operations use similar naming and response patterns.
  • Discoverable: developers can learn how to use it from documentation and examples.
  • Stable: compatible changes do not unexpectedly break consumers.
  • Secure: authentication, authorization, validation, and data minimization are addressed.
  • Observable: requests can be traced and failures diagnosed.

For a REST-style web API, resource-oriented paths and appropriate HTTP methods are common conventions. For example:

OperationMethod and pathTypical successful response
List productsGET /products200 OK with a collection
Retrieve one productGET /products/{id}200 OK with a product
Create a productPOST /products201 Created with a representation or location
Replace a productPUT /products/{id}200 OK or 204 No Content
Partially updatePATCH /products/{id}200 OK or 204 No Content
Delete a productDELETE /products/{id}204 No Content when successful

These conventions are not mandatory in every architecture, but consistency helps clients predict behavior. Status codes should distinguish validation failure, missing resources, forbidden operations, conflicts, and unexpected server errors.

5.2 Compatibility and versioning

An API change is breaking when existing clients can no longer function correctly. Removing a field, changing a field’s meaning, tightening accepted input, or altering error semantics can be breaking even if the URL remains unchanged. Additive changes are often safer, but they can still create problems if clients reject unknown fields or if a response becomes too large.

Versioning may use a URL segment, header, media type, or a compatibility policy that avoids explicit versions for non-breaking changes. The choice matters less than having a documented deprecation and migration process. Consumers should receive advance notice, replacement guidance, and a defined support period.

5.3 API security

Authentication establishes identity; authorization determines permitted actions. An API should apply least privilege, validate object ownership, constrain input, protect transport, and avoid exposing internal identifiers or stack traces unnecessarily. Rate limiting and request-size limits help reduce abuse. Security is a property of the whole interaction, not merely the presence of a login endpoint.

6. Version Control and Branching

Version-control systems record changes to source code and related artifacts. They provide history, enable collaboration, support rollback, and make review possible. Git is widely used, but the underlying practices are tool-independent.

A useful commit should be:

  • focused on one logical change;
  • internally coherent and buildable when practical;
  • accompanied by a message that explains intent;
  • free from generated files or secrets unless explicitly required.

A message such as “fix stuff” provides little historical value. “Reject duplicate reservation requests using idempotency key” communicates purpose and supports future investigation.

6.1 Branching strategies

Common approaches include:

  • Trunk-based development: developers integrate small changes frequently into a main branch, often using feature flags for incomplete functionality.
  • Short-lived feature branches: a branch isolates a small change and is merged after automated checks and review.
  • Release branches: a branch stabilizes a planned release while ongoing development continues elsewhere.
  • Long-lived feature branches: a large change remains isolated for an extended period; this can reduce disruption but increases merge risk.

No strategy eliminates integration cost. Long separation tends to increase divergence, while continuous integration requires disciplined automation and small changes. A team should select a strategy based on release frequency, deployment automation, regulatory constraints, and the cost of incomplete features.

6.2 Merge conflicts and integration

A merge conflict occurs when Git cannot determine how competing changes should be combined. Conflict resolution is not merely a textual task. Developers must understand the intended behavior of both changes, resolve the code, and rerun relevant tests. A syntactically successful merge can still produce a semantic defect.

A healthy integration process includes frequent synchronization, small pull requests, automated tests, and ownership that is shared rather than concentrated in one person.

7. Code Review and Pair Programming

Code review is a quality and knowledge-sharing activity in which developers examine a proposed change before integration. It can identify defects, clarify design, improve security, and spread system knowledge. It should not become a competition or a search for stylistic preferences that automated tools could enforce.

7.1 Effective review practice

The author should provide context: what changed, why it changed, how it was tested, and what risks remain. Reviewers should inspect:

  1. alignment with the requirement;
  2. correctness and edge cases;
  3. security and privacy implications;
  4. error handling and observability;
  5. API and data compatibility;
  6. test adequacy;
  7. maintainability and operational impact.

Comments should be specific and respectful. “This is bad” is not actionable; “Could this query be parameterized to prevent input from becoming SQL syntax?” identifies both concern and direction. Reviewers should distinguish blocking defects from suggestions.

Review effectiveness depends on review size and context. A small pull request is easier to understand than a large one containing unrelated refactoring, formatting changes, and feature work. Teams should avoid using review approval as a substitute for automated testing or architectural ownership.

7.2 Pair programming

In pair programming, two developers work on one task at one workstation or shared environment. The driver controls the immediate implementation, while the navigator examines direction, assumptions, and risks. Roles should rotate.

Pairing can improve feedback speed, knowledge transfer, and design quality. It is especially useful for unfamiliar code, security-sensitive changes, debugging, and complex algorithms. It can be less efficient for routine work or when the pair lacks a clear task boundary. Psychological safety is essential: the practice should not be used to monitor individuals or suppress independent thinking.

8. Static Analysis and Automated Quality Gates

Static analysis examines source code or related artifacts without executing the program in its normal operational environment. Examples include linters, type checkers, security scanners, dependency analyzers, and complexity detectors.

Static analysis can identify unreachable code, unsafe data flow, inconsistent types, unused variables, vulnerable patterns, and violations of project conventions. It cannot prove that a system satisfies every business requirement. Dynamic tests and human reasoning remain necessary.

A quality pipeline may include:

  1. formatting verification;
  2. linting;
  3. compilation or type checking;
  4. unit and integration tests;
  5. dependency and secret scanning;
  6. build and packaging;
  7. deployment checks.

A quality gate is a condition that must be satisfied before integration or deployment, such as no high-severity security findings and all required tests passing. Gates should be calibrated. If a tool produces excessive false positives, developers may ignore it. Teams should review warnings, suppress only justified findings, and periodically update rules.

Metrics such as code coverage can inform investigation but should not be treated as proof of quality. A test suite may execute many lines while failing to verify important behavior, boundary conditions, or security properties.

9. Dependency Management

Modern applications depend on libraries, frameworks, build tools, operating-system packages, and services. Dependencies accelerate development but create risks involving vulnerabilities, licensing, compatibility, availability, and abandonment.

A responsible dependency process includes:

  • declaring direct dependencies explicitly;
  • recording exact or controlled versions through a lockfile where appropriate;
  • distinguishing production from development dependencies;
  • reviewing transitive dependencies;
  • scanning for known vulnerabilities;
  • updating regularly in small, tested increments;
  • removing unused packages;
  • verifying package provenance and integrity;
  • checking license compatibility;
  • maintaining a response process for urgent advisories.

Semantic versioning is often expressed as major, minor, and patch numbers. In the common convention, a major release may contain breaking changes, a minor release adds backward-compatible functionality, and a patch release fixes backward-compatible defects. This convention is useful but not a guarantee; teams should read release notes and test upgrades.

Dependency risk is also architectural risk. A small package may introduce a large transitive graph, and a popular package may become unmaintained. Organizations may use approved-package inventories, software bills of materials, private registries, and reproducible builds to improve governance.

10. Technical Documentation

Documentation is part of the product, not an afterthought. Different audiences require different artifacts:

AudienceUseful documentation
API consumerEndpoint reference, schemas, authentication, examples
MaintainerSetup instructions, architecture, troubleshooting, operational notes
ContributorCoding standards, workflow, tests, review process
OperatorDeployment, monitoring, rollback, incident procedures
Product stakeholderBehavior, limitations, assumptions, release notes

A README should enable a new contributor to install prerequisites, configure the project, run tests, and understand the repository structure. Architecture decision records are useful for recording significant choices, alternatives considered, and consequences. API specifications can make contracts machine-readable and support generated clients or validation.

Documentation must be versioned with the software when it describes behavior that changes with the code. It should state assumptions and limitations rather than claiming more certainty than the system provides.

11. Worked Application: Improving a Reservation Service

The following is an illustrative case.

Background

A university laboratory operates an online equipment-reservation system. Students use a web application to reserve cameras and sensors. The front end calls a back-end API, which stores reservations in a relational database.

Problem

The system has experienced three recurring problems:

  1. Two users can occasionally reserve the same equipment for overlapping periods.
  2. A failed database request sometimes appears to the user as a successful reservation.
  3. Developers merge large branches after several weeks, causing conflicts and regressions.

The team must improve reliability without stopping feature development.

Analysis

The first problem is a concurrency and data-integrity issue. Checking availability in application code and then inserting a reservation as separate, unprotected actions creates a race condition: two requests can both observe availability before either writes its reservation.

The second problem is an error-handling defect. The service catches an exception but returns a success response. This violates the API contract and prevents the user from taking corrective action.

The third problem is a collaboration problem. Long-lived branches increase divergence, make reviews difficult, and delay feedback.

Approach and solution

The team takes the following actions:

  • defines a reservation API contract, including validation errors, conflict responses, and server-error behavior;
  • validates equipment identifiers, user permissions, time ranges, and maximum reservation duration at the API boundary;
  • enforces the no-overlap rule using an appropriate database transaction and constraint strategy rather than relying only on application checks;
  • returns a conflict response when a reservation cannot be created because the equipment is already reserved;
  • uses an idempotency key so that a client retry does not create duplicate reservations;
  • logs failures with a correlation identifier but excludes authentication tokens and personal data not needed for diagnosis;
  • adds tests for overlapping requests, malformed input, authorization, timeout behavior, and repeated submissions;
  • introduces short-lived branches and pull requests limited to one logical change;
  • runs formatting, static analysis, tests, and dependency scanning in continuous integration;
  • documents the API, local setup, deployment assumptions, and the rationale for the concurrency design.

A simplified service boundary might look like this:

async function createReservation(request, context) {
  validateReservationInput(request);
  await authorizeReservation(context.user, request.equipmentId);

  return database.transaction(async (transaction) => {
    const available = await transaction.isAvailable(
      request.equipmentId,
      request.startsAt,
      request.endsAt
    );

    if (!available) {
      throw new ConflictError("Equipment is already reserved");
    }

    return transaction.insertReservation(request, {
      idempotencyKey: request.idempotencyKey
    });
  });
}

This example is not a complete concurrency solution by itself: isAvailable and the insertion must be protected by the database’s transactional and constraint mechanisms. The important design lesson is that correctness must be enforced at the authority that controls shared state.

Outcome

After deployment, failed reservations are reported honestly, duplicate submissions are safely recognized, and overlapping reservations are rejected consistently. Smaller pull requests reduce review time, while automated checks detect formatting and dependency problems before merging. The team also gains clearer operational evidence when an external service fails.

Learning points

The case demonstrates that construction practices reinforce one another. Defensive validation alone cannot solve a database race. A good API cannot compensate for misleading error handling. Version control and review practices affect the reliability of technical solutions because they determine how effectively changes are examined and integrated.

12. Challenges, Ethics, and Governance

Collaborative development introduces organizational and ethical responsibilities. Code review should be inclusive and focused on the artifact, not personal status. Teams should avoid measuring productivity through simplistic counts of commits, lines changed, or review comments. Such metrics can encourage harmful behavior and do not represent delivered value or software quality.

Privacy must be considered in logs, test data, monitoring, and dependency services. Production personal data should not be copied into development environments without a lawful and controlled basis. Security findings should be triaged according to risk, and responsible disclosure procedures should protect users while defects are corrected.

Open-source dependencies create both opportunity and obligation. License conditions must be understood and respected. Organizations should not assume that publicly available code is automatically safe, maintained, or free of compliance requirements.

Artificial-intelligence coding assistants can accelerate implementation, generate tests, and explain unfamiliar code. However, generated code may contain vulnerabilities, licensing uncertainty, incorrect assumptions, or fabricated APIs. Developers remain responsible for review, testing, security analysis, and compliance. Sensitive source code or personal data should not be submitted to an AI service unless organizational policy and data-protection controls permit it.

13. Contemporary Practices and Best Practices

Current engineering environments increasingly combine trunk-based or short-lived-branch development with continuous integration and continuous delivery. Feature flags allow incomplete functionality to be deployed separately from its public activation, but flags create configuration complexity and should be removed when no longer needed.

Infrastructure-as-code, containerized development environments, reproducible builds, software bills of materials, and automated supply-chain scanning improve consistency and traceability. These practices do not eliminate human judgment. They shift attention toward designing reliable policies, interpreting findings, and responding to exceptions.

A practical set of best practices is:

  1. Keep changes small and purposeful.
  2. Validate untrusted data at every relevant trust boundary.
  3. Make failure behavior explicit and test it.
  4. Design APIs as contracts, not incidental controller code.
  5. Integrate frequently and resolve conflicts with behavioral understanding.
  6. Automate formatting, linting, testing, and security checks.
  7. Review dependencies as part of the system’s attack surface.
  8. Write documentation for the next developer and the next operator.
  9. Treat review as collaboration and learning.
  10. Prefer evidence from tests, monitoring, and incidents over assumptions.

Chapter Summary

Software construction is the disciplined production of executable software that is correct, robust, maintainable, secure, testable, and observable. Coding standards reduce accidental variation, while readable structure and meaningful names make intent easier to verify. Defensive programming protects invariants and trust boundaries through validation, authorization, resource limits, and safe defaults.

Effective error handling distinguishes input, business, external, and internal failures. APIs should define consistent operations, representations, security requirements, error behavior, and compatibility policies. Version control enables history and collaboration; small commits, short-lived branches, and frequent integration reduce divergence. Code reviews and pair programming improve defect detection and knowledge sharing when they are respectful, focused, and supported by automation.

Static analysis, tests, dependency scanning, and quality gates provide valuable evidence but do not replace engineering judgment. Dependency management includes version control, vulnerability response, license awareness, and supply-chain governance. Technical documentation preserves operational and architectural knowledge. Finally, ethical software construction requires privacy protection, inclusive collaboration, responsible dependency use, and critical evaluation of AI-generated code.

Key Terms

Coding standard: An agreed convention governing code style, structure, naming, and related practices.

Defensive programming: Designing software to handle invalid inputs, unexpected states, and environmental failures safely.

Precondition: A condition that must hold before an operation begins.

Postcondition: A condition expected to hold after an operation completes successfully.

Invariant: A property that remains true throughout a specified operation or system state.

Trust boundary: A point where data or control crosses from one level of trust to another.

API: A defined interface and contract through which software components communicate.

Idempotency: A property whereby repeating an operation has the same intended effect as performing it once.

Version control: A system for recording, comparing, and coordinating changes to project artifacts.

Branch: An independent line of development within a version-control repository.

Merge conflict: A situation in which competing changes cannot be combined automatically.

Code review: Systematic examination of a proposed change by one or more developers.

Pair programming: A practice in which two developers collaborate simultaneously on one implementation task.

Static analysis: Examination of code or artifacts without normal execution of the program.

Quality gate: An automated or manual condition that must be satisfied before integration or release.

Dependency: External software or service required by an application or development process.

Transitive dependency: A dependency required indirectly through another dependency.

Technical documentation: Written information that explains software behavior, use, operation, design, or maintenance.

Feature flag: A runtime-controlled mechanism that separates deployment of code from activation of behavior.

Software bill of materials: An inventory of components and dependencies contained in a software product.

Review Questions

Short Answer Questions

  1. Why should server-side validation be performed even when a browser performs client-side validation?
  2. Distinguish authentication from authorization.
  3. What makes a commit useful to future maintainers?
  4. State two risks associated with unmanaged dependencies.
  5. Why should code review comments be specific and actionable?

Long Answer Questions

  1. Explain how coding standards, automated formatting, and code review work together to improve maintainability.
  2. Describe a structured error-handling strategy for a full-stack application, including logging and user-facing responses.
  3. Compare trunk-based development with long-lived feature branches, including benefits, risks, and suitable contexts.
  4. Explain the role and limitations of static analysis in a software quality process.
  5. Discuss how API compatibility, versioning, and deprecation affect collaborative development.

Analytical / Application Questions

  1. A payment endpoint sometimes charges a customer twice when the client retries after a timeout. Analyze the failure and propose an API, database, and observability solution.
  2. A team’s pull requests regularly contain formatting changes, feature work, and unrelated refactoring in one large branch. Design a revised construction and review workflow and justify each element.
  3. An AI coding assistant proposes a library with an unknown license and generates code that logs complete request bodies. Identify the technical, legal, privacy, and governance risks, and define the checks required before accepting the change.

Multiple Choice Questions with Answers

Question 1

Which practice most directly protects a server from manipulated client input?

A. Relying only on browser validation

B. Validating input at the server trust boundary

C. Increasing the user interface font size

D. Adding more comments to the client code

Correct Answer: B. Validating input at the server trust boundary

Question 2

Which response is most appropriate when a reservation cannot be created because the requested resource is already reserved?

A. A successful response that hides the conflict

B. A generic success response followed by silent logging

C. A conflict response with a useful client-facing explanation

D. A stack trace containing database details

Correct Answer: C. A conflict response with a useful client-facing explanation

Question 3

What is the primary purpose of a focused commit?

A. To maximize the number of changed lines

B. To combine unrelated tasks for faster review

C. To record one coherent logical change

D. To avoid running automated tests

Correct Answer: C. To record one coherent logical change

Question 4

Which statement best describes static analysis?

A. It proves that all business requirements are satisfied

B. It examines code or artifacts without normal program execution

C. It replaces code review in every situation

D. It is limited to measuring application response time

Correct Answer: B. It examines code or artifacts without normal program execution

Question 5

Why can long-lived feature branches increase project risk?

A. They prevent any developer from writing tests

B. They increase divergence and the likelihood of difficult integration

C. They automatically remove version history

D. They make APIs impossible to document

Correct Answer: B. They increase divergence and the likelihood of difficult integration

Question 6

Which information should generally not be written to ordinary application logs?

A. A correlation identifier

B. An operation name

C. A password or access token

D. A timestamp

Correct Answer: C. A password or access token

Question 7

What is the main purpose of an idempotency key in a retried request?

A. To increase the size of the response

B. To prevent an intentional repeat from causing an unintended duplicate effect

C. To replace authorization checks

D. To disable database transactions

Correct Answer: B. To prevent an intentional repeat from causing an unintended duplicate effect

Question 8

Which activity is most appropriate during a code review?

A. Rejecting code solely because the reviewer prefers different colors

B. Checking correctness, security, edge cases, and test adequacy

C. Counting the author’s lines of code

D. Avoiding discussion of API compatibility

Correct Answer: B. Checking correctness, security, edge cases, and test adequacy

Question 9

What is a transitive dependency?

A. A dependency used only in printed documentation

B. A dependency required indirectly through another dependency

C. A dependency that has no version

D. A dependency written by the same developer

Correct Answer: B. A dependency required indirectly through another dependency

Question 10

Which statement about AI-generated code is most accurate?

A. It is correct if it compiles

B. It requires no license review when publicly available

C. It should be reviewed, tested, and checked for security and compliance

D. It can safely receive any sensitive production data

Correct Answer: C. It should be reviewed, tested, and checked for security and compliance

Software Engineering Principles
Chapter 7 of 15