{"id":461,"date":"2016-01-24T21:32:37","date_gmt":"2016-01-24T20:32:37","guid":{"rendered":"http:\/\/joost.vunderink.net\/blog\/?p=461"},"modified":"2016-01-24T21:32:37","modified_gmt":"2016-01-24T20:32:37","slug":"expiring-temporary-information","status":"publish","type":"post","link":"https:\/\/joost.vunderink.net\/blog\/2016\/01\/24\/expiring-temporary-information\/","title":{"rendered":"Expiring temporary information"},"content":{"rendered":"<p>Imagine you are a developer, working on a backend system with reservations. A new requirement comes up: if a reservation is not paid within 24 hours, it needs to be expired.<\/p>\n<p>Your reservation table already has a field <span class=\"lang:default decode:true crayon-inline \">creationDate<\/span>\u00a0. So all you need to do, is to create a periodic job that looks at all active and unpaid reservations, that were created more than 24 hours ago, and set their status to <span class=\"lang:default decode:true crayon-inline \">expired<\/span>\u00a0.<\/p>\n<p>Simple, right? You feel a bit queasy about using the <span class=\"lang:default decode:true  crayon-inline \">creationDate<\/span>\u00a0 field in this manner, but decide to go for it anyway.<\/p>\n<p>A few weeks later, someone from customer support comes to you. &#8220;<em>We have this reservation that has expired. But we really want to give the customer the option to pay, even though he was too late. Could\u00a0you un-expire it?<\/em>&#8221;<\/p>\n<p>It seemed pretty important, so you change the <span class=\"lang:default decode:true crayon-inline\">creationDate<\/span>\u00a0 value of this reservation. Yes, this will screw up the statistics, but who&#8217;ll notice that? Let&#8217;s hope this won&#8217;t happen too often.<\/p>\n<p>Some time later, you receive a feature request. &#8220;<em>Is it possible for all reservations made by premium users to have an expiry time of 48 hours instead of 24?<\/em>&#8221;<\/p>\n<p>Sure, no problem. You expand your expiry code. Instead of only looking in the <span class=\"lang:default decode:true crayon-inline \">reservation<\/span>\u00a0 table, you <span class=\"lang:default decode:true crayon-inline \">JOIN<\/span>\u00a0 the <span class=\"lang:default decode:true crayon-inline \">users<\/span>\u00a0 table to check whether a user is a premium user. This does work, but it has a small bug in it: the user&#8217;s premium status should actually be checked when the reservation was created, not when it&#8217;s being expired.<\/p>\n<p>So you ponder whether you should add a history log to the user&#8217;s premium status, but in the end you and the business decide to accept this small defect instead of spending time on fixing it.<\/p>\n<p>The next feature request arrives. &#8220;<em>Could we have a way to increase the expiry time for individual reservations via the reservation overview page?<\/em>&#8221;<\/p>\n<p>Hmm, tricky. You tell them that it&#8217;s possible but it will screw up the creation statistics. They accept it, and you program it.<\/p>\n<p>And another one. &#8220;<em>We are A\/B testing our reservation site. Can we change the expiry time to 6 hours for reservations created on the B version of the website?<\/em>&#8221;<\/p>\n<p>This one has you puzzled. How can you\u00a0do this? The reservation in the database\u00a0is not aware of any A\/B testing going on in the website, and neither is the expiry script.<\/p>\n<p>So you consider adding metadata to the reservation to keep track how it was created. Based on that, the expiry script can calculate what the exact expiry time needs to be. So for a reservation by a premium user on the B version of the website, should that be 6 hours or 48 or maybe 1\/4th of 48&#8230;<\/p>\n<div id=\"attachment_465\" style=\"width: 302px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/joost.vunderink.net\/blog\/wp-content\/uploads\/2016\/01\/lightbulb-with-idea-concept-icon.jpg\" rel=\"attachment wp-att-465\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-465\" class=\"size-medium wp-image-465\" src=\"http:\/\/joost.vunderink.net\/blog\/wp-content\/uploads\/2016\/01\/lightbulb-with-idea-concept-icon-292x300.jpg\" alt=\"Glowing lightbulb, symbolising an idea.\" width=\"292\" height=\"300\" srcset=\"https:\/\/joost.vunderink.net\/blog\/wp-content\/uploads\/2016\/01\/lightbulb-with-idea-concept-icon-292x300.jpg 292w, https:\/\/joost.vunderink.net\/blog\/wp-content\/uploads\/2016\/01\/lightbulb-with-idea-concept-icon.jpg 413w\" sizes=\"(max-width: 292px) 100vw, 292px\" \/><\/a><p id=\"caption-attachment-465\" class=\"wp-caption-text\">Suddenly, everything becomes clear.<\/p><\/div>\n<p>&#8230; and suddenly you realise that it&#8217;s actually much smarter to <strong>store the expiration time in the reservation <\/strong>and also to<strong> add an &#8220;expiry time&#8221; argument to the API call that creates the reservation<\/strong>.<\/p>\n<p>After all,\u00a0whatever system creates the reservation in the backend knows exactly in which circumstances the reservation is being created, and thus can decide what the expiration time needs to be. Thinking about this a bit more, you realise that this solves all previous feature requests as well.<\/p>\n<p>At least, you have learned a few valuable lessons from this experience.<\/p>\n<ol>\n<li>It&#8217;s really hard to predict the future.<\/li>\n<li>Trust your queasy feelings. They are there for a reason.<\/li>\n<li>Don&#8217;t put too much meaning in a single field. You will regret it later on.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Imagine you are a developer, working on a backend system with reservations. A new requirement comes up: if a reservation is not paid within 24 hours, it needs to be expired. Your reservation table already has a field creationDate\u00a0. So &hellip; <a href=\"https:\/\/joost.vunderink.net\/blog\/2016\/01\/24\/expiring-temporary-information\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[254,10],"tags":[259,258,256,257,255],"class_list":["post-461","post","type-post","status-publish","format-standard","hentry","category-design","category-software-development","tag-expiration","tag-expiry","tag-gut-feeling","tag-queasy-feeling","tag-software-design"],"_links":{"self":[{"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/posts\/461"}],"collection":[{"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":4,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"predecessor-version":[{"id":466,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/posts\/461\/revisions\/466"}],"wp:attachment":[{"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joost.vunderink.net\/blog\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}