Programming in C++/Java/Python

Chapter 15
Secure, Ethical, and Professional Programming Capstone

Diploma in Software Engineering
Programming in C++/Java/Python   •   Diploma

Secure, Ethical, and Professional Programming Capstone

Introduction and Context

A software project is not complete when the program runs. A professional deliverable must also satisfy documented requirements, protect users and data, be maintainable by another developer, comply with law and licensing obligations, and be deployable in a controlled manner. This chapter brings together the practical capabilities developed in C++, Java, and Python: design, implementation, testing, version control, debugging, documentation, and responsible decision-making.

A capstone project provides an environment in which technical and professional concerns interact. A choice of programming language affects libraries, performance, hiring, deployment, and security. A database design affects privacy and recovery. An AI-generated code fragment may accelerate development while introducing licensing, security, or quality risks. Consequently, programming is both an engineering activity and a governance activity.

The central principle is that quality must be designed into the development process rather than inspected into the product at the end.

Learning Objectives

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

  1. Convert stakeholder needs into requirements, acceptance criteria, and a manageable project plan.
  2. Estimate work, track progress, and use version control professionally.
  3. Compare C++, Java, and Python for an appropriate implementation context.
  4. Apply secure coding, privacy, accessibility, licensing, and governance practices.
  5. Conduct useful code reviews and interpret practical engineering metrics.
  6. Design a reproducible deployment process, including cloud-native concerns.
  7. Evaluate AI coding assistants critically and document technical decisions.
  8. Present, assess, and improve a complete multi-language capstone project.

1. From Stakeholder Need to Engineering Requirement

A stakeholder statement such as “the system should be fast and easy to use” is not sufficiently precise for implementation or testing. Requirements should express a capability, a constraint, or a quality property in terms that can be verified.

A useful functional requirement identifies an actor, an action, and an expected result. For example: “A registered user shall be able to export their transaction history as a CSV file.” A non-functional requirement describes a quality attribute: “For 95% of requests under the defined normal load, the service shall respond within 500 milliseconds.” The latter is testable because it specifies a population of requests, a condition, and a threshold.

Acceptance criteria convert requirements into observable evidence. A user story may be written as:

As a library member, I want to reserve an available book so that I can collect it later.

Its acceptance criteria might state that an authenticated member can reserve only an available item, that the reservation receives a timestamp, and that a confirmation is displayed. Criteria should include normal, invalid, boundary, and authorization cases.

Requirements should be prioritized. The MoSCoW classification—Must have, Should have, Could have, and Won’t have in this release—helps control scope. It is not a substitute for stakeholder agreement: “Won’t have” means explicitly deferred, not forgotten.

Traceability links requirements to design components, source files, tests, and release evidence. A small traceability matrix may contain the requirement identifier, implementation location, test identifier, result, and responsible person. This supports change impact analysis and auditability.

2. Estimation and Planning

Estimation is a reasoned forecast, not a promise. Begin by decomposing work into tasks small enough to estimate and review. Typical work packages include requirements clarification, interface design, database design, implementation, testing, security review, documentation, and deployment.

For uncertain tasks, the three-point estimate uses an optimistic estimate a, a most-likely estimate m, and a pessimistic estimate b. The expected duration in the PERT approximation is:

E = (a + 4m + b) / 6

Here, all three variables use the same time unit, such as hours. The approximation assumes that the most-likely estimate deserves four times the weight of either extreme; it is useful for planning but does not remove uncertainty. For a = 2, m = 5, and b = 11 hours, E = (2 + 4(5) + 11)/6 = 33/6 = 5.5 hours.

A rough effort model can be based on historical data. If a team has completed similar tasks at an average rate of 12 validated tasks per person-week, then 36 comparable tasks require approximately three person-weeks, assuming similar complexity and no major dependency. Person-weeks are not calendar weeks: three people may not complete the work in one week because communication, sequencing, and integration impose constraints.

A credible plan includes contingency for known uncertainty, explicit dependencies, and a definition of done. The definition of done should include reviewed code, passing automated tests, updated documentation, security checks, and reproducible build or deployment instructions—not merely “code committed.”

3. Version Control and Collaborative Delivery

Git provides a history of changes, authorship, branching, merging, and recovery. A professional repository normally contains source code, tests, configuration templates, documentation, and build instructions. It must not contain passwords, private keys, production tokens, or unnecessary personal data.

A practical workflow is:

  1. Create a small issue describing one coherent change.
  2. Develop on a short-lived branch.
  3. Make focused commits with informative messages.
  4. Run local tests and static checks.
  5. Open a pull request with a description, evidence, and risk statement.
  6. Obtain review, resolve comments, and merge using the team’s agreed policy.
  7. Tag or otherwise identify a reproducible release.

Branches are not a replacement for communication. Long-lived branches increase merge conflicts and delay integration. Small, frequent integration makes defects easier to locate. Commit messages should describe intent, such as “Validate reservation ownership before cancellation,” rather than “fix code.”

A pull request should explain what changed, why it changed, how it was tested, and what remains uncertain. Reviewers should inspect correctness, security, readability, test adequacy, error handling, performance implications, and compatibility with project requirements. Review comments should address the artifact, not attack the author.

4. Choosing Among C++, Java, and Python

Language choice is a technical decision constrained by the problem and operating environment.

ConcernC++JavaPython
Typical strengthSystems, embedded, performance-sensitive applicationsLarge enterprise services and portable applicationsAutomation, data work, scripting, rapid application development
Memory modelManual control with RAII and smart pointersGarbage collection with managed runtimeGarbage collection and highly dynamic objects
Main riskMemory-safety defects and complex ownershipRuntime configuration, dependency complexity, concurrency errorsRuntime performance, dynamic typing errors, dependency management
Professional controlCompiler warnings, sanitizers, static analysisType checking, testing, static analysis, dependency scanningType hints, linters, tests, package and vulnerability scanning

These are tendencies rather than absolute rules. C++ can be appropriate where latency or hardware control dominates, but resource ownership must be explicit. Java provides a mature ecosystem for long-running services, but garbage collection and runtime configuration require operational understanding. Python can produce clear solutions quickly, but type hints, tests, and careful dependency control are important in larger systems.

A multi-language project should define boundaries. For example, a Python command-line client may call a Java service, while a C++ module performs image processing. The interfaces should use stable, documented protocols such as HTTP with JSON or a message format. Each component needs its own build, test, dependency, and security process. Using several languages without a clear architectural reason increases operational and maintenance cost.

A technical decision record should state the context, options considered, decision, consequences, and conditions that would cause reconsideration. This prevents teams from treating personal preference as engineering evidence.

5. Secure Coding and Threat-Aware Design

Security begins before implementation. Threat modeling asks what must be protected, from whom, and by what attack paths. A simple process identifies assets, trust boundaries, entry points, threats, mitigations, and residual risks. The STRIDE categories—spoofing, tampering, repudiation, information disclosure, denial of service, and elevation of privilege—can provide a useful vocabulary, although no checklist replaces system-specific analysis.

Core secure coding practices include:

  • Validate input according to expected type, length, range, and business meaning.
  • Use parameterized database queries rather than string concatenation.
  • Apply least privilege to users, services, files, and cloud roles.
  • Authenticate users securely and authorize every protected operation server-side.
  • Store passwords using a modern, salted, adaptive password-hashing algorithm; never reversible encryption or plain text.
  • Protect secrets with a secret manager or protected environment configuration, not source control.
  • Avoid exposing stack traces, tokens, personal data, or internal topology in user-facing errors.
  • Use secure transport and verify certificates correctly.
  • Keep dependencies updated and scan them for known vulnerabilities.
  • Log security-relevant events without logging passwords, access tokens, or unnecessary personal information.

Memory safety deserves special attention in C++. Buffer bounds, object lifetime, integer conversion, and ownership errors may lead to crashes or exploitable behavior. RAII, standard containers, smart pointers, compiler warnings, sanitizers, and static analysis reduce risk. In Java and Python, memory corruption is less common in ordinary application code, but injection, insecure deserialization, authorization flaws, and dependency vulnerabilities remain serious.

Security controls should be tested. A test that confirms a user can view their own record is incomplete unless another test confirms that they cannot view a different user’s record by changing an identifier in the request. This is an authorization test, not merely an input-validation test.

6. Privacy, Ethics, Accessibility, and Licensing

Privacy is not equivalent to security. Security protects information from unauthorized access or alteration; privacy concerns appropriate collection, use, retention, sharing, and deletion of information. A responsible project applies data minimization: collect only what the stated purpose requires. It should document purpose, retention, access, deletion, and user rights according to applicable law and institutional policy. Legal obligations vary by jurisdiction, so developers must consult the relevant privacy authority or organizational counsel rather than assume that one regulation applies everywhere.

Ethical programming considers people who may be harmed even when an action is technically legal. Relevant questions include: Who benefits? Who bears risk? Could the system discriminate? Can a person challenge an automated decision? Is consent meaningful? Are vulnerable users affected? Professional codes, such as those published by computing professional bodies, emphasize public welfare, honesty, competence, privacy, and avoidance of harm.

Accessibility is an engineering requirement. Interfaces should support keyboard operation, meaningful labels, readable contrast, scalable text, captions or transcripts where needed, clear error messages, and compatibility with assistive technologies. Accessibility should be tested with automated tools and human users where possible; automated checks do not identify every usability barrier.

Licensing governs how software may be used, modified, and distributed. Permissive licenses generally allow broad reuse subject to conditions such as attribution. Reciprocal or copyleft licenses may impose obligations on distribution of derivative works. A project should maintain a dependency inventory and preserve required copyright and license notices. “Open source” does not mean “without obligations,” and copying code from an unknown source may create both licensing and security risk.

7. AI Coding Assistants and Professional Judgment

AI coding assistants can generate boilerplate, explain unfamiliar APIs, propose tests, and support refactoring. They can also produce insecure, obsolete, non-compiling, biased, or license-incompatible output. Generated code is an untrusted suggestion, not an authority.

A professional workflow is:

  1. Define the requirement and constraints independently of the tool.
  2. Ask for a small, inspectable contribution.
  3. Review the output line by line.
  4. Test normal, invalid, boundary, security, and failure cases.
  5. Check dependencies, licenses, data handling, and performance.
  6. Record substantial tool use when institutional policy or project governance requires it.

Do not paste confidential source code, personal data, credentials, or proprietary designs into an external service without authorization. Prompts and outputs may be retained or used according to the provider’s terms. Teams should establish rules for approved tools, data classification, attribution, human review, and incident reporting.

AI assistance does not transfer accountability. The developer who commits code remains responsible for understanding and validating it. In education, undisclosed generated work may also violate academic-integrity rules.

8. Metrics, Review, and Evidence of Quality

Metrics are signals for learning and decision-making, not targets to manipulate. Useful measures include:

  • Requirement completion and acceptance-test pass rate.
  • Defects found before and after release.
  • Review turnaround time and unresolved review comments.
  • Build success rate and test duration.
  • Deployment frequency, lead time, change-failure rate, and recovery time.
  • Vulnerabilities by severity and age.
  • Accessibility findings and dependency freshness.

A metric needs a definition and context. “Test coverage” is not the percentage of correct code. Line coverage records executed lines; branch coverage records exercised decision outcomes. High coverage can coexist with weak assertions and missing security tests. Coverage should therefore guide investigation rather than serve as a sole quality criterion.

Code review is most effective when changes are small and the review purpose is clear. A reviewer should first understand the requirement, then examine behavior, failure paths, security boundaries, maintainability, and test evidence. Automated checks should handle formatting and routine rules so that human attention can focus on design and risk.

9. Deployment and Cloud-Native Development

A reproducible deployment describes the environment, dependencies, configuration, database changes, health checks, and rollback or recovery procedure. Configuration differs across environments, but the application artifact should be built consistently. Continuous integration can compile each component, run tests, scan dependencies, and publish evidence. Continuous delivery makes a verified release available for controlled deployment; continuous deployment automatically releases it when policy permits.

Cloud-native development commonly uses independently deployable services, containers, declarative infrastructure, externalized configuration, observability, and automated scaling. These patterns are not automatically superior. A small capstone may be harmed by unnecessary microservices, distributed transactions, network failure, and operational complexity. A modular monolith may provide clearer boundaries at lower cost.

A service should expose useful health information without revealing secrets. Logs, metrics, and traces should support diagnosis while respecting privacy. Backups must be tested through restoration, because an untested backup is only an assumption. Deployment decisions should address availability, cost, data location, identity, access control, and vendor dependence.

10. An Illustrative Capstone Case

Background

A fictional student team, Northstar, builds a community tool-lending platform. Members search for tools, reserve them, and receive reminders. The project uses a Python web client, a Java service for lending rules, and a C++ library for barcode and image processing.

Problem

The first prototype stores passwords in a local file, concatenates SQL strings, accepts reservations without checking ownership, and has no reproducible deployment. The team also proposes uploading borrower records to an AI assistant to generate test data.

Analysis

The assets include identity data, reservation history, and images. Threats include credential theft, unauthorized record access, injection, accidental disclosure, and service disruption. Privacy analysis shows that exact addresses and full birth dates are unnecessary for the stated purpose. The language split is reasonable only if the interfaces are stable and the C++ component provides measurable value.

Approach and Solution

The team creates a requirements and traceability matrix, prioritizing search, authenticated reservation, cancellation, and accessibility. They replace plain-text passwords with adaptive password hashing, use parameterized queries, enforce authorization in the Java service, and remove unnecessary personal fields. Secrets are stored outside the repository.

The C++ component uses bounds-checked containers where suitable, RAII, compiler warnings, sanitizers, and tests for malformed images. Python and Java dependencies are pinned or constrained, scanned, and reviewed. The team documents a JSON API contract and adds contract tests. Pull requests require one peer review and passing automated checks.

The team refuses to upload real borrower records to an external AI service. Instead, it generates synthetic data, reviews any generated test code, and records the tool’s use. Accessibility testing confirms keyboard navigation, labels, focus visibility, and meaningful error messages. A containerized deployment runs in a staging environment with a database migration, health check, backup-restore test, and rollback instructions.

Outcome

The final release has fewer features than the original wish list but has clear acceptance evidence, no known critical dependency vulnerabilities, tested authorization boundaries, and a reproducible deployment. Performance testing identifies the image-processing path as the main cost, so the team documents it as a future optimization rather than prematurely distributing the system into additional services.

Learning Points

The case demonstrates that scope control, security, privacy, accessibility, licensing, and deployment are interconnected. A technically impressive feature is not valuable if it violates user trust or cannot be maintained. The strongest evidence comes from traceable requirements, tests, review records, and explicit decisions.

11. Governance, Risk, and Emerging Trends

Governance defines who may make decisions, what evidence is required, and how exceptions are handled. A small team can use a lightweight decision log, risk register, secure-development checklist, dependency inventory, and release approval record. Risks should have an owner, likelihood, impact, mitigation, and review date. Risk ratings are aids to prioritization, not precise measurements of future harm.

Emerging language trends include stronger static typing in traditionally dynamic ecosystems, memory-safe systems programming, improved package and build tooling, and language features designed for concurrency. These trends matter because language design influences defect classes and developer productivity. However, adopting a new language should be based on ecosystem maturity, team competence, interoperability, tooling, long-term support, and operational fit—not novelty.

Supply-chain security is increasingly important. Projects should pin or constrain dependencies appropriately, verify package sources, generate software bills of materials where required, sign releases when feasible, and monitor vulnerability advisories. Reproducible builds and provenance information improve confidence that the released artifact corresponds to reviewed source.

Challenges and Limitations

No process guarantees secure or ethical software. Requirements can be incomplete, metrics can be gamed, automated scanners produce false positives and false negatives, and code review can miss subtle defects. Privacy laws and licensing obligations differ across jurisdictions and products. Threat models become obsolete when architecture or attackers change. Cloud services and AI tools introduce dependency, availability, data-governance, and vendor risks.

Teams must therefore combine automation with expert judgment, user feedback, periodic reassessment, and transparent documentation. The appropriate level of process depends on risk: a medical or financial system requires stronger evidence and controls than a private classroom prototype, although basic security and honesty remain necessary in every context.

Best-Practice Checklist

Before submission or release, confirm that the team can answer “yes” to the following:

  • Are requirements prioritized, testable, and traceable?
  • Is the work estimated, assigned, and monitored with assumptions stated?
  • Does version control show focused changes and reviewed integration?
  • Are secrets absent from the repository?
  • Are authentication, authorization, validation, error handling, and dependency risks tested?
  • Is personal data minimized, protected, retained, and deleted appropriately?
  • Are accessibility, licensing, and AI-use obligations documented?
  • Are metrics defined rather than presented without context?
  • Can another person build, test, deploy, restore, and roll back the system?
  • Are major technical decisions and residual risks visible?

Chapter Summary

Professional programming extends beyond writing executable statements. A capstone project should begin with verifiable requirements and a controlled estimate, proceed through disciplined version control and review, and finish with tested, documented, reproducible deployment. C++, Java, and Python each offer valuable strengths, but language choice must follow system constraints and operational evidence.

Secure coding requires threat-aware design, validation, least privilege, safe secret handling, dependency control, and authorization testing. Privacy, accessibility, ethics, and licensing are design responsibilities rather than final paperwork. AI coding assistants can improve productivity only when their output, data use, provenance, and security implications are reviewed by accountable developers. Metrics provide evidence when definitions and limitations are explicit. Cloud-native practices can improve delivery, but unnecessary distribution creates cost and failure modes. Governance connects all these concerns through decisions, ownership, risk records, and release evidence.

Key Terms

Requirement: A documented capability, constraint, or quality expectation.

Acceptance criterion: A condition used to determine whether a requirement is satisfied.

Traceability: The linkage among requirements, implementation, tests, and release evidence.

PERT estimate: A weighted three-point estimate using optimistic, most-likely, and pessimistic durations.

Version control: A system for recording, comparing, collaborating on, and recovering changes.

Pull request: A proposed repository change submitted for review and integration.

Threat model: An analysis of assets, attackers, boundaries, threats, and mitigations.

Least privilege: Giving an identity only the access required for its legitimate task.

Authentication: Establishing who a user or service is.

Authorization: Determining what an authenticated identity may do.

Privacy: Responsible control of personal information’s collection, use, sharing, and retention.

Accessibility: Designing software for people with diverse abilities and assistive technologies.

Software license: Legal terms governing use, modification, and distribution of software.

Static analysis: Automated examination of source or binaries without normal execution.

Test coverage: A measure of which selected code elements or paths tests execute.

Continuous integration: Frequent automated integration and verification of changes.

Cloud-native: Development emphasizing automated, observable, deployable services and infrastructure practices suited to cloud environments.

Technical decision record: A document preserving context, alternatives, decisions, and consequences.

Software bill of materials: An inventory of components included in a software artifact.

Residual risk: Risk remaining after controls and mitigations are applied.

Review Questions

Short Answer Questions

  1. Why should a requirement include acceptance criteria?
  2. State the difference between authentication and authorization.
  3. Why must AI-generated code be reviewed and tested?
  4. Give two examples of information that should not be committed to a repository.
  5. What is the purpose of a technical decision record?

Long Answer Questions

  1. Explain a professional Git-based workflow from issue creation to release, including the role of code review.
  2. Compare C++, Java, and Python for a multi-language project and discuss the risks of unclear language boundaries.
  3. Discuss how security, privacy, accessibility, and licensing should influence requirements and design.
  4. Explain why code coverage is useful but insufficient as a measure of software quality.
  5. Describe the components of a reproducible deployment and evaluate when a modular monolith may be preferable to microservices.

Analytical / Application Questions

  1. A reservation service lets a user change an account identifier in a request and view another member’s history. Identify the security weakness, propose a control, and specify a test that would demonstrate the fix.
  2. A task has optimistic, most-likely, and pessimistic estimates of 2, 5, and 11 hours. Calculate its PERT expected duration and explain one limitation of the estimate.
  3. Design a governance plan for a student project that uses an external AI coding assistant. Include data restrictions, review responsibilities, licensing checks, testing, and disclosure requirements.

Multiple Choice Questions with Answers

Question 1

Which item makes a software requirement directly testable?

A. A broad statement that the system should be modern

B. A measurable response-time threshold under a stated load

C. A developer’s preferred programming language

D. A list of possible future features

Correct Answer: B. A measurable response-time threshold under a stated load

Question 2

Using the PERT approximation with a = 2, m = 5, and b = 11 hours, what is the expected duration?

A. 4.0 hours

B. 5.0 hours

C. 5.5 hours

D. 6.5 hours

Correct Answer: C. 5.5 hours

Question 3

Which practice best prevents SQL injection?

A. Concatenating user input after escaping a few characters

B. Using parameterized queries

C. Displaying database errors to the user

D. Storing SQL statements in comments

Correct Answer: B. Using parameterized queries

Question 4

What is the primary purpose of authorization?

A. To establish a user’s identity

B. To compress user data

C. To determine what an authenticated identity may do

D. To compile source code

Correct Answer: C. To determine what an authenticated identity may do

Question 5

Which item should normally be excluded from a version-control repository?

A. A README file

B. An automated test

C. A source-code license notice

D. A production access token

Correct Answer: D. A production access token

Question 6

Why is high test coverage not proof of high software quality?

A. Coverage tools always modify the program

B. Executed code may have weak assertions and omit important scenarios

C. Coverage can be measured only in C++

D. Coverage eliminates the need for code review

Correct Answer: B. Executed code may have weak assertions and omit important scenarios

Question 7

Which statement best describes privacy?

A. It is identical to encryption

B. It concerns appropriate collection, use, sharing, and retention of information

C. It applies only to government systems

D. It means every available field must be collected

Correct Answer: B. It concerns appropriate collection, use, sharing, and retention of information

Question 8

What is the safest professional view of AI-generated code?

A. It is trusted if it compiles

B. It is an untrusted suggestion requiring review and testing

C. It is automatically free of licensing obligations

D. It removes developer accountability

Correct Answer: B. It is an untrusted suggestion requiring review and testing

Question 9

Which practice supports reproducible deployment?

A. Relying on undocumented machine-specific settings

B. Changing dependencies manually on each server

C. Documenting dependencies, configuration, tests, and recovery procedures

D. Deploying without a staging environment or rollback plan

Correct Answer: C. Documenting dependencies, configuration, tests, and recovery procedures

Question 10

What does least privilege mean?

A. Giving every service administrator access

B. Giving an identity only the access needed for its legitimate task

C. Disabling all authentication

D. Allowing users to select their own permissions without review

Correct Answer: B. Giving an identity only the access needed for its legitimate task

Programming in C++/Java/Python
Chapter 15 of 15