(Feel free to browse the checkpoint for step 2 as you follow along.)
For our data model, we will begin with how we will store it. At a high level:
- Web logs have a name, an optional subtitle, a theme, a URL, and a time zone
- Users have an e-mail address, a password, a first name, a last name, a preferred name, and a personal URL
- Categories have a name, a URL-friendly "slug", and a description
- Posts have a title, a status, a permalink, when they were published and last updated, 0 or more tags, the text of the post, and a list of revisions of that post
- Pages have a title, a permalink, when they were published and last updated, whether they should show in the default page list (think "About", "Contact", etc.), the text of the page, and a list of revisions to that page
- Posts and Pages can be authored in HTML or Markdown
- Comments have a name, an e-mail address, an optional URL, a status, when they were posted, and the text of the comment
As far as relationships among these entities:
- Users can have differing authorization levels among the different web logs to which they are authorized
- Categories, Posts, and Pages all each belong to a specific web log
- Comments belong to a specific Post
- Posts are linked to the user who authored them
- Categories can be nested (parent/child)
- Comments can be marked as replies to another comment
- Posts can be assigned to multiple Categories (and can have multiple Comments, as implied above)
- Revisions (Posts and Pages) will track the date/time of the revision and the text of the post or page as of that time
Both Uno and Dos will use the same C# model. For Tres, we'll convert classes to F# record types (and
null checks to
Options). For Quatro and Cinco, we'll make some concrete types for some of these primitives, making it more difficult to represent an invalid state within our model. (We'll also deal with the implications of those in step 3.)
Our C# data model looks very much like one you'd see in an Entity Framework project. The major difference is that what would be the navigation properties; collections (ex. the
Revisions collection in the
Post) are part of the type, rather than a
Revision being its own entity, while parent navigation properties (ex.
WebLog for entities that define a
WebLogId property) do not exist. Even if you are unfamiliar with Entity Framework, you will likely easily see how this model could be represented in a relational database.
src directory, add
nuget MarkdownSharp to
paket.dependencies, and add
MarkdownSharp to the
paket.references file for each project. This is the library we'll use to generate HTML from Markdown article content.
Some other design decisions:
- We will use strings (created from
Guids, utilizing the
MiniGuidpackage to preserve space) as our Ids for entities, and all of documents will have
Idas the property (this supports the convention RavenDB uses to identify document identifiers).
- Authorization levels, post statuses, and comment statuses are represented as strings, but we provide a means to avoid magic strings in the code while dealing with these.
- Properties representing date/time will be stored as
int64, representing ticks. (We'll use NodaTime for manipulation, but this would also support using something built-in like
- While best practices dictate properly commenting all classes and public properties/fields, we will exclude these for brevity's sake.
Uno / Dos - In Depth
Tres - In Depth
Quatro / Cinco - In Depth