<div dir="auto">Hello Amber Dev Team,<div dir="auto"><br></div><div dir="auto">I just wanted to share an experiment that I ran a long while back that made refactoring sort of painful for me today.</div><div dir="auto"><br></div><div dir="auto">I have a sealed interface called Cell.java, which has a deep inheritance graph below it, all made up of datatypes that are very amenable for edge-case checking via exhaustiveness checking. Aka, enums, sealed interfaces, and records. And for records, I used LOTS of record patterns, to extract and use the attributes I needed exhaustively.</div><div dir="auto"><br></div><div dir="auto">The purpose was becase I was implementing a Path-Finding Algorithm, and I needed to know what type of cells were in front of me in order to decide the cost of going down a certain path (ex. walking on spikes uses up more stamina then empty flooring). Basically, checking the current cell, and the 2 in front of me.</div><div dir="auto"><br></div><div dir="auto">Originally, I implemented edge-case checking via a nested set of switch expressions, all feeding into 1 final variable as the output. Using this, I would check the data types of my current cell and the 2 in front of me, to cover all possible combinations of Cell instances.</div><div dir="auto"><br></div><div dir="auto">While this worked well enough, there were 2 problems with it.</div><div dir="auto"><br></div><div dir="auto">1 - The verticality of it made it a little difficult to keep track of what exactly I was checking at any given point in time. Sometimes, I would accidentally skip over c2, for example, because I would be 5 levels deep in a switch, checking the 3rd record attribute on c1, and then accidentally skip c2 and just jump to c3. </div><div dir="auto"><br></div><div dir="auto">2 - There were a lot of keywords getting in the way of the logic, making it harder to read.</div><div dir="auto"><br></div><div dir="auto">So, I thought to myself -- why don't I just flatten this hierarchy down to a single switch expression? Patterns compose, after all.</div><div dir="auto"><br></div><div dir="auto">What I did was make a local record Triple(Cell c1, Cell c2, Cell c3){}, then fed that into a single Switch Expression, then checked all that I needed to using Record Patterns.</div><div dir="auto"><br></div><div dir="auto">This definitely solved both of my problems. For 1, I used whitespace to vertically align all of the record patterns for c1, c2, and c3. That made it impossible for me to miss a Cell. And for 2, having a single case contain nothing but record patterns meant that all of the fluff was out of the way. Only the logic in front of me.</div><div dir="auto"><br></div><div dir="auto">However, I exchanged 2 problems for 1.</div><div dir="auto"><br></div><div dir="auto">A few days ago, I needed to do some refactoring to add a new feature to the game. That meant adding 2 new data types (at different levels of my hierarchy) to my Cell.</div><div dir="auto"><br></div><div dir="auto">Well, when I did so, and pressed compile, I got the error message that I was missing a case on my switch expression. Perfect, that's what I love about Exhaustiveness Checking. The compiler becomes a "pit of success" of sorts, where you press compile, and all the missing cases become highlighted.</div><div dir="auto"><br></div><div dir="auto">Except, that's not really what happened. All the error message told me was that this switch was not exhaustive. Nothing about what I might be missing, or an example of a possible, unaccounted for case.</div><div dir="auto"><br></div><div dir="auto">I started searching and making changes where I thought be missing cases, and found that it was actually super difficult to find all of the missing spots. It took me almost 20-30 minutes just to see what I was missing.</div><div dir="auto"><br></div><div dir="auto">Back when I had nested Switch Expressions, finding the error case was trivial. Yes, it was the exact same error message, but since each Switch Expression was so small and self-contained, no real digging had to occur to figure out what case I was missing.</div><div dir="auto"><br></div><div dir="auto">And that's when I realized my tradeoff -- flattening my switch expressions meant that I had sacrificed traceability for readability. Finding my error got much harder, now that I had made my code much more readable.</div><div dir="auto"><br></div><div dir="auto">This was a bit frustrating to me, as I felt like I was forced to pick between 2 unideal situations.</div><div dir="auto"><br></div><div dir="auto">Anyways, readability is important to me, but traceability is even moreso, so I will go back to nested Switch Expressions. I just wanted to announce my experience, in case it helps.</div><div dir="auto"><br></div><div dir="auto">Thank you for your time and attention!</div><div dir="auto">David Alayachew</div></div>