Skip to content

Commit

Permalink
More docs
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveDunn committed Dec 10, 2023
1 parent d699870 commit 90af870
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 596 deletions.
3 changes: 3 additions & 0 deletions docs/site/Writerside/hi.tree
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
<toc-element topic="your-first-value-object.md"/>
<toc-element topic="Validation.md"/>
<toc-element topic="NormalizationTutorial.md"/>
<toc-element topic="Specifying-pre-set-values.md"/>
<toc-element topic="Serialization.md"/>
</toc-element>
<toc-element topic="how-to-guides.topic">
<toc-element topic="create-and-use-value-objects.md"/>
<toc-element topic="Validate-values.md"/>
<toc-element topic="Instances.md"/>
<toc-element topic="Normalization.md"/>
<toc-element topic="Integration.md"/>
Expand All @@ -28,6 +30,7 @@
<toc-element topic="Value-Objects-in-EFCore.md"/>
</toc-element>
<toc-element topic="Reference.md">
<toc-element topic="Configuration.md"/>
<toc-element topic="Records.md">
<toc-element topic="Differences-when-using-records.md"/>
</toc-element>
Expand Down
25 changes: 25 additions & 0 deletions docs/site/Writerside/topics/Configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Configuration

Each Value Object can have its own *optional* configuration. Configuration includes:

* The underlying type
* Any 'conversions' (Dapper, System.Text.Json, Newtonsoft.Json, etc.) - see [the Integrations page](https://github.com/SteveDunn/Vogen/wiki/Integration) in the wiki for more information
* The type of the exception that is thrown when validation fails

If any of those above are not specified, then global configuration is inferred. It looks like this:

```c#
[assembly: VogenDefaults(underlyingType: typeof(int), conversions: Conversions.Default, throws: typeof(ValueObjectValidationException))]
```

Those again are optional. If they're not specified, then they are defaulted to:

* Underlying type = `typeof(int)`
* Conversions = `Conversions.Default` (`TypeConverter` and `System.Text.Json`)
* Validation exception type = `typeof(ValueObjectValidationException)`

There are several code analysis warnings for invalid configuration, including:

* when you specify an exception that does not derive from `System.Exception`
* when your exception does not have one public constructor that takes an int
* when the combination of conversions does not match an entry
101 changes: 101 additions & 0 deletions docs/site/Writerside/topics/Specifying-pre-set-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Specifying pre-set values

In this tutorial, we'll look at how we can have pre-set values on our types.

Pre-set values have two common uses:

1. represent known values
2. represent values that cannot be externally created

Let's look at the first scenario; representing known values. Create the following type:

```c#
[ValueObject<float>]
[Instance("WaterFreezingPoint", 0.0f)]
[Instance("WaterBoilingPoint", 100.0f)]
[Instance("AbsoluteZero", -273.15f)]
public partial struct Centigrade { }
```

You can now use it like so:

```C#
Console.WriteLine(Centigrade.WaterFreezingPoint);
Console.WriteLine(Centigrade.WaterBoilingPoint);
Console.WriteLine(Centigrade.AbsoluteZero);
```

... resulting in

```
0
100
-273.15
```

These known instances can bring domain terms into your code; for instance, it's easier to read this than
numeric literals of `0` and `273.15`:

```C#
if(waterTemperature == Centigrade.WaterFreezingPoint) ...
```

Now, let's take a look at the other scenario of representing values that can't (and **shouldn't**) be
created externally. The term 'externally' user here, means **users** of the class.

Let's revisit our `CustomerId` from the [validation tutorial](Validation.md). We want to say that an instance
with a value of zero means that the customer was not specified, but we don't want users to explicitly create
instances with a value of zero. Let's try it out. Create this type again:

```C#
[ValueObject<int>]
public partial struct CustomerId
{
private static Validation Validate(int input) => input > 0
? Validation.Ok
: Validation.Invalid("Customer IDs must be greater than 0.");
}
```

We know, from the validation tutorial that this throws an exception. This means that users can't create one with
a zero value. All well and good. But **we** (the author of the type), want to create one with a zero.

We can do this with a known-instance:

```C#
[ValueObject<int>]
[Instance("Unspecified", 0)]
public partial struct CustomerId
{
private static Validation Validate(int input) => input > 0
? Validation.Ok
: Validation.Invalid("Customer IDs must be greater than 0.");
}
```

We can now use the instance of an unspecified customer id:

```C#
Console.WriteLine(CustomerId.Unspecified);

>> 0
```

This can be useful in representing optional or missing data in your domain, e.g.

```C#
public CustomerId TryGetOptionalCustomerId(string input)
{
if (string.IsNullOrEmpty(input))
{
return CustomerId.Unspecified;
}

return CustomerId.From(123);
}
```

This again makes the domain easier to read and eliminates a scenario where a `null` might otherwise be used.

There are other ways to declare instances, and there is special consideration for dates. These are covered in
this [How-to article](Instances.md)
5 changes: 3 additions & 2 deletions docs/site/Writerside/topics/Tutorials.topic
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
<section-starting-page>
<title>Tutorials</title>
<description>
These focus on how to achieve various things using Vogen, from creating your first
value object, to handling nuances of decimals when deserializing from JavaScript.
These tutorials focus on how to achieve various things using Vogen, from creating your first
value object, to more advances scenarios like handling the nuances of decimals when
deserializing from JavaScript.
</description>

<!-- Add up to 2 topics that you want to promote. Use the "type" attribute to select an icon. -->
Expand Down
3 changes: 3 additions & 0 deletions docs/site/Writerside/topics/Validate-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Validate values

Start typing here...
Loading

0 comments on commit 90af870

Please sign in to comment.