Skip to content

Clean Code

Sandesh Kota edited this page Dec 15, 2017 · 9 revisions

CLEAN CODE “We are Authors”

#0.0 Principles – Global Collection

DRY : Don't Repeat Yourself YAGNI : You Ain't Gonna Need It 7 rule : Remembering more than 7 items is difficult. So ensure that we limit the variables/params to a function to less than 7

1.0 Principles

3 Core Principles:-

  1. Right tool: One Language Per File. Ex: Html in .html , Styles in .css, Javascript in .js
  2. High Signal to Noise ratio: TED - Terse (using few words), Expressive, Do One thing Noise: - High Cyclomatic Complexity - Excessive Indentation - Zombie Code - Unnecessary Comments - Poorly named structures - Huge Classes - Long methods - Repetition - No Whitespace - Overly verbose
  3. Self-Documenting: Clear intent Layers of Abstractions Format for readability Favor Code over Comments

NOTE: Every Tech is Potential Evil Linq-to-Sql: No for - Massive Queries Outer Joins Flash/Silverlight: No for - When native is an option Javascript: No for - Sole Validation Proprietary Logic DRY : Don't repeat yourself - No Copy & Paste - Decreases Signal to noise ratio - Increases the number of lines of code (lines in code == weight in airplane) - Maintenance problem - Many of same principles as relational DB normalization

#2.0 Naming

  • Naming matters
  • Readability : understanding the intent of the code

Dirty: List p = new List() { 5.50m, 10.48m, 12.69m }; decimal t = 0; foreach (var i in p) { t += i; } return t;

Clean: List prices = new List() { 5.50m, 10.48m, 12.69m }; decimal total = 0; foreach (var price in prices) { total += price; } return total;

CLASS Names: Dirty: WebsiteBO Utility Common MyFunctions MikesObjects *Manager / *Processor / *Info

Clean: - 1. Nouns (Not Verbs) 2. Be Specific 3. Single Responsibility 4. Avoid Generic Suffixes User Account QueryBuilder ProductRepository

METHOD names: Dirty: Get Process Pending DoIt Start On_Init, Page_Load,etc. - Named based on when it is called not what it does

Clean: GetRegisteredUsers isvalidSubmission ImportDocument SendEmail

WARNING SIGNS: And, If, Or - Probably doing too many things -> Split

ABBREVIATIONS: No

  • Difficult to have a conversation with others.
  • Abbreviations may have different meanings.

BOOLEAN Values: Dirty: - open, start, status, login Ex: if(login) {} Clean: - isOpen, done, isActive, loggedIn Ex: if(loggedIn){}

SYMMETRY: Dirty: on/disable quick/slow lock/open slow/max

Clean: on/off fast/slow lock/unlock min/max

#3.0 Conditionals

  1. Clear Intent
  2. Use the right tool
  3. Bite-size logic
  4. Sometimes code isn't the answer

ASSIGN BOOLEAN IMPLICITLY Dirty: bool goingOut;

if(cashInwallet > 6) { goingOut = true; } else { goingOut = false; }

Clean: bool goingOut = cashInWallet > 6;

POSITIVE CONDITIONALS: Dirty: if(!isNotLoggedIn) Clean: if(loggedIn)

TERNARY ELEGANCE:

Dirty: int registrationFee;

if(isSpeaker) { registrationFee = 0; } else { registrationFee = 50; }

Clean: int registrationFee = isSpeaker ? 0 : 50;

STRINGLY TYPED:

Dirty: if (employeeType = "manager")

Clean: if (employeeType = Enums.EmployeeType.Manager)

Benefits:

  • No Typos
  • Intellisense support
  • Searchable, References

MAGIC NUMBERS: Dirty: If(age > 21) { } If (status == 2) { }

Clean: Const int legalDrinkingAge = 21; If (age > legalDrinkingAge) { }

If (status == Status.Active) { }

COMPLEX CONDITIONALS If (car.Year > 1980 && (car.Make == “Ford” || car.Make == “Chevrolet”) && car.Odometer < 100000 && car.Vin.StartsWith(“V2”) || car.Vin.StartsWith(“VIA3”)) {

}

Better:

  • Intermediate variables
  • Encapsulate with a function

Dirty: If (employee.Age > 55 && employee.YearsEmployed > 10 && employee.IsRetired == true) { }

Clean: Bool eligibleForPension = employee.Age > MinretirementAge && employee.YearsEmployed > MinPensionEmploymentYears && employee.IsRetired;

Dirty: If (fileExtension == “mp4” || fileExtension == “mpg” || fileExtension == “avi”) && (isAdmin || isActiveFile)

Clean: If (ValidFileRequest(fileExtension, isActiveFilem isAdmin))

POLYMORPHISM vs ENUMS Instead of Switch statements use Polymorphism : Parent – Child Classes

BE DECLARATIVE C# : LINQ to Objects JavaScript : jLinq Java : Lambdaj Python : Pynq

Dirty: Var matchingUsers = new List();

foreach (var user in users) { If(user.AccountBalance < minimumAccountBalance && user.Status == Status.active) { matchingUsers.Add(user); } }

Return matchingUsers;

Clean: Return users .Where(u => u.AccountBalance < minimumAccountBalance ) .Where(u => u.Status == Status.Active );

#4.0 Functions

Function v/s Method: Method – Methods are associated with an Object

When to Create a Function: Duplication Indentation Unclear Intent – Well named method If code does > 1 Task - SRP

Avoid Duplicity: DRY, Code is liability, Less is more

Excessive Indentation Overview: If there are more than 3 if conditions Solutions:

  • Extract Method
  • Return Early Use a return when it enhances readability… In certain routines, once you know the answer.. not returning immediately means that you have to write more code. – Steve McConnell, “Code Complete”
  • Fail Fast Throw exception as soon as possible Ensure you throw an exception in “default” switch clause. And log the value you ae checking.

Convey Intent: Instead of condition check, encapsulate the logic inside a method which has a meaningful name.

Do One Thing: SRP for a function

  • Aids the reader
  • Promotes reuse
  • Eases naming and testing
  • Avoids side-effects

Mayfly Variables: Do not create variables at the beginning as developer has to remember everything Declare variables where its used. JIT Mayfly  shortest lifespan 30mins – 24 hours

Parameters: Too many parameters is difficult to understand

  • Strive for 0 – 2 parameters
  • Easier to understand
  • Easier to test
  • Helps assure function does one thing

Should not have flag arguments: Dirty: private void Saveuser(User user, bool emailUser) { // some logic to save user If (emailUser) { // send email to user } }

Clean: private void Saveuser(User user) { // some logic to save user }

private void Emailuser(User user) { // send email to user }

What’s Too Long:

  • If there are more comments and whitespaces
  • Scrolling required
  • Function naming issues
  • Multiple Conditionals
  • Hard to digest (max 7 params/variables)

Funciton should Rarely be over 20 lines, Harldy ever over 100 lines, No more than 3 parameters – Robert C.Martin, “Clean Code”

Exceptions:

  • Kinds of Exceptions o Unrecoverable: Null reference, File not found, Access denied o Recoverable: Retry Connection, Try different file, Wait and try again o Ignorable: Logging
  • Do not catch an exception if you are not handling it. Let it flow

Dirty: try { // many // lines // of // complicated // code // and // verbose // logic // here } Catch() { // do something here }

Clean: try { SaveThePlanet(); } Catch() { // do something here }

Private void SaveThePlanet() { // many // lines // of // complicated // code // and // verbose // logic // here }

#5.0 Classes

Clone this wiki locally