Understanding the Vogen Codebase
This outline covers the core concepts and design decisions behind the Vogen codebase, focusing on its ability to improve the safety of your code by addressing security vulnerabilities related to serialization, deserialization, and validation.
Value Objects: Beyond Primitive Obsession
- The Problem: Using primitives like
int
andstring
to represent domain concepts can lead to Primitive Obsession, a code smell that can introduce subtle errors and security vulnerabilities. Primitives lack inherent validation, making them susceptible to misuse. - Vogen’s Solution: Vogen introduces the concept of Value Objects (VOs). VOs are immutable, encapsulate a single concept, and enforce validation rules.
- Example from
README.md
:int customerId = 42 // This is primitive obsession
- Better approach using VOs:
CustomerId customerId = CustomerId.From(42); // Vogen's approach
- Example from
- Factory Methods: Vogen promotes the use of factory methods like
From
to create and validate VOs. This ensures that VOs are created in a consistent and safe manner.docs/nuget-readme.md
: “A value object (VO) is constructed via a factory method named From, e.g. Age.From(12)”
Instances: Special Values and Validation Control
- Need for Special Values: Sometimes, VOs need to represent special states like “unspecified” or “invalid.” These states are not always valid values of the underlying type.
- Instances to the Rescue: Instances provide a way to create special VO instances that bypass validation and normalization.
- Example from
docs/site/Writerside/topics/discussions/Home.md
:public class Person { public Age Age { get; } = Age.Unspecified; }
- Example from
Validation and Immutability
- Vogen Enforces Validation: VOs created through factory methods are automatically validated. This helps prevent the creation of invalid objects and ensures data integrity.
- Example from
docs/site/Writerside/topics/discussions/Home.md
: Instances allownew
to be used in the value object itself, which bypasses validation and normalization. More information on validation can be found in this tutorial.
- Example from
- Immutability: VOs are designed to be immutable. Once created, their state cannot be changed. This prevents accidental or malicious modification, enhancing data integrity and security.
Source Generation for Code Efficiency
- Generated Code: Vogen utilizes source generation to simplify VO usage and improve performance. The Source Generator creates code for essential functionality such as object creation, equality checks, and serialization.
- Reduced Boilerplate: Source generation reduces the amount of boilerplate code developers need to write, improving maintainability and reducing errors.
Exploring Vogen: Tutorials and How-to Guides
- Tutorials: Provide a step-by-step introduction to Vogen for new users. They guide you through building applications that use VOs. (
docs/site/Writerside/topics/Tutorials.topic
) - How-to Guides: Address specific use cases and problems, assuming a basic understanding of Vogen. (
docs/site/Writerside/topics/how-to-guides.topic
)
Key Files and Code Snippets
src/Vogen/VoTarget.cs
: Defines theVoTarget
class, which encapsulates information about a user-provided VO type, including its symbol information and syntax.- Example:
VoSyntaxInformation
stores theTypeDeclarationSyntax
for the VO, e.g.,CustomerId
.
- Example:
src/Vogen/DiscoverUserProvidedOverloads.cs
: Discovers user-provided methods likeParse
,TryParse
,ToString
, andGetHashCode
for VOs.samples/Vogen.Examples/TypicalScenarios/Instances.cs
: Demonstrates the use of Instances for creating special VO instances that bypass validation.tests/ConsumerTests/EqualityTests.cs
: Tests the equality comparison functionality for VOs.tests/ConsumerTests/HashCodeTests.cs
: Tests theGetHashCode
implementation for VOs, particularly when dealing with structs and classes.tests/ConsumerTests/SerializationAndConversionTests/RecordClassVos/IntVoTests.cs
: Tests serialization and deserialization capabilities for VOs with various JSON serializers like Newtonsoft.Json and System.Text.Json.tests/ConsumerTests/SerializationAndConversionTests/RecordStructVos/IntVoTests.cs
: Similar to the previous test, but focuses on VOs defined as record structs.Consumers.sln
: The solution file for the Vogen project.
Top-Level Directory Explanations
samples/ - This directory contains example projects that demonstrate the usage of the Vogen library. Each subdirectory represents a different example, and contains the necessary files and configurations for that example.
src/ - This directory contains the source code for the project. It includes the Vogen library itself, as well as any shared types and code fixers.
src/Vogen/ - This subdirectory contains the core Vogen library code. It includes subdirectories for diagnostics, extensions, generators, properties, rules, suppressors, templates, and binaries and object files.
tests/ - This directory contains unit tests and benchmarks for the project. It includes subdirectories for analyzer tests, consumer tests, snapshot tests, and Vogen benchmarks.
tests/AnalyzerTests/ - This subdirectory contains unit tests for the analyzer component of the Vogen library.
tests/ConsumerTests/ - This subdirectory contains unit tests for the consumer-side components of the Vogen library.
tests/SnapshotTests/ - This subdirectory contains snapshot tests, which test the output of the code generation and serialization components of the Vogen library.