Project Technical Documentation - Implementation Part
Methodological Introduction
In general, justifications are written similarly to so-called ADRs (Architecture Decision Records):
- https://adr.github.io/
- https://github.com/joelparkerhenderson/architecture-decision-record
- https://endjin.com/blog/2024/03/adr-a-dotnet-tool-for-creating-and-managing-architecture-decision-records
- https://github.com/npryce/adr-tools
We describe what problem we are solving, what options we have, what we chose, and what are the advantages and disadvantages. We are particularly interested in disadvantages - which are usually omitted. This format applies to both system architecture, application architecture, selected libraries, testing methods, and deployment-related tools.
Elements marked in red should be described by the end of semester 2 (PRO2).
Technical Documentation Structure
1. System Architecture
1.1. C4 Diagram (Level 1 and 2) with Description and Justification of the Chosen Approach
What this chapter should contain:
- Context Diagram (C4 Level 1) - presentation of the system as a whole in the context of its users and external systems it integrates with. System boundaries and data flow directions should be clearly marked.
- Container Diagram (C4 Level 2) - decomposition of the system into main containers (applications, databases, queue systems, cache, etc.) with a description of the technologies used in each container and communication protocols between them.
- Architecture Justification - explanation of why a particular architecture was chosen (monolithic, microservices, modular monolith, serverless). Alternatives considered, decision criteria, and trade-offs the team decided on should be presented.
- Quality Attributes - description of how the chosen architecture supports non-functional requirements: scalability, availability, performance, security, maintainability.
- Architectural Constraints - documentation of external constraints affecting architectural decisions (client requirements, budget, team competencies, infrastructure).
2. Server Application
2.1. Framework
What this chapter should contain:
- Framework Selection - name and version of the chosen framework (e.g., Spring Boot, ASP.NET Core, NestJS, Django, FastAPI) with justification for the choice.
- Selection Criteria - comparative analysis of considered frameworks in terms of: ecosystem maturity, community support, learning curve, performance, library availability, compliance with project requirements.
- Disadvantages of the Chosen Solution - honest analysis of the weak points of the chosen framework and ways to mitigate them.
2.2. Application Architecture
What this chapter should contain:
- Architectural Pattern - description of the chosen pattern (e.g., Layered Architecture, Clean Architecture, Hexagonal Architecture, Vertical Slice Architecture, CQRS) with justification.
- Component Diagram (optionally C4 Level 3) - visualization of the internal application structure divided into layers/modules.
- Directory Structure - description of the source code organization with explanation of naming conventions and responsibility division.
- Request Flow - description of the processing path of a typical HTTP request through individual application layers.
- Design Patterns - list and description of key design patterns used in the application (Repository, Unit of Work, Mediator, Factory, Strategy, etc.).
2.3. Selected Libraries with Justification
What each subsection about a library should contain:
For each category of libraries, present: name and version, problem it solves, alternatives considered, selection criteria, advantages and disadvantages.
- Database Communication - ORM/micro-ORM (e.g., Entity Framework, Hibernate, Prisma, Dapper), mapping strategy, migration handling, connection pooling.
- Validation - validation library (e.g., FluentValidation, class-validator, Joi), validation strategy (where and when), validation error handling.
- Inter-module Communication - internal communication mechanism (Mediator, domain events, message bus), synchronous vs asynchronous.
- Authentication and Authorization - authentication mechanism (JWT, OAuth 2.0, OpenID Connect), libraries (e.g., IdentityServer, Keycloak, Auth0), authorization strategy (RBAC, ABAC, Claims-based).
- Logging and Monitoring - logging framework (Serilog, NLog, Winston), structured logging, APM system integration.
- Exception Handling - global error handling strategy, mapping exceptions to HTTP responses, problem details (RFC 7807).
- Serialization - JSON/XML libraries, serialization configuration, circular reference handling.
- API Documentation - OpenAPI/Swagger, documentation generation, API versioning.
2.4. Additional Chapters (Optional)
- Background Task Handling - task queues, scheduled jobs, saga/choreography implementation.
- Caching - caching strategy, distributed cache, invalidation.
- File Handling - upload, storage, processing.
- External Integrations - description of integrations with third-party systems.
3. Client Application
3.1. Framework
What this chapter should contain:
- Framework Selection - name and version (e.g., React, Angular, Vue.js, Svelte, Next.js, Nuxt) with justification.
- Rendering Strategy - choice between CSR (Client-Side Rendering), SSR (Server-Side Rendering), SSG (Static Site Generation), ISR (Incremental Static Regeneration) with justification of impact on SEO, performance, and UX.
- Meta-framework - if used (Next.js, Nuxt, SvelteKit), justification for the choice.
3.2. Application Architecture
What this chapter should contain:
- Project Structure - directory organization, division into feature modules vs layer-based structure.
- Component Patterns - component division strategy (atomic design, smart/dumb components, compound components).
- Dependency Management - dependency injection, service locator, context providers.
- Styling Strategy - CSS Modules, Styled Components, Tailwind CSS, SCSS with justification.
3.3. Selected Libraries with Justification
- State Management - solution choice (Redux, Zustand, MobX, Pinia, NgRx, Signals), state scope (local vs global), data normalization strategy.
- API Communication - HTTP library (Axios, fetch, Angular HttpClient), query caching strategy (React Query, SWR, Apollo Client).
- Validation - form and data validation (Yup, Zod, class-validator), TypeScript type integration.
- Authentication and Authorization - token storage, refresh token flow, protected routes, session handling.
- Form Handling - form library (React Hook Form, Formik, Angular Reactive Forms), validation strategy, complex form handling.
- Routing - routing library, lazy loading, code splitting, parameter and query string handling, guards.
- Internationalization (i18n) - if required, library and translation strategy.
- Component Testing - testing tools (Jest, Vitest, Testing Library).
3.4. Additional Chapters (Optional)
- Design System - UI components, component library (Material UI, Ant Design, custom).
- Error Handling - error boundaries, global error handling, user feedback.
- Performance - optimizations, memoization, virtualization, bundle analysis.
- Accessibility (a11y) - WCAG standards, audit tools.
4. Module A, B, C... (for Modular Architecture)
What this chapter should contain:
For each separated module (in case of modular monolith) or microservice, describe:
- Module Responsibility - bounded context, functional scope.
- Public Module API - contracts, interfaces exposed to other modules.
- Dependencies - which modules it depends on, which modules depend on it.
- Domain Model - key entities and aggregates in the module.
- Special Technical Solutions - algorithms, patterns specific to the module.
5. Data Persistence Layer
5.1. Chosen Database with Justification
What this chapter should contain:
- Database Type - relational (PostgreSQL, MySQL, SQL Server), document (MongoDB), graph (Neo4j), key-value (Redis) with justification for the choice.
- Requirements Analysis - which project requirements influenced the choice (ACID, scalability, data model, licensing).
- Alternatives Considered - comparison with other databases.
- Disadvantages of the Chosen Solution - limitations and ways to work around them.
5.2. Entity Diagram with Description
What this chapter should contain:
- ERD Diagram - complete entity diagram with relationships, primary and foreign keys.
- Entity Description - for each entity: name, business description, list of attributes with data types.
- Relationship Description - cardinality, optionality, operation cascading.
- Indexes - list of indexes with justification (query optimization).
- Constraints - unique, check, foreign key with justification.
5.3. Additional Chapters (Optional)
- Migration Strategy - tools, schema versioning, rollback.
- Data Seeding Strategy - test data, initial data.
- Stored Procedures and Views - if used.
- Replication and Sharding - if required for scalability.
- Backup and Disaster Recovery - backup strategy.
6. Application Testing
6.1. Introduction
What this chapter should contain:
- Testing Strategy - test pyramid, proportions between test types.
- Testing Tools - overview of frameworks and libraries used.
- Quality Metrics - code coverage, mutation testing (if applied).
- Test Environment - configuration, test data, isolation.
6.2. Unit Tests
What this chapter should contain:
- Test Scope - what is tested at the unit level (business logic, services, helpers).
- Testing Framework - (xUnit, NUnit, Jest, pytest) with justification.
- Conventions - test naming, Arrange-Act-Assert/Given-When-Then structure.
- Mocking - mock library, dependency isolation strategy.
- Examples - representative unit test examples.
6.3. Integration Tests
What this chapter should contain:
- Test Scope - integration with database, API, external systems.
- Testcontainers - if used, test container configuration.
- Fixtures and Setup - test environment preparation.
- WebApplicationFactory / TestServer - API testing.
- Examples - representative integration test examples.
6.4. End-to-End Tests
What this chapter should contain:
- Tool - (Cypress, Playwright, Selenium) with justification for the choice.
- Strategy - which scenarios are E2E tested (critical user paths).
- Page Object Pattern - if used, structure.
- Test Data - preparation and cleanup strategy.
- CI/CD - E2E test integration with pipeline.
6.5. Performance Tests
What this chapter should contain:
- Tools - (k6, JMeter, Gatling, Artillery) with justification.
- Scenarios - load testing, stress testing, spike testing.
- Metrics - response time, throughput, error rate, percentiles.
- Results and Conclusions - analysis of conducted tests, bottlenecks.
6.6. Acceptance Tests
What this chapter should contain:
- Approach - BDD (Behavior-Driven Development), if applied.
- Tools - (SpecFlow, Cucumber, Behave).
- Stakeholder Collaboration - how scenarios are defined.
- Scenario Examples - representative cases.
6.7. Additional Chapters (Optional)
- Security Tests - OWASP, SAST, DAST.
- Contract Tests - Pact, if microservices architecture.
- Mutation Tests - tools, results.
7. Application Deployment
7.1. Deployment Architecture
What this chapter should contain:
- Infrastructure Diagram - visualization of the production environment.
- Environments - development, staging, production - differences and purpose.
- Platform - cloud (AWS, Azure, GCP), on-premise, hybrid with justification.
- Containerization - Docker, Kubernetes, if used.
- Reverse Proxy / Load Balancer - Nginx, Traefik, cloud load balancer.
7.2. CI/CD Pipeline
What this chapter should contain:
- Tool - (GitHub Actions, GitLab CI, Azure DevOps, Jenkins) with justification.
- Pipeline Stages - build, test, security scan, deploy.
- Deployment Strategy - blue-green, canary, rolling update.
- Pipeline Diagram - CI/CD process visualization.
7.3. File Storage
What this chapter should contain:
- Storage Strategy - local storage, cloud storage (S3, Azure Blob, GCS).
- CDN - if used, configuration and justification.
- File Backup - backup strategy.
7.4. Configuration and Secrets
What this chapter should contain:
- Configuration Management - environment variables, configuration files.
- Secrets Management - (Vault, Azure Key Vault, AWS Secrets Manager).
- Per-environment Configuration - differentiation strategy.
7.5. Monitoring and Observability
What this chapter should contain:
- Logging - log centralization (ELK, Loki, CloudWatch).
- Metrics - Prometheus, Grafana, Application Insights.
- Tracing - distributed tracing (Jaeger, Zipkin), if applied.
- Alerting - alerting strategy, messenger integration.
- Health Checks - liveness, readiness probes.
7.6. Infrastructure Security
What this chapter should contain:
- SSL/TLS Certificates - management strategy (Let's Encrypt, managed certificates).
- Firewall and Network Policies - access configuration.
- Vulnerability Scanning - tools, frequency.
8. Summary
8.1. Achieved Goals
What this chapter should contain:
- Brief summary of implemented functionalities.
- Degree of fulfillment of requirements from the first part of the documentation.
8.2. Problems Encountered and Conclusions
What this chapter should contain:
- Technical Problems - most important challenges and how they were solved.
- Wrong Decisions - decisions that turned out to be wrong and what the team learned.
- Technical Debt - consciously incurred debt and plan for its repayment.
8.3. Further Development
What this chapter should contain:
- Planned Functionalities - development roadmap.
- Technical Improvements - refactoring, optimizations, migrations.
- Scaling - plan for increased load.
9. List of Illustrations
List of all diagrams, screenshots, and other illustrations with numbering and page references.
10. List of Tables
List of all tables contained in the documentation with numbering and page references.
11. Bibliography
What the bibliography should contain:
- Official documentation of used technologies.
- Articles and scientific publications justifying architectural choices.
- Books and educational materials.
- Sources of benchmarks and technology comparisons.
Format: consistent with the chosen citation style (e.g., IEEE, APA).
General Notes
- In the documentation, we are not interested in in-depth description of the history of a given pattern, technology, etc. In other words, we don't want many pages describing where HTML came from. We expect everyone to describe and justify their choice - the justification format should be similar to ADRs.
- Formal language is used in the documentation. We avoid colloquialisms and unexplained jargon.
- In the documentation, when justifying the choice of any technology, we try to provide sources (documentation, benchmarks, articles) that confirm our words.
- We remember about formatting. Chapters should not start at the bottom of a page (widows and orphans). Numbering of figures and tables should be consistent.
- Remember that you don't have to practice "success propaganda" in your work. The greatest value of such work is describing what problems you encountered and what wrong decisions you made. It is important to show that you make thoughtful decisions guided by analysis of pros and cons - not just what is currently trendy.
- Source code fragments - if we include code in the documentation, it should be properly formatted (syntax highlighting), described, and justified. We don't include entire files - only representative fragments illustrating the discussed solution.
- Diagrams - all diagrams should be readable, stylistically consistent, and contain a legend if using non-standard notations. Recommended tools: PlantUML, Mermaid, draw.io, Lucidchart.
- Documentation versioning - documentation should contain information about version and date of last update.
ADR - Architecture Decision Record
ADRs, or Architecture Decision Records, are a tool used in software engineering to document decisions regarding system architecture. They serve to record significant technological and design choices made during system development, as well as the justification for those choices.
The concept of ADRs was proposed by Michael Nygard (not Mark Richards - this is a common mistake) in 2011. Nygard noticed that many architectural decisions are not well documented, which leads to problems in maintaining and developing information systems. Thanks to ADRs, it is possible to track and understand the architectural decision-making process, which facilitates the management of complex projects.
ADR Structure
A typical ADR contains the following sections:
- Title - short, descriptive decision title (e.g., "Use PostgreSQL as the main database")
- Status - proposed, accepted, deprecated, superseded
- Context - description of the problem and circumstances requiring a decision
- Decision - what was decided
- Consequences - positive and negative effects of the decision
- Alternatives - what other options were considered (optional)
ADR - Location
Usually, it's best to keep ADRs "close" to the code. ADRs should represent the actual state of our code. It's best to store them together with the application code in the repository (e.g., in the /docs/adr/ directory). I recommend using command-line tools that make it easier to generate ADRs: