Software assurance

How I evaluate an unfamiliar software system

A repeatable path from delivered artifacts and documentation to defensible findings about what a system actually does, how confidently it is understood, and what should happen next.

Evaluating unfamiliar software is not the same as performing a code review, running a scanner, or following an installation guide. Each reveals something useful, but none is sufficient by itself. The real task is to build an evidence-backed understanding of a system while preserving the distinction between what was delivered, what was documented, what was observed, and what was inferred.

Those observations have meaning only in context. The system must be judged against the mission it is intended to accomplish, the written requirements that govern it, and the maturity expected at that point in its lifecycle.

The goal is not to prove that software is good or bad. It is to make its demonstrated capabilities, risks, uncertainties, and ownership burden visible enough to support a decision.

1. Define the decision before collecting evidence

An evaluation should begin with the decision it is meant to inform. A source-selection assessment, technical-baseline review, onboarding exercise, operational-readiness check, and modernization study can examine the same repository and reasonably emphasize different evidence.

I establish the evaluation boundary, representative workflows, applicable requirements, current and expected maturity, required environments, expected outputs, and the confidence needed for the decision. A limitation that is normal and manageable during early development may be unacceptable when the same system is presented for operational acceptance. I also record explicit exclusions. Without that frame, teams tend to collect large quantities of technically interesting information that never resolves the actual question.

2. Establish provenance and inventory the delivery

Before changing anything, preserve what arrived. Record versions, manifests, hashes, repository state, build artifacts, configuration, dependency declarations, documentation, and supplied test data. Confirm that the expected delivery is present and internally consistent.

This is more than administrative hygiene. If the delivered source, documentation, binaries, deployment scripts, and version labels do not agree, every later result needs that qualification. Provenance is the foundation for reproducibility and for maintaining a government- or customer-owned technical baseline.

3. Treat onboarding as an engineering test

Follow the supplied instructions in a controlled environment before relying on expert intuition to repair them. Record ambiguous steps, missing dependencies, incorrect paths, stale configuration, environment assumptions, and manual knowledge supplied outside the documentation.

Necessary corrections should be small, explicit, and reversible. The resulting deviation log is an evaluation artifact: it measures how much undocumented expertise is required before the software can be operated by someone other than its original developers.

4. Run a representative thread through the system

A successful build or deployment does not demonstrate useful system behavior. Select a known data set or operationally representative scenario and trace it through the system. Identify the inputs, transformations, interfaces, state changes, outputs, and expected observables before execution.

The thread should be large enough to cross meaningful architectural boundaries but controlled enough that unexpected behavior can be investigated. When possible, include a normal path, an invalid or degraded input, and a recovery path.

5. Use logs and data flow to reconcile claims with behavior

Observe what each application or service produces, consumes, and reports. Compare logs, messages, stored data, user-visible output, and interface behavior against documentation and the expected scenario.

This often reveals configuration errors, undocumented dependencies, silent fallback behavior, interface mismatches, brittle ordering, weak error handling, or features that technically execute without producing a trustworthy result. Troubleshooting these discrepancies is part of the evaluation because it exposes the system’s real operational model.

6. Use automated analysis as instrumentation

Static analysis, dependency inspection, test results, complexity metrics, security scanners, and build warnings can efficiently identify areas that deserve attention. They are sensors, not verdicts. Tool findings must be interpreted in the context of the language, architecture, mission, written requirements, expected maturity, generated code, accepted risk, and actual execution.

I look for convergence. A warning becomes more meaningful when it aligns with a failed workflow, weak test boundary, recurring defect, confusing implementation, or documented technical debt.

7. Review representative code by risk

Exhaustive manual review is rarely possible for a substantial codebase. Sampling should therefore be deliberate. Useful targets include critical data paths, interface boundaries, state machines, error and recovery handling, security-sensitive code, configuration loading, unusually complex modules, generated-code boundaries, and areas implicated by runtime or automated findings.

The aim is not to impose personal style preferences. It is to assess whether important behavior can be understood, changed, tested, and operated without unacceptable hidden knowledge or fragility.

8. Test documented features from the user’s perspective

Newly delivered or materially changed features should be exercised as documented. Confirm that the workflow is discoverable, the interface communicates state and failure, and the result is representative—not merely that a control exists or a request returns successfully.

User-interface feedback belongs in a software evaluation when the interface affects correct operation, diagnosis, recovery, or trust.

9. Separate findings from uncertainty

A useful report distinguishes demonstrated defects, documentation gaps, technical debt, operational risks, maintainability concerns, and unresolved questions. Each finding should state the evidence, conditions, likely impact, confidence, and a proportionate recommendation.

This prevents two common errors: presenting uncertainty as a defect, and allowing the absence of evidence to become evidence of acceptability.

10. Produce an actionable technical record

The final report should make it possible for decision-makers and developers to act without reconstructing the entire evaluation. It should preserve enough detail to reproduce significant observations while remaining clear about scope and confidence.

Good findings are specific enough to verify and flexible enough to let the responsible engineering team choose an appropriate implementation. The objective is shared technical understanding, not a rhetorical victory.

Public boundary

This methodology intentionally omits customer data, contractor findings, nonpublic architectures, program-specific evaluation criteria, and operational details. It describes a reusable engineering practice rather than any particular assessment.