{"id":1550,"date":"2019-06-19T00:00:00","date_gmt":"2019-06-18T22:00:00","guid":{"rendered":"https:\/\/demo.sidekick.be\/itenium\/datestart-and-dateend\/"},"modified":"2025-11-28T13:31:44","modified_gmt":"2025-11-28T12:31:44","slug":"datestart-and-dateend","status":"publish","type":"post","link":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/","title":{"rendered":"DateStart + DateEnd"},"content":{"rendered":"<h1 id=\"basic-example\">Basic Example<\/h1>\n<p>Consider the following class:<\/p>\n<pre><code class=\"language-c#\">class Person {\n    public string FirstName;\n    public string LastName;\n    public string Initials;\n    public string Address;\n    public string Street;\n    public int HouseNumber;\n    public string Telephone;\n    public string Mobile;\n    public string Email;\n    public string WorkAddress;\n    public string WorkStreet;\n    public string WorkHouseNumber;\n    public DateTime ActiveStart;\n    public DateTime? ActiveEnd;\n    \/\/ ... and many more?\n}\n<\/code><\/pre>\n<p>And how beautiful it could\u2019ve been:<\/p>\n<pre><code class=\"language-c#\">class Person {\n    \/\/ The first version was quite obfuscated, while in this version it's\n    \/\/ quite obvious what's in it by merely glancing at the declaration.\n    public Name Name;\n    public Contact Contact;\n    public Address HomeAddress;\n    public Address WorkAddress;\n    public DateRange Active;\n}\n\nclass Name {\n    \/\/ Please don't repeat the Name for each property here\n    \/\/ Considering the current class, we know the context!\n    public string First;\n    public string Last;\n    public string Initials;\n}\n<\/code><\/pre>\n<h1 id=\"advantages\">Advantages<\/h1>\n<h4 id=\"for-the-ide\">For the IDE<\/h4>\n<p>Instead of a long list of properties that may be difficult to navigate in your IDE, where it is difficult to spot that one property you need, one could instead split it up in things that logically belong together to keep intellisense small and focused.<br \/> Keep data that belongs together &#8211; together!<\/p>\n<h4 id=\"for-the-ui\">For the UI<\/h4>\n<p>Such stuff is usually displayed together. All the way down to the frontend, passing an <code>Address<\/code> to an <code>AddressComponent<\/code> is very preferable over passing those properties in separately.<\/p>\n<h4 id=\"for-expressiveness\">For Expressiveness<\/h4>\n<p>Without our precious <code>ValueObject<\/code>, we would end up creating all sorts of helper classes for often sought after functionality, all scattered around the codebase, some perhaps getting duplicated by different programmers or even for different UserStories.<\/p>\n<p>Some of these helper methods would be much better off being members of a <code>ValueObject<\/code> instead. We get better IDE discoverability and rather than having to pass some or all properties of an entity into an algorithm, we invoke a well-named method on the ValueObject in true <a href=\"https:\/\/martinfowler.com\/bliki\/TellDontAsk.html\">TellDontAsk<\/a> style.<\/p>\n<p>And isn\u2019t that what Object Oriented Design is all about? \ud83d\ude07<\/p>\n<h1 id=\"recognition\">Recognition<\/h1>\n<p>If you look, <code>ValueObject<\/code> opportunities will present themselves.<\/p>\n<h2 id=\"technical-valueobjects\">Technical ValueObjects<\/h2>\n<p>Classes are very technical in nature and so there\u2019ll be purely technical candidates like, for example, a (still?) popular one:<br \/><code>CreatedOn + CreatedBy<\/code> and <code>UpdatedOn + UpdatedBy<\/code>.<br \/> Why clutter (all) your entities with 4 superfluous properties if you can hide them behind a single <code>Audit<\/code> ValueObject?<\/p>\n<h2 id=\"domain-valueobjects\">Domain ValueObjects<\/h2>\n<p>It is the <code>ValueObjects<\/code> derived from the Business Domain that often offer the most value however. Helper functions for a <code>DateRange<\/code> only go as long as a <code>IsIn(DateTime)<\/code>. For Domain ValueObjects, this can be whatever rabbit Marketing pulls out of their hat depending on the current lunar phase, so the possibilities are endless!<\/p>\n<h3 id=\"not-invented-here-syndrome\">Not Invented Here Syndrome<\/h3>\n<p>I never thought I\u2019d ever say this: Do not use a package. Yes, there is that well-known and fully-fledged <code>DateRange<\/code> package out there. 80% of its features are probably not useful for your problem domain though. Again you get a long list of methods that basically clutter your IDE. Super handy features that are applicable only in your domain will most likely not be available, as your business probably has very particular requirements.<\/p>\n<h3 id=\"business-domain-example\">Business Domain Example<\/h3>\n<pre><code class=\"language-c#\">\/\/ A domain where we work with measured stuff\nclass MeasurementResults {\n    public decimal Value1;\n    public int Value1Precision;\n    public decimal Value2;\n    public int Value2Precision;\n    public decimal Value3;\n    public int Value3Precision;\n}\n\n\/\/ Could be turned into\nclass MeasurementResults {\n    public Measurement Result1;\n    public Measurement Result2;\n    public Measurement Result3;\n}\n\nclass Measurement {\n    public decimal Value;\n    public int Precision;\n}\n<\/code><\/pre>\n<h1 id=\"random-thoughts\">Random Thoughts<\/h1>\n<h4 id=\"the-true-enemy\">The True Enemy?<\/h4>\n<p>Well I guess that missing <code>ValueObjects<\/code> are often an unfortunate side-effect of using a relational database. Your SQL database simply likes things flat. Your ORM probably has something like Custom Types (Hibernate), Complex Types (EF) or Owned Entities (EF Core). If you use an ORM it can probably do the ValueObject creation for you.<\/p>\n<h4 id=\"derive-dont-store\">Derive, Don\u2019t Store<\/h4>\n<p>If you can calculate something from existing state, do so. Once stored separately, it will, at some point be out of sync, I guarantee it.<\/p>\n<pre><code class=\"language-c#\">class Person {\n    public string FirstName;\n    public string LastName;\n\n    \/\/ This simply does not get out of sync\n    \/\/ Otherwise each day is trying to remember if the\n    \/\/ FullName starts or ends with the FirstName\n    \/\/ +You have less state to manage, so hurray!\n    public string FullName =&gt; $\"{FirstName} {LastName}\";\n}\n<\/code><\/pre>\n<h1 id=\"conclusions\">Conclusions<\/h1>\n<p>Not creating a value object for coherent pairs of value types is a missed opportunity? \ud83d\ude02<\/p>\n<h1>Extras<\/h1>\n<p><b>Other interesting reads<\/b><\/p>\n<ul>\n<li><a href=\"https:\/\/www.martinfowler.com\/books\/eaa.html\">Patterns of Enterprise Application Architecture &#8211; Martin Fowler<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/modeling\/owned-entities\">EF Core Owned Entities<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<h1 class=\"hide-from-excerpt\" id=\"valueobjects\">ValueObjects<\/h1>\n<p>A ramble against objects containing <code>DateStart<\/code> &amp; <code>DateEnd<\/code> pairs of properties.<\/p>\n<p>Some of their equally evil relatives:<\/p>\n<ul>\n<li><code>DateStart<\/code> &amp; <code>TimeSpan<\/code> or <code>Day\/Month only in DateTime<\/code>, etc.<\/li>\n<li><code>decimal Money<\/code> &amp; <code>string Currency<\/code><\/li>\n<li><code>decimal X\/Y<\/code> and\/or <code>Width\/Height<\/code><\/li>\n<\/ul>\n<p>This is the case for the <a href=\"https:\/\/martinfowler.com\/bliki\/ValueObject.html\"><strong>ValueObject<\/strong><\/a>:<\/p>\n<blockquote>\n<p><em>A small simple object, like money or a date<\/em><br \/><em>range, whose equality isn\u2019t based on identity.<\/em><br \/> \u2014 Martin Fowler<\/p>\n<\/blockquote>\n","protected":false},"author":1,"featured_media":2060,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[27],"tags":[10],"class_list":["post-1550","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-design","tag-war-story"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>DateStart + DateEnd - Itenium<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DateStart + DateEnd - Itenium\" \/>\n<meta property=\"og:description\" content=\"ValueObjectsA ramble against objects containing DateStart &amp; DateEnd pairs of properties.Some of their equally evil relatives:DateStart &amp; TimeSpan or Day\/Month only in DateTime, etc.decimal Money &amp; string Currencydecimal X\/Y and\/or Width\/HeightThis is the case for the ValueObject:A small simple object, like money or a daterange, whose equality isn\u2019t based on identity. \u2014 Martin Fowler\" \/>\n<meta property=\"og:url\" content=\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/\" \/>\n<meta property=\"og:site_name\" content=\"Itenium\" \/>\n<meta property=\"article:published_time\" content=\"2019-06-18T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-28T12:31:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"360\" \/>\n\t<meta property=\"og:image:height\" content=\"300\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Usdevelop\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Usdevelop\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/\",\"name\":\"DateStart + DateEnd - Itenium\",\"isPartOf\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg\",\"datePublished\":\"2019-06-18T22:00:00+00:00\",\"dateModified\":\"2025-11-28T12:31:44+00:00\",\"author\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022\"},\"breadcrumb\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg\",\"contentUrl\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg\",\"width\":360,\"height\":300},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/demo.sidekick.be\/itenium\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DateStart + DateEnd\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#website\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/\",\"name\":\"Itenium\",\"description\":\"We build software. We build careers.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/demo.sidekick.be\/itenium\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022\",\"name\":\"Usdevelop\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g\",\"caption\":\"Usdevelop\"},\"sameAs\":[\"https:\/\/demo.sidekick.be\/itenium\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"DateStart + DateEnd - Itenium","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"en_US","og_type":"article","og_title":"DateStart + DateEnd - Itenium","og_description":"ValueObjectsA ramble against objects containing DateStart &amp; DateEnd pairs of properties.Some of their equally evil relatives:DateStart &amp; TimeSpan or Day\/Month only in DateTime, etc.decimal Money &amp; string Currencydecimal X\/Y and\/or Width\/HeightThis is the case for the ValueObject:A small simple object, like money or a daterange, whose equality isn\u2019t based on identity. \u2014 Martin Fowler","og_url":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/","og_site_name":"Itenium","article_published_time":"2019-06-18T22:00:00+00:00","article_modified_time":"2025-11-28T12:31:44+00:00","og_image":[{"width":360,"height":300,"url":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg","type":"image\/jpeg"}],"author":"Usdevelop","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Usdevelop","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/","url":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/","name":"DateStart + DateEnd - Itenium","isPartOf":{"@id":"https:\/\/demo.sidekick.be\/itenium\/#website"},"primaryImageOfPage":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage"},"image":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage"},"thumbnailUrl":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg","datePublished":"2019-06-18T22:00:00+00:00","dateModified":"2025-11-28T12:31:44+00:00","author":{"@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022"},"breadcrumb":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#primaryimage","url":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg","contentUrl":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/valueobjects.jpg","width":360,"height":300},{"@type":"BreadcrumbList","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/datestart-and-dateend\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/demo.sidekick.be\/itenium\/"},{"@type":"ListItem","position":2,"name":"DateStart + DateEnd"}]},{"@type":"WebSite","@id":"https:\/\/demo.sidekick.be\/itenium\/#website","url":"https:\/\/demo.sidekick.be\/itenium\/","name":"Itenium","description":"We build software. We build careers.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/demo.sidekick.be\/itenium\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022","name":"Usdevelop","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g","caption":"Usdevelop"},"sameAs":["https:\/\/demo.sidekick.be\/itenium"]}]}},"_links":{"self":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/comments?post=1550"}],"version-history":[{"count":3,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1550\/revisions"}],"predecessor-version":[{"id":2289,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1550\/revisions\/2289"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/media\/2060"}],"wp:attachment":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/media?parent=1550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/categories?post=1550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/tags?post=1550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}