Infinite code smells! \ We see several symptoms and situations that make us doubt the quality of our development. Let's look at some possible solutions. \ Most of these smells are just hints of something that might be wrong. They are not rigid rules. ## Previous Code Smells * [Part I](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd) * [Part II](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ii-o96s3wl4) * [Part III](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iii-t7h3zkv) * [Part IV](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iv-7sc3w8n) * [Part V](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-v-evj3zs9) * [Part VI](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-vi-cmj31om) * [Part VII](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-vii-8dk31x0) * [Part VIII](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-viii-8mn3352) * [Part IX](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ix-7rr33ol) * [Part X](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-x-i7r34uj) * [Part XI](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xi-sit35t1) * [Part XII](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xii) * [Part XIII](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii) * [Part XIV](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv) \ Let's continue... --- # Code Smell 71 - Magic Floats Disguised as Decimals \ > TL;DR Don't trust numbers on immature languages like JavaScript. \  ## Problems * [Principle of Least Surprise](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) Violation * [Accidental Complexity](https://hackernoon.com/there-are-no-silver-bullets-for-this-werewolf-2t213woi) * Wrong decimal representations. ## Solutions 1. Choose Mature Languages. 2. Represent [Decimals with Decimals](https://hackernoon.com/the-one-and-only-software-design-principle-1x983ylp). ## Sample Code ### Wrong ```javascript console.log(0.2 + 0.1) // 0.30000000000000004 //We are adding two decimal numbers // 2/10 + 1/10 // Result should be 3/10 as we learnt at school ``` \ ### Right ```javascript class Decimal { constructor(numerator) { this.numerator = numerator; } plus(anotherDecimal) { return new Decimal(this.numerator + anotherDecimal.numerator); } toString() { return "0." + this.numerator; }} console.log((new Decimal(2).plus(new Decimal(1))).toString()); // 0.3 //We can represent the numbers with a Decimal class (storing only the numerator) //or with a generic Fraction class (storing both the numerator and denominator) ``` ## Detection Since this is a language feature, it is difficult to detect. We can ask our linters to prevent us from manipulating numbers this way. ## Tags * JavaScript * Premature Optimization ## Conclusion My first programming language was [Commodore 64](https://en.wikipedia.org/wiki/Commodore_64)'s basic back in 1985. \ I was very surprised to discover that 1+1+1 was not always 3. Then they introduced integer types. \ JavaScript is 30 years younger, and it has the same immaturity problems. ## More info Here is the technical (and accidental) explanation: <https://blog.pankajtanwar.in/do-you-know-01-02-03-in-javascript-here-is-why> \ Please, don't argue telling this is fine and expected since this is the binary representation. These numbers are decimals, we should represent them as decimals. If you think representing them as floats is a great performance improvement, you are wrong. Premature optimization is the root of all evil. \ [Floating Point Standard - 83 pages](https://en.wikipedia.org/wiki/IEEE_754) ___ > The purpose of computing is insight, not numbers -*Richard Hamming* ___ # Code Smell 72 - Return Codes *APIs, Return codes, C Programming Language, We've all been there.*  \ > TL;DR: Don't return codes to yourself. Raise Exceptions. ## Problems * [IFs](https://hackernoon.com/how-to-get-rid-of-annoying-ifs-forever-zuh3zlo) * Code Polluting * Outdated documentation * Coupling to accidental codes. * Functional logic polluted. ## Solutions 1. Change Ids and return Generic Exceptions. 2. Distinguish Happy Path from Exception Path. ## Sample Code ### Wrong ```javascript function createSomething(arguments) { //Magic Creation success = false; //we failed //We failed to create if (!success) { return { object: null, errorCode: 403, errorDescription: 'We didnt have permddtttttttttission to create...' }; } return { object: createdObject, errorCode: 400, errorDescription: '' }; } var myObject = createSomething('argument'); if (myObject.errorCode != 400) { console.log(myObject.errorCode + ' ' + myObject.errorDescription) } //but myObject does not hold My Object but an implementative //and accidental array //from now on me need to remember this ``` ### Right ```javascript function createSomething(arguments) { //Magic Creation success = false; //we failed //We failed to create if (!success) { throw new Error('We didnt have permission to create...'); } return createdObject; } try { var myObject = createSomething('argument'); //no IFS, just happy path } catch (exception) { //deal with it! console.log(exception.message); } // myObject holds my expected object ``` ## Detection We can teach our linters to find patterns of integer and strings returns coupled with ifs and return checking. ## Tags * Exceptions ## Conclusion * Ids and codes are external identifiers. * They are useful when you need to interact with an external system (for example an API Rest). * We should not use them on our own systems and our own internal APIs. * Create and raise generic exceptions. * Only create specific exceptions if you are ready to handle them, and they have specialized behavior. * Don't create [anemic](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd) Exceptions. * Avoid [immature and premature optimized languages](https://golangdocs.com/errors-exception-handling-in-golang) favoring return codes. ## More info <https://hackernoon.com/how-to-get-rid-of-annoying-ifs-forever-zuh3zlo> <http://nicolecarpenter.github.io/2016/03/15/clean-code-chapter-7-error-handling.html> ___ > Error handling is important, but if it obscures logic, it’s wrong - *Robert Martin* ___ # Code Smell 73 - Exceptions for Expected Cases *Exceptions are handy Gotos and flags. Let's abuse them.* \  \ > TL;DR: Do not use exceptions for flow control. ## Problems * Readability * Principle of least astonishment Violation. ## Solutions 1. Use Exceptions just for unexpected situations. 2. Exceptions handle [contract violations](https://en.wikipedia.org/wiki/Design_by_contract). Read the contract. ## Sample Code ### Wrong ```java try { for (int i = 0;; i++) array[i]++; } catch (ArrayIndexOutOfBoundsException e) {} //Endless loop without end condition ``` ### Right ```java for (int index = 0; index < array.length; index++) array[index]++; //index < array.length breaks execution ``` ## Detection This is a semantic smell. Unless we use machine learning linters it will be very difficult to find the mistakes. ## Tags * Readability ## Conclusion Exceptions are handy, and we should definitively use them instead of returning codes. The boundary between correct usage and wrong usage is blur like so many design principles. ## Relations [Code Smell 72 - Return Codes](https://maximilianocontieri.com/code-smell-72-return-codes) ## More info * [Don't use exceptions for flow control](https://wiki.c2.com/?DontUseExceptionsForFlowControl) * [Java Zone](https://dzone.com/articles/exceptions-as-controlflow-in-java) * [Stack Exchange](https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why) * [Stack Overflow](https://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control) \ ___ > When debugging, novices insert corrective code; experts remove defective code - *Richard Pattis* ___ # Code Smell 74 - Empty Lines *Breaking the code to favor readability asks for refactor.* \  \ > TL;DR Don't add empty lines to your methods. Extract them! ## Problems * Readability * Kiss * Low Reuse ## Solutions 1. Extract Method 2. Refactor 3. Remove unneeded lines. ## Sample Code ### Wrong ```php <? function translateFile() { $this->buildFilename(); $this->readFile(); $this->assertFileContentsAreOk(); //A lot of lines more //Empty space to pause definition $this->translateHiperLinks(); $this->translateMetadata(); $this->translatePlainText(); //Yet Another empty space $this->generateStats(); $this->saveFileContents(); //A lot of more lines } ``` \ ### Right ```php <? function translateFile() { $this->readFileToMemoy(); $this->translateContents(); $this->saveFileContents(); } ``` ## Detection This is a policy smell. Every linter can detect blank lines and warn us. ## Tags * Readability * Long Methods ## Conclusion Empty lines are harmless, but show us an opportunity to break the code into small steps. If you break your code with comments, it is also a code smell asking for a refactor. \ ___ > It’s OK to figure out murder mysteries, but you shouldn’t need to figure out code. You should be able to read it - *Steve McConnell* ___ # Code Smell 75 - Comments Inside a Method *Comments are often a code smell. Inserting them inside a method calls for an urgent refactor.* \  \ > TL;DR Don't add comments inside your methods. Extract them and leave declarative comments just for not obvious design decisions. ## Problems * Readability * Kiss * Low Reuse * Bad Documentation ## Solutions 1. Extract Method 2. Refactor 3. Remove not declarative comments. ## Sample Code ### Wrong ```javascript function recoverFromGrief() { // Denial stage absorbTheBadNews(); setNumbAsProtectiveState(); startToRiseEmotions(); feelSorrow(); // Anger stage maskRealEffects(); directAngerToOtherPeople(); blameOthers(); getIrrational(); // bargaining stage feelVulnerable(); regret(); askWhyToMyself(); dreamOfAlternativeWhatIfScenarios(); postoponeSadness(); // depression stage stayQuiet(); getOverwhelmed(); beConfused(); // acceptance stage acceptWhatHappened(); lookToTheFuture(); reconstructAndWalktrough(); } ``` ### Right ```javascript function recoverFromGrief() { denialStage(); angerStage(); bargainingStage(); depressionStage(); acceptanceStage(); } function denialStage() { absorbTheBadNews(); setNumbAsProtectiveState(); startToRiseEmotions(); feelSorrow(); } function angerStage() { maskRealEffects(); directAngerToOtherPeople(); blameOthers(); getIrrational(); } function bargainingStage() { feelVulnerable(); regret(); askWhyToMyself(); dreamOfAlternativeWhatIfScenarios(); postoponeSadness(); } function depressionStage() { stayQuiet(); getOverwhelmed(); beConfused(); } function acceptanceStage() { acceptWhatHappened(); lookToTheFuture(); reconstructAndWalktrough(); } ``` ## Detection This is a policy smell. Every linter can detect comments not in the first line and warn us. ## Tags * Readability * Long Methods * Comments ## Conclusion Comments are a code smell. If you need to document a design decision, you should do it before the actual method code. ## Relations [Code Smell 03 - Functions Are Too Long](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd) [Code Smell 74 - Empty Lines](https://maximilianocontieri.com/code-smell-74-empty-lines) [Code Smell 05 - Comment Abusers](https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd) \ ___ > Don't get suckered in by the comments, they can be terribly misleading: Debug only the code - *Dave Storer* --- And that’s all for now… The next article will explain 5 more code smells!