1![Kodi Logo](resources/banner_slim.png) 2 3# HOW-TO: Clean Up Logic 4Guide originally published at **[PR13717](https://github.com/xbmc/xbmc/pull/13717)**. To better understand this document, you should read the original *Pull Request*. 5 6## Table of Contents 71. **[Why clean logic is important](#1-why-clean-logic-is-important)** 82. **[What bad `if` and ternary (`? :`) statements look like](#2-what-bad-if-and-ternary-statements-look-like)** 93. **[How to clean up OR's](#3-how-to-clean-up-ors)** 104. **[How to clean up AND's](#4-how-to-clean-up-ands)** 115. **[How to clean up ternary (`? :`) statements](#5-how-to-clean-up-ternary-statements)** 126. **[Extra credit: the `switch` statement](#6-extra-credit-the-switch-statement)** 137. **[Choosing AND vs. OR](#7-choosing-and-vs-or)** 14 15## 1. Why clean logic is important 16 17It's all about readability. We should strive to write code for people, not computers. `if` statements impact the control flow. We want the control flow to be as easy to read and follow as possible. 18 19**[back to top](#table-of-contents)** 20 21## 2. What bad if and ternary statements look like 22 23Take the **[first commit](https://github.com/xbmc/xbmc/commit/2d85c66~6)**. The previous logic roughly translates to: 24 25```c++ 26if (A || B || (C &&D) || ((E || (F && G)) && (H && I && J && K)) || L) 27 something(); 28``` 29 30Wow. 31 32Ternary logic can also be unwieldy. For example, the previous logic in the second commit translates to: 33 34```c++ 35X = (A && !B) ? Y : Z; 36``` 37 38This statement isn't as offensive, but wouldn't it be more readable and maintainable by using a few more lines? 39 40**[back to top](#table-of-contents)** 41 42## 3. How to clean up OR's 43 44Generally, OR's are separated by creating a *sequence* of `if`'s on new lines with the same indentation. An initial flag is set, and the `if` statements are used to flip the flag. We can then use a final `if` that only depends on a single flag. 45 46For example: 47 48```c++ 49if (A || B) 50 something() 51``` 52 53becomes: 54 55```c++ 56bool flag = false; 57 58if (A) 59 flag = true; 60else if (B) 61 flag = true; 62 63if (flag) 64 something(); 65``` 66 67This is demonstrated in the commit **[Improve logic for GUI_MSG_QUEUE_NEXT_ITEM in CApplication::OnMessage()](https://github.com/xbmc/xbmc/commit/2d85c66~2)**. 68 69**[back to top](#table-of-contents)** 70 71## 4. How to clean up AND's 72 73Generally, AND's are separated by creating a *series* of `if`'s by embedding indented blocks. 74 75For example: 76 77```c++ 78if (A && B) 79 something() 80``` 81 82becomes: 83 84```c++ 85if (A) 86{ 87 if (B) 88 something(); 89} 90``` 91 92This is demonstrated in the commit **[Improve logic in CAutorun::ExecuteAutorun()](https://github.com/xbmc/xbmc/commit/2d85c66~1)**. 93 94**[back to top](#table-of-contents)** 95 96## 5. How to clean up ternary statements 97 98As the name suggests, ternary statements can be split into three lines. For example, 99 100```c++ 101X = (A && !B) ? Y : Z; 102``` 103 104becomes: 105 106```c++ 107X = Y; 108if (!A || B) 109 X = Z; 110``` 111 112This is demonstrated in the commit **[Improve sleep time logic in CApplication::FrameMove()](https://github.com/xbmc/xbmc/commit/2d85c66~5)**. 113 114**[back to top](#table-of-contents)** 115 116## 6. Extra credit: the `switch` statement 117 118As a bonus, if the logic compares the same value to multiple constants, you can use a `switch` statement for a small performance boost. 119 120For example (notice how I add a tricky OR at the end): 121 122```c++ 123if (x == A || x == B || x == C || y == D) 124 something(); 125``` 126 127becomes: 128 129``` 130bool flag = false; 131 132switch (x) 133{ 134case A: 135case B: 136case C: 137 flag = true; 138 break; 139default: 140 if (y == D) 141 flag = true; 142 break; 143} 144 145if (flag) 146 something(); 147``` 148 149This is demonstrated in the commit **[Clean up player notification logic in CApplication::OnAction()](https://github.com/xbmc/xbmc/commit/2d85c66~6)**. 150 151Switch statements use *jump tables*, which can be faster than `if`s in some cases because branching slows down speculative execution. 152 153**[back to top](#table-of-contents)** 154 155## 7. Choosing AND vs. OR 156 157In general, I prefer the flag approach (OR) over the embedding indented blocks approach (AND) because less indentation makes the control flow easier to follow. Boolean algebra can be used to convert AND statements into ORs. 158 159However, when a bunch of ANDs and ORs are combined, sometimes it makes things more complicated to use a single OR operator. It's really a process of trying different algebraic combinations to get the simplest-to-read control flow. 160 161The last commit shows how I was given a convoluted condition and played around with boolean algebra until I eventually settled on what I considered most readable, **[Improve logic in CGraphicContext::SetFullScreenVideo()](https://github.com/xbmc/xbmc/commit/2d85c66)**. 162 163**[back to top](#table-of-contents)** 164 165