Skip to content

Ralireza/clean-code-summary

master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 

README.md

Persian presentation on youtube:

clean code - MrBug

Table of Contents

Meaningful names

Intension-Revealing Names

Bad:

int a;

Good:

int downTimeCounterToLifeEnded;

avoid disinformation

Bad:

int a = l; 
if ( O == l )
   a=O1;
else
   l=01;

Good:

int allMrBugIssues = loadOfWeb;

int zeroNumberOfServer= 0;
int oneNumberOfServer= 1;
int originalNumberOfBugs= 2;
int originalNumberOfHumer= 3;

 if ( originalNumberOfHumer == loadOfWeb )
   allMrBugIssues=originalNumberOfBugs;
 else
   loadOfWeb=oneNumberOfServer;

Meaningful Distinction

Bad:

string deadManProperty;
string deadManInfo;
string deadManData;

Good:

string killedManId;
string nameOfKilledMan;
string allInfoAboutKilledWoman; 

Pronounceable Names

Bad:

string ymdstr = datetime.today().strftime("%y-%m-%d");

Good:

string currentTimeOfHappyMan = datetime.today().strftime("%y-%m-%d");

Use Searchable Names

Bad:

// What is the number 86400 for again?
human.sleep(86400) ;

Good:

// Declare them in the global namespace for the module.
int SECONDS_IN_A_DAY = 60     - 60     - 24 ; 
human.sleep(SECONDS_IN_A_DAY) ;

Avoid Encoding

Bad:

int iHumanCapacity= 1;
string strMyName= "MrBug";
DateTime dLifeLength;
bool impCalculateLifeSuffering(int nPeopleArroundYou){
   bool bSuffering=false;
   if(nPeopleArroundYou > iHumanCapacity)
      bSuffering=true;
   
   return bSuffering;

}

Good:

int humanCapacity= 1;
string myName= "MrBug";
DateTime LifeLength;

bool CalculateLifeSuffering(int PeopleArroundYou){
   bool Suffering=false;
   if(PeopleArroundYou > 0)
      Suffering=true;
   
   return Suffering;

}

Avoid Mental Mapping

Bad:

bestTimesOfDay = ("Morning", "Befor Morning", "After Morning")

for item in bestTimeOfDay:
    #do_stuff()
    #do_some_other_stuff()

    # Wait, what's `item` again?
    print(item)

Good:

bestTimeOfDay = ("Morning", "Befor Morning", "After Morning")

for timeOfDay in bestTimeOfDay:
    #do_stuff()
    #do_some_other_stuff()

    print(timeOfDay)

Pick One Word Per One Concept

Bad:

FetchHumanOverthinkingData(sadness, happiness)

GetHumanOverthinkingData(sadness, happiness)

RetrieveHumanOverthinkingData(sadness, happiness)

Good:

GetHumanOverthinkingData(sadness, happiness)

Dont Pun

Bad:

time = calculateMyBirthday()

# ... some code are happening ....

time = calculateDeathTime()

Good:

timeOfBirthday = calculateMyBirthday()

# ... some code are happening ....

timeOfEndingThisShit = calculateDeathTime()

Functions

Small

Bad:

int calcBeautyOfLife(){
   // here is full of messy condistion and long over 20 lines
   // ...
   // .. 
   // ..
   // ..
   return 0;
}

Good:

int calcHappinessOfLife(){
   if(isHumanAlive)
      return 0;
   // keep it small and simple
}

Indent

Bad:

string howCanIBeAGentleman(){
   for ...
      if ...
        for ...
            if ...
               for ...
                  if ...
                     return "you can not !"
}  

Good:

// break into multi function and max indent of each function is 2
int howCan(){}
int IBe(){}
string AGentleman(){ return "you can not !" }

Just one thing

Bad:

string getFullPackageOfData(string name){
   // some code to eval life problems
   for ...
      if ...
   
   // some code to get information about coffee
   for ...
      if ...

   // some another junk code to eval nothing
   ... 
   ...

}

Good:

string getCoffeeInfo() { }

long evalLifeProblems() { }

void evalNothing() { }

One Level of Abstraction per Function

Bad:

void multiLevelOfAbstraction(){
   // getNameOfUser
   for ...
    if ... 
   
   // check user have a lot of money or not
   for ...
     if ...
}

Good:

string getNameOfUser() { }

bool hasAlotOfMoney()  { }

Reading Code from Top to Bottom: The Stepdown Rule

Bad:

getUserInfo()
getName()
getDataFromServer()

Good:

getDataFromServer()
getUserInfo()
getName()

Switch Statements

Bad:

void deadManOrLiveWoman(){
   switch ...
    case:

    case:
}

Good:

void deadManOrLiveWoman(){
   
}

Use Descriptive Names

Bad:

int handle(string life){
   // some complecated code to calc value of input
   // ...
   // ...
   // ...

   return 0;
}

Good:

int calculateValueOfLife(string life){
   // some complecated code to calc value of input
   // ...
   // ...
   // ...
   
   return 0;
}

Function Arguments

Bad:

int humanDetection(int name, int job, int personality, int degree, int lastTweet, ...){
   return 0;
}

Good:

int humanDetection(){
   return 0;
}
// or max args =3
int humanDetection(int name, int job, int personality){
   return 0;
}

Side effects

Bad:

int evalLifeProblems(){
   changeLifePain();
   changeHumanSadness();
   changeAllOfPeople();

   for ...
      if ...
   
   return 99999999999999999999999999999999999
}

Good:

int evalLifeProblems(){

   for ...
      if ...
   
   return 99999999999999999999999999999999999
}

Command query sepration

Bad:

string timeToDeath(){
   If(Set("username","you")){
      ...
   }
   return "i am cpu not god !" 
}

Good:

string timeToDeath(){
   if(attributeExist("username")){
      ...
   }
   else
      setAtrribute("username","you")

   return "i am cpu not god !" 
}

prefer exception to return error code

Bad:

int findCrazyManInClass(){
   if(!isMan())
      return 1;
  
   if(!isInClass())
      return 2;
  
   if(!isCrazy())
      return 3;
   
   return 1000;
}

Good:

int findCrazyManInClass(){
   try{
   ...
   
   return 1000;

   }
   catch(Error){
      return 0;
   }
   
}

Don’t repeat your self

Bad:

string coolFunction(){
   return "i am not cool";
};

copyOfCoolFunction(){
   return "i am not cool";
}
copyOfCoolFunction(){
   return "i am not cool";
}
copyOfCoolFunction(){
   return "i am not cool";
}
copyOfCoolFunction(){
   return "i am not cool";
}
copyOfCoolFunction(){
   return "i am not cool";
}

Good:

string coolFunction(){
   return "i am not cool";
};

// import cool function and use it
coolFunction();

Comments

Comments Do Not Make Up for Bad Code

Bad:

# a is sum of you and me 
a = b + c

Good:

we = you + me

Explain Yourself in Code

Bad:

// here is function explaination 
// too boring 
// . . . 
// . . . 
iAmComplicatedFunction()

Good:

simple()
function()
toUnderstand()
withoutComments()

Good Comments

Legal Comments

Good:

// Copyright (C) 2020 by mrBug, Inc. All rights reserved.

Informative Comments

Good:

// format matched kk:mm:ss EEE, MMM dd, yyyy 
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");

Explanation of Intent

Bad:

int isBetter(string human){
   if(human == "woman")
      return 0; 
}

Good:

int isBetter(string human){
   if(human == "woman")
      return 0;  // i mean woman is not better 
}

Warning of concequences

Bad:

void relaxFunction(){
   system.sleep(1000000)
}

Good:

// Don't run unless you have some time
void relaxFunction(){
   system.sleep(1000000)
}

TODO Comments

Bad:

void makeSomeDangerInSoftware(){
   
}

Good:

// TODO write this function  when company doesn't pay the money
void makeSomeDangerInSoftware(){
   
}

Bad Comments

Redundant Comments

Bad:

// this function input is name of user and check if the name is you return false becouse you
// are not cool enough
bool isCoolPerson(string name){
   if(name == "you")
      return false;
}

Good:

bool isCoolPerson(string name){
   if(name == "you")
      return false;
}

Mandated Comments

Bad:

/**
* The Manager implementation with which this Container is * associated.
*/
protected Manager manager = null;
/**
* The cluster with which this Container is associated. */
protected Cluster cluster = null;
/**
* The human-readable name of this Container. */
protected String name = null;
/**
* The parent Container to which this Container is a child. */
protected Container parent = null;
/**
* The parent class loader to be configured when we install a * Loader.
*/
protected ClassLoader parentClassLoader = null;

Good:

protected Manager manager = null;

protected Cluster cluster = null;

protected String name = null;

protected Container parent = null;

protected ClassLoader parentClassLoader = null;

Journal Comments

Bad:

* Changes (from 20-Oct-2020)
* --------------------------
* fixed and report

Good:

// keep it clean

Noise Comments

Bad:

/** The day of the month. */
private int dayOfMonth;

Good:

private int dayOfMonth;

Don’t Use a Comment When You Can Use a Function or a Variable

Bad:

// this function gain the pain 
// long long description
void a(){
   ...
}

Good:

void painGainer(){
   ...
}

Position Markers

Bad:

///////////////////////////////////////////
///////////////// mrBug ///////////////////
///////////////////////////////////////////

Good:

// mrBug

Closing Brace Comments

Bad:

while (deadLine != null) {

   work++;
   if(life == null){
      ...
      ...
      ...
      ...
      if(time == "night" ){
         ...
         ...
         ...
         ...
         ...
         ...
         ...
      } // if : time == night
      ...
      ...
      ...
      break;
   }// if : life == null

} //while deadLine

Good:

while (deadLine != null) {

   work++;
   if(life == null){
      anotherSimpleFunction()
      ...
      break;
   }

} 

Attributions and Bylines

Bad:

/* Added by MrBug */

Good:

// keep it clean, let version-contrlol do !

Commented-Out Code

Bad:

this.bytePos = writeBytes(pngIdBytes, 0);
//hdrPos = bytePos;
writeHeader(); writeResolution();
 //dataPos = bytePos; 
 if (writeImageData()) {
   writeEnd();
   // this.pngBytes = resizeByteArray(this.pngBytes, this.maxPos); 

   }

Good:

this.bytePos = writeBytes(pngIdBytes, 0);
writeHeader(); writeResolution();
 if (writeImageData()) {
   writeEnd();
   }

Nonlocal Information

Bad:

/**
* nonLocalFunction description
* nonLocalFunction description
* nonLocalFunction description
* nonLocalFunction description
* nonLocalFunction description
* nonLocalFunction description
*
*
*
* Port on which fitnesse would run. *
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort) {
   this.fitnessePort = fitnessePort; 
}

Good:

/**
* Port on which fitnesse would run. *
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort) {
   this.fitnessePort = fitnessePort; 
}

Too Much Information

Bad:

/*
RFC 2045 - Multipurpose Internet Mail Extensions (MIME)
Part One: Format of Internet Message Bodies
section 6.8. Base64 Content-Transfer-Encoding
The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. When encoding a bit stream via the base64 encoding, the bit stream must be presumed to be ordered with the most-significant-bit first. That is, the first bit in the stream will be the high-order bit in the first 8-bit byte, and the eighth bit will be the low-order bit in the first 8-bit byte, and so on.
*/

Good:

// keep it clean

Formatting

Vertical Formatting

Bad:

lineOfCodePerFile > 500

Good:

lineOfCodePerFile < 100

The Newspaper Metaphor

Bad:

<Not in newspaper mode>

Good:

<headline>
...
<synopsis of the whole story>
...
<details increase>

Vertical Openness Between Concepts

Bad:

package fitnesse.wikitext.widgets;
import java.util.regex.*;
public class BoldWidget extends ParentWidget {
 public static final String REGEXP = "'''.+?'''";
 private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
 Pattern.MULTILINE + Pattern.DOTALL);
 public BoldWidget(ParentWidget parent, String text) throws Exception {
 super(parent);
 Matcher match = pattern.matcher(text);
 match.find();
 addChildWidgets(match.group(1));
 }
 public String render() throws Exception {
 StringBuffer html = new StringBuffer("<b>");
 html.append(childHtml()).append("</b>");
 return html.toString();
 }
}

Good:

package fitnesse.wikitext.widgets;

import java.util.regex.*;

public class BoldWidget extends ParentWidget {
 public static final String REGEXP = "'''.+?'''";
 private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
 Pattern.MULTILINE + Pattern.DOTALL
 );

 public BoldWidget(ParentWidget parent, String text) throws Exception {
 super(parent);
 Matcher match = pattern.matcher(text);
 match.find();
 addChildWidgets(match.group(1));
 }

 public String render() throws Exception {
 StringBuffer html = new StringBuffer("<b>");
 html.append(childHtml()).append("</b>");
 return html.toString();
 }
}

Vertical Distance

Bad:

int verifyAuthentication(string userId){
   for ...
      if ...
   int password;
   for ...
      if ...
   ...
   ...
   // long distance !
   password = 1234;
}

Good:

// declare first of function and/or class
// because its small
int verifyAuthentication(string userId){
   int password;
   for ...
      if ...
   password = 1234;
}

Dependent Functions

Bad:

bool coolFunction(string nothing){
   if(nothing.isEqual(null))
      return true;

   return false;
}
...
/* long long story of code */
...
coolFunction("haha")

Good:

bool coolFunction(string nothing){
   if(nothing.isEqual(null))
      return true;

   return false;
}
coolFunction("haha")
...
/* long long story of code */

Horizontal Formatting

Bad:

public static double calculateArea(double vertical,double horizental) {
 double determinant=determinant(vertical,horizental);
 return (-b+Math.sqrt(determinant))/(2*a);
 }

Good:

public static double calculateArea(double vertical, double horizental) {
 double determinant = determinant(vertical, horizental);
 return (-horizental + Math.sqrt(determinant)) / (2*a);
 }

Indentation

Bad:

public class FitNesseServer implements SocketServer { private FitNesseContext
context; public FitNesseServer(FitNesseContext context) { this.context =
context; } public void serve(Socket s) { serve(s, 10000); } public void
serve(Socket s, long requestTimeout) { try { FitNesseExpediter sender = new
FitNesseExpediter(s, context);
sender.setRequestParsingTimeLimit(requestTimeout); sender.start(); }
catch(Exception e) { e.printStackTrace(); } } }

Good:

public class FitNesseServer implements SocketServer {
   private FitNesseContext context;
      this.context = context;
   }
   public void serve(Socket s) {
      serve(s, 10000);
   }
   public void serve(Socket s, long requestTimeout) {
      try {
         FitNesseExpediter sender = new FitNesseExpediter(s, context);
         sender.setRequestParsingTimeLimit(requestTimeout);
         sender.start();
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }
}

Team Rules

Bad:

Every programmer has his own favorite formatting rules

Good:

A team of developers should agree
upon a single formatting style

Error Handeling

Use Exceptions Rather Than Return Codes

Bad:

errno value       Error
1             /* Operation not permitted */
2             /* No such file or directory */
3             /* No such process */
4             /* Interrupted system call */
5             /* I/O error */
6             /* No such device or address */
7             /* Argument list too long */
8             /* Exec format error */
9             /* Bad file number */
10            /* No child processes */
11            /* Try again */
12            /* Out of memory */
13            /* Permission denied */

Good:

public void sendShutDown() {
  try {
    tryToShutDown();
  } catch (DeviceShutDownError e) {
    logger.log(e);
}
private void tryToShutDown() throws DeviceShutDownError {
  // ..
}

Write Your Try-Catch-Finally Statement First

Bad:

int main(){
   // code
}

Good:

try {
    int main(){
      // code

   }
  } catch (Error e) {
    logger.log(e);
  }

Provide Context with Exceptions

Bad:

public void sendShutDown() {
  try {
    tryToShutDown();
  } catch (DeviceShutDownError e) {
    logger.log("some error occured !");
}
private void tryToShutDown() throws DeviceShutDownError {
  // ..
}

Good:

public void sendShutDown() {
  try {
    tryToShutDown();
  } catch (DeviceShutDownError e) {
    logger.log(class.name + function.name + e);
}
private void tryToShutDown() throws DeviceShutDownError {
  // ..
}

Don’t Return Null

Bad:

List<Employee> employees = getEmployees();
if (employees != null) {
 for(Employee e : employees) {
   totalPay += e.getPay();
 }
}

Good:
```java
public List<Employee> getEmployees() {
 if( .. there are no employees .. )
   return Collections.emptyList();
   // or throw an exception
}

Don’t Pass Null

Bad:

public class MetricsCalculator
{
 public double xProjection(Point p1, Point p2) {
   return (p2.xp1.x) * 1.5;
 }
 …
}

Good:

public class MetricsCalculator
{
   public double xProjection(Point p1, Point p2) {
      assert p1 != null : "p1 should not be null";
      assert p2 != null : "p2 should not be null";
      return (p2.xp1.x) * 1.5;
   }
}

Boundaries

Using Third-Party Code

Bad:

Map sensors = new HashMap();
Sensor s = (Sensor)sensors.get(sensorId);

Good:

public class Sensors {
   private Map sensors = new HashMap();

   public Sensor getById(String id) {
      return (Sensor) sensors.get(id);
}

}

Exploring and Learning Boundaries

Bad:

import superComputer

superComputer.solve()

Good:

import superComputer

@test
...
@test
...

Using Code That Does Not Yet Exist

Bad:

// stop development 

Good:

interface pendingModule()
interface fakeApi()

Clean Boundaries

Bad:

if (third-party == 'changed')
   change(wholeSoftware)

Good:

if (third-party == 'changed')
   change(surviveSoftwareWithoutBigChange)

Unit Tests

The Three Laws of TDD

Bad:

write test and write test

Good:

unitTest() -> failedUnitTest() -> makeCodeBetter() -> isUnitTestFail() -> production() -> makeMoney()

Clean Tests

Bad:

// just write test, and lose them

Good:

// keep it clean, make it readable!

One Assert per test

Bad:

@Test
testPainMaximization(){
   if(lifeExistance)
      return true;
   
   if(isDeveloper)
      return true;

}  

Good:

@Test
testLifeExistance()

@Test
testIsDeveloper()

F.I.R.S.T

Good:

Fast()
Independient() 
Repeatable() // any env
SelfValidating() // return true || false
Timely() // write befor production

Classes

Encapsulation

Bad:

// make all things private 
// fanatic about encapsulation 

Good:

// make protected something
// access by a test

Classes Should be Small

Bad:

public class longBoringStory(){

   ...
   too many methods 
   ....
}

Good:

public class shortCoolStory(){

   public void tellMeStory(){

   }
}

The Single Responsibility Principle

Bad:

public class SuperSuperResponsibility(){

   ...
   too many methods 
   ....
}

Good:

public class cleanSingleResponsibility(){

   public void iAmCleanYouKnow(){
      
   }
}

Cohesion

Bad:

public class longBoringStory(){

  string story;
  string character;
  string word;
  string page;
  srting time;
  ...
  devilManipulator(string story, string character, 
  string word,   string page,   srting time ){

  }
}

Good:

public class ShortStory(){

  string story;
  string character;

  ...
  tellStory(string story, string character ){

  }
}

Maintaining Cohesion Results in Many Small Classes

Bad:

public class BigClassDoEveryThing(){

}

Good:

public class Cool(){
   
}
public class Small(){
   
}
public class Class(){
   
}

Organizing for change

Bad:

// no abstraction just implement to work and make money

Good:

// use interfaces and design in multiLayer abstraction