{"id":2006,"date":"2019-03-25T12:44:55","date_gmt":"2019-03-25T12:44:55","guid":{"rendered":"http:\/\/dlang.org\/blog\/?p=2006"},"modified":"2021-09-30T13:40:01","modified_gmt":"2021-09-30T13:40:01","slug":"using-const-to-enforce-design-decisions","status":"publish","type":"post","link":"https:\/\/dlang.org\/blog\/2019\/03\/25\/using-const-to-enforce-design-decisions\/","title":{"rendered":"Using const to Enforce Design Decisions"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"alignleft size-full wp-image-180\" src=\"http:\/\/dlang.org\/blog\/wp-content\/uploads\/2016\/08\/d3.png\" alt=\"\" width=\"160\" height=\"301\" srcset=\"https:\/\/dlang.org\/blog\/wp-content\/uploads\/2016\/08\/d3.png 160w, https:\/\/dlang.org\/blog\/wp-content\/uploads\/2016\/08\/d3-159x300.png 159w\" sizes=\"(max-width: 160px) 100vw, 160px\" \/><\/p>\n<p>The saying goes that the best code is no code. As soon as a project starts to grow, technical debt is introduced. When a team is forced to adapt to a new company guideline inconsistent with their previous vision, the debt results from a business decision. This could be tackled at the company level. Sometimes technical debt can arise simply due to the passage of time, when new versions of dependencies or of the compiler introduce breaking changes. You can try to tackle this by letting your local physicist stop the flow of time. More often however, technical debt is caused when issues are fixed by a quick hack, due to time pressure or a lack of knowledge of the code base. Design strategies that were carefully crafted are temporarily neglected. This blog post will focus on using the <code>const<\/code> modifier. It is one of the convenient tools D offers to minimize the increase of technical debt and enforce design decisions.<\/p>\n<p>To keep a code base consistent, often design guidelines, either explicit or implicit, are put in place. Every developer on the team is expected to adhere to the guidelines as a gentleman\u2019s agreement. This effectively results in a policy that is only enforced if both the programmer and the reviewer have had enough coffee. Simple changes, like adding a call to an object method, might seem innocent, but can reduce the consistency and the traceability of errors. To detect this in a code review requires in-depth knowledge of the method\u2019s implementation.<\/p>\n<p>An example from a real world project I\u2019ve worked on is generating financial transactions for a read-only view, the <code>display<\/code> function in the following code fragment. Nothing seemed wrong with it, until I realized that those transactions were persisted and eventually used for actual payments <em>without being calculated again<\/em>, as seen in the <code>process<\/code> method. Potentially different payments occurred depending on whether the user decided to glance at the summary, thereby triggering the generation with new currency exchange rates, or just blindly clicked the OK button. That\u2019s not what an innocent bystander like myself expects and has caused many frowns already.<\/p>\n<pre class=\"prettyprint lang-d\">public class Order\r\n{\r\n    private Transaction[] _transactions;\r\n\r\n    public Transaction[] getTransactions()\r\n    {\r\n        _transactions = calculate();\r\n        return _transactions;\r\n    }\r\n\r\n    public void process()\r\n    {\r\n        foreach(t; _transactions){\r\n            \/\/ ...\r\n        }\r\n    }\r\n}\r\n\r\nvoid display(Order order)\r\n{\r\n    auto t = order.getTransactions();\r\n    show(t);\r\n}<\/pre>\n<p>The internet has taught me that if it is possible, it will one day happen. Therefore, we should make an attempt to make the undesired impossible.<\/p>\n<h2 id=\"aconstantfeature\">A constant feature<\/h2>\n<p>By default, variables and object instances in D are mutable, just like in many other programming languages. If we want to prevent objects from ever changing, we can mark them <code>immutable<\/code>, i.e. <code>immutable MyClass obj = new MyClass();<\/code>. <code>immutable<\/code> means that we can modify neither the object reference (<em>head constant<\/em>) nor the object\u2019s properties (<em>tail constant<\/em>). The first case corresponds to <code>final<\/code> in Java and <code>readonly<\/code> in C#, both of which signify head constant only. D\u2019s implementation means that nobody can ever modify an object marked <code>immutable<\/code>. What if an object needs to be mutable in one place, but immutable in another? <a href=\"https:\/\/dlang.org\/spec\/const3.html#const_and_immutable\">That\u2019s where D\u2019s <code>const<\/code><\/a> pops in.<\/p>\n<p>Unlike <code>immutable<\/code>, whose contract states that an object cannot be mutated through any reference, <code>const<\/code> allows an object to be modified through another, non-<code>const<\/code> reference. This means it\u2019s illegal to initialize an <code>immutable<\/code> reference with a mutable one, but a <code>const<\/code> reference can be initialized with a mutable, <code>const<\/code>, or <code>immutable<\/code> reference. In a function parameter list, <code>const<\/code> is preferred over <code>immutable<\/code> because it can accept arguments with either qualifier or none. Schematically, it can be visualized as in the following figure.<\/p>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-2010\" src=\"http:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image2.png\" alt=\"const relationships\" width=\"336\" height=\"243\" srcset=\"https:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image2.png 336w, https:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image2-300x217.png 300w\" sizes=\"(max-width: 336px) 100vw, 336px\" \/><\/p>\n<h2 id=\"aconstantdetour\">A constant detour<\/h2>\n<p>D\u2019s <code>const<\/code> differs from C++ <code>const<\/code> in a significant way: it\u2019s transitive (see <a href=\"https:\/\/dlang.org\/articles\/const-faq.html\">the const(FAQ)<\/a> for more details). In other words, it\u2019s not possible to declare any object in D as head constant. This isn\u2019t obvious from examples with classes, since classes in D are reference types, but is more apparent with pointers and arrays. Consider these C++ declarations:<\/p>\n<pre class=\"prettyprint lang-c_cpp\">const int *cp0;         \/\/ mutable pointer to const data\r\nint const *cp1;         \/\/ alternative syntax for the same<\/pre>\n<p>Variable declarations in C++ are best read from right to left. Although <code>const int<\/code> is likely the more common syntax, <code>int const<\/code> matches the way the declaration should be read: <em>cp0 is a mutable pointer to a const int<\/em>. In D, the equivalent of <code>cp0<\/code> and <code>cp1<\/code> is:<\/p>\n<pre class=\"prettyprint lang-d\">const(int)* dp0;<\/pre>\n<p>The next example shows what head constant looks like in C++.<\/p>\n<pre class=\"prettyprint lang-c_cpp\">int *const cp2;         \/\/ const pointer to mutable data<\/pre>\n<p>We can read the declaration of <code>cp2<\/code> as: <em>cp2 is a const pointer to a mutable int<\/em>. There is no equivalent in D. It\u2019s possible in C++ to have any number and combination of <code>const<\/code> and mutable pointers to <code>const<\/code> or mutable data. But in D, if <code>const<\/code> is applied to the outermost pointer, then it applies to all the inner pointers and the data as well. Or, as they say, it\u2019s turtles all the way down.<\/p>\n<p>The equivalent in C++ looks like this:<\/p>\n<pre class=\"prettyprint lang-c_cpp\">int const *const cp3;         \/\/ const pointer to const data<\/pre>\n<p>This declaration says <em>cp3 is a const pointer to const data<\/em>, and is possible in D like so:<\/p>\n<pre class=\"prettyprint lang-d\">const(int*) dp1;\r\nconst int* dp2;     \/\/ same as dp1<\/pre>\n<p>All of the above syntax holds true for D arrays:<\/p>\n<pre class=\"prettyprint lang-d\">const(int)[] a1;    \/\/ mutable reference to const data\r\nconst(int[]) a2;    \/\/ const reference to const data\r\nconst int[] a3;     \/\/ same as a2<\/pre>\n<p><code>const<\/code> in the examples can be replaced with <code>immutable<\/code>, with the caveat that initializers must match the declaration, e.g. <code>immutable(int)*<\/code> can only be initialized with <code>immutable(int)*<\/code>.<\/p>\n<p>Finally, note that classes in D are reference types; the reference is baked in, so applying <code>const<\/code> or <code>immutable<\/code> to a class reference is always equivalent to <code>const(p*)<\/code> and there is no equivalent to <code>const(p)*<\/code> for classes. Structs in D, on the other hand, are value types, so pointers to structs can be declared like the <code>int<\/code> pointers in the examples above.<\/p>\n<h2 id=\"aconstantexample\">A constant example<\/h2>\n<p>For the sake of argument, we assume that updating the currency exchange rates is a function that, by definition, needs to mutate the order. After updating the order, we want to show the updated prices to our user. Conceptually, the display function should not modify the order. We can prevent mutation by adding the <code>const<\/code> modifier to our function parameter. The implicit rule is now made explicit: the function takes an <code>Order<\/code> as input, and treats the object as a constant. We no longer have a gentleman\u2019s agreement, but a formal contract. Changing the contract will, hopefully, require thorough negotiation with your peer reviewer.<\/p>\n<pre class=\"prettyprint lang-d\">void updateExchangeRates(Order order);\r\nvoid display(const Order order);\r\n\r\nvoid updateAndDisplay()\r\n{\r\n    Order order = \/\/\u2026\r\n    updateExchangeRates(order);\r\n    display(order); \/\/ Implicitly converted to const.\r\n}<\/pre>\n<p>As with all contracts, defining it is the easiest part. The hard part is enforcing it. The D compiler is our friend in this problem. If we try to compile the code, we will get a compiler error.<\/p>\n<pre class=\"prettyprint lang-d\">void display(const Order order)\r\n{\r\n    \/\/ ERROR: cannot call mutable method\r\n    auto t = order.getTransactions();\r\n    show(t);\r\n}<\/pre>\n<p>We never explicitly stated that <code>getTransactions<\/code> doesn\u2019t modify the object. As the method is virtual by default, the compiler cannot derive the behavior either way. Without that knowledge, the compiler is required to assume that the method might modify the object. In other words, in the D justice system one is guilty until proven innocent. Let\u2019s prove our innocence by marking the method itself <code>const<\/code>, telling the compiler that we do not intend to modify our data.<\/p>\n<pre class=\"prettyprint lang-d\">public class Order\r\n{\r\n    private Transaction[] _transactions;\r\n\r\n    public Transaction[] getTransactions() const\r\n    {\r\n        _transactions = calculate(); \/\/ ERROR: cannot mutate field\r\n        return _transactions;\r\n    }\r\n}\r\n\r\nvoid display(const Order order)\r\n{\r\n    auto t = order.getTransactions(); \/\/ Now compiles :)\r\n    show(t);\r\n}<\/pre>\n<p>By marking the method <code>const<\/code>, the original compile error has moved away. The promise that we do not modify any object state is part of the method signature. The compiler is now satisfied with the method call in the <code>display<\/code> function, but finds another problem. Our getter, which we stated should not modify data, actually does modify it. We found our code smell by formalizing our guidelines and letting the compiler figure out the rest.<\/p>\n<p>It seems promising enough to try it on a real project.<\/p>\n<h2 id=\"aconstantapplication\">A constant application<\/h2>\n<p>I had a pet project lying around and decided to put the effort into enforcing the constraint. This is what inspired me to write this post. The project is <a href=\"https:\/\/github.com\/Zevenberge\/Mahjong\">a four-player mahjong game<\/a>. The relevant part, in abstraction, is highlighted in the image.<\/p>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-2009\" src=\"http:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image1.png\" alt=\"Mahjong abstraction\" width=\"422\" height=\"422\" srcset=\"https:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image1.png 422w, https:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image1-200x200.png 200w, https:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/03\/image1-300x300.png 300w\" sizes=\"(max-width: 422px) 100vw, 422px\" \/><\/p>\n<p>The main engine behind the game is the white box in the center. A player or AI is sent a message with a <code>const<\/code> view of the game data for display purposes and to determine their next move. A message is sent back to the engine, which then determines the mutation on the internally mutable game data. The most obvious win is that I cannot accidentally modify the game data when drawing my UI. Which, of course, appeared to be the case before I refactored in the <code>const<\/code>-ness of the game data.<\/p>\n<p>Upon closer inspection, coming from the UI there is only one way to manipulate the state of the game. The UI sends a message to the engine and remains oblivious of the state changes that need to be applied. This also encourages layered development and improves testability of the code. So far, so good. But during the refactoring, a problem arose. Recall that marking an object with <code>const<\/code> means that only member functions that promise not to modify the object, those marked with <code>const<\/code> themselves, can be called. Some of these could be trivially fixed by applying <code>const<\/code> or, at worst, <code>inout<\/code> (<a href=\"https:\/\/dlang.org\/spec\/function.html#inout-functions\">a sort of wildcard<\/a>). However, the more persistent issues, like in the <code>Order<\/code> example, required me to go back to the drawing board and rethink my domain. In the end, being forced to think about mutability versus immutability improved my understanding of my own code base.<\/p>\n<h2 id=\"aconstantverdict\">A constant verdict<\/h2>\n<p>Is <code>const<\/code> all good? It\u2019s not a universal answer and certainly has downsides. The most notable one is that this kills lazy initialization where a property is computed only when first requested and then the result is cached. Sometimes, like in the earlier example, this is a code smell, but there are legit use cases. In my game, I have a class that composes the dashboard per player. Updating it is expensive and rarely required. The screen, however, gets rendered sixty times a second. It makes sense to cache the dashboards and only update them when the player objects change. I could split the method in two, but then my abstraction would leak its optimization. I settled for not using <code>const<\/code> here, as it was a module-private class and didn\u2019t have a large impact on my codebase.<\/p>\n<p>A complaint that is sometimes heard regarding <code>const<\/code> is that it does not work well with one of D\u2019s main selling points, ranges. A range is D\u2019s implementation of a lazy iterator, usable in <code>foreach<\/code> loops and heavily used in <code>std.algorithm<\/code>. The functions in <code>std.algorithm<\/code> can handle ranges with <code>const<\/code> elements perfectly fine. However, iterating a range changes the internal values and ultimately consumes the range. Therefore, when a range itself is <code>const<\/code>, it cannot be iterated over. I think this makes sense by design, but I can imagine that this behavior can be surprising in edge cases. I haven\u2019t encountered this as I generate new ranges on every query, both on mutable and <code>const<\/code> objects.<\/p>\n<p>A guideline for when to use <code>const<\/code> would be to separate the queries from the command, a.k.a. ye olde <a href=\"https:\/\/en.wikipedia.org\/wiki\/Command%E2%80%93query_separation\">Command-Query Separation (CQS)<\/a>. All queries should, in principle, be <code>const<\/code>. To perform a mutation, even on nested objects, one should call a method on the object. I\u2019d double down on this and state that member functions should be commands, with logic that can be overridden, and therefore never be marked constant. Queries basically serve as a means to peek at encapsulated data and don\u2019t need to be overridden. This should be a <code>final<\/code>, non-virtual, function that simply exposes a read-only view on the inner field. For example, using D\u2019s module-private modifier on the field in conjunction with an acquainted function in the same module, we can put the logic inside the class definition and the queries outside.<\/p>\n<pre class=\"prettyprint lang-d\">\/\/ in order.d\r\npublic class Order\r\n{\r\n    private Transaction[] _transactions; \/\/ Accessible in order.d\r\n\r\n    public void process(); \/\/ Virtual and not restricted\r\n}\r\n\r\npublic const(Transaction)[] getTransactions(const Order order)\r\n{\r\n    \/\/ Function, not virtual, operates on a read-only view of Order\r\n    return order._transactions;\r\n}\r\n\r\n\/\/ in view.d\r\nvoid display(const Order order)\r\n{\r\n    auto t = order.getTransactions();\r\n    show(t);\r\n}<\/pre>\n<p>We should take care, however, not to overapply the modifier. The question that we need to answer is not \u201cDo I modify this object here?\u201d, but rather, \u201cDoes it make sense that the object is modified here?\u201d Wrongly assuming constant objects will result in trouble when you finally need to change the instance due to a new feature. For example, in my game a central <code>Game<\/code> class contains the players\u2019 hands, but doesn\u2019t explicitly modify them. However, given the structure of my code, it does not make sense to make the player objects constant, as free functions in the engine do use mutable player instances of the game object.<\/p>\n<p>Reflecting on my design, even when writing this blog post, gave me valuable insights. Taking the effort to properly use the tool called <code>const<\/code> has paid off for me. It improved the structure of my code and improved my understanding of the ramblings I write. It is like any other tool not a silver bullet. It serves to formalize our gentleman\u2019s agreement and is therefore just as fragile as one.<\/p>\n<hr \/>\n<p><em>Marco graduated in physics, were he used Fortran and Matlab. He used <a href=\"http:\/\/ddili.org\/ders\/d.en\/index.html\">Programming in D<\/a> to learn application programming. After 3 years of being a C# developer, he is now trainer-coach of mainly Java and C# <a href=\"https:\/\/www.sogyo.nl\">developers at Sogyo<\/a>. Marco uses D for programming experiments and side projects including his darling mahjong game.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The saying goes that the best code is no code. As soon as a project starts to grow, technical debt is introduced. When a team is forced to adapt to a new company guideline inconsistent with their previous vision, the debt results from a business decision. This could be tackled at the company level. Sometimes [&hellip;]<\/p>\n","protected":false},"author":33,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[26,9,20],"tags":[],"_links":{"self":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/2006"}],"collection":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/comments?post=2006"}],"version-history":[{"count":7,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/2006\/revisions"}],"predecessor-version":[{"id":2008,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/2006\/revisions\/2008"}],"wp:attachment":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/media?parent=2006"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/categories?post=2006"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/tags?post=2006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}