-
Notifications
You must be signed in to change notification settings - Fork 0
Clean Code
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:-
- Right tool: One Language Per File. Ex: Html in .html , Styles in .css, Javascript in .js
- 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
- 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
- Clear Intent
- Use the right tool
- Bite-size logic
- 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