Top Banner
Clean Code (ROR) Md. Tauhidul Islam Software Engineer Nascenia Ltd.
45

Clean code

Apr 15, 2017

Download

Software

Nascenia IT
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Clean code

Clean Code (ROR)

Md. Tauhidul IslamSoftware Engineer

Nascenia Ltd.

Page 2: Clean code

Table of Content

Source Code Layout

Syntax

Comments

Page 3: Clean code

Source Code Layout

Page 4: Clean code

Indentation

Use two spaces per indentation level (aka soft tabs). No hard tabs.

# bad - four spacesdef some_method do_somethingend

# good - two spacedef some_method do_somethingend

Page 5: Clean code

Line endings

Use Unix-style line endings. (*BSD/Solaris/Linux/OS X users are covered by default, Windows users have to be extra careful.)

$ git config --global core.autocrlf true

Page 6: Clean code

Statements & Expressions

Don't use ; to separate statements and expressions. As a corollary - use one expression per line.

# goodputs 'foobar'puts 'foo'puts 'bar'puts 'foo', 'bar'

# badputs 'foobar';puts 'foo'; puts 'bar'

Page 7: Clean code

Use spaces

Use spaces around operators, after commas, colons and semicolons.

The only exception is the exponent operator

sum = 1 + 2a, b = 1, 2class FooError < StandardError; end

# bade = M * c ** 2

# goode = M * c**2

Page 8: Clean code

Use spaces

No spaces after (, [ or before ], ). Use spaces around { and before }

For hash literals two styles are considered acceptable

With interpolated expressions, there should be no padded-spacing inside the braces.

{one: 1, two: 2}{ one: 1, two: 2 }

[1, 2, 3].each { |e| puts e }

# bad"From: #{ user.name }"

# good"From: #{user.name}"

Page 9: Clean code

Use spaces

No space after !

No space inside range literals

# bad! something

# good!something

# bad1 .. 3'a' … 'z'

# good1..3'a'...'z'

Page 10: Clean code

When-Case

Indent when as deep as case

# badcase when song.name == 'Misty' puts 'Not again!' when song.duration > 120 puts 'Too long!' when Time.now.hour > 21 puts "It's too late" else song.playend

# goodcasewhen song.name == 'Misty' puts 'Not again!'when song.duration > 120 puts 'Too long!'when Time.now.hour > 21 puts "It's too late"else song.playend

Page 11: Clean code

Alignment: assigning a conditional expression

When assigning the result of a conditional expression to a variable, preserve the usual alignment of its branches

kind = case year when 1850..1889 then 'Blues' when 1890..1909 then 'Ragtime' when 1910..1929 then 'New Orleans Jazz' when 1930..1939 then 'Swing' when 1940..1950 then 'Bebop' else 'Jazz' end

result = if some_cond calc_something else calc_something_else end

Page 12: Clean code

Empty lines

Use empty lines between method definitions and also to break up methods into logical paragraphs internally

def some_method data = initialize(options)

data.manipulate!

data.resultend

def some_method resultend

Page 13: Clean code

Assigning default values to method parameters

Use spaces around the = operator when assigning default values to method parameters

# baddef some_method(arg1=:default, arg2=nil, arg3=[]) # do something...End

# gooddef some_method(arg1 = :default, arg2 = nil, arg3 = []) # do something...end

Page 14: Clean code

Align the parameters of a method call

When aligning parameters is not appropriate due to line-length constraints, single indent for the lines after the first is also acceptable

def send_mail(source) Mailer.deliver( to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text )end

def send_mail(source) Mailer.deliver(to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text)end

Page 15: Clean code

Align the elements of array

Align the elements of array literals spanning multiple lines

# bad - single indentmenu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

# goodmenu_item = [ 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

# goodmenu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

Page 16: Clean code

Add underscores to large numeric

Add underscores to large numeric literals to improve their readability

# bad - how many 0s are there?num = 1000000

# good - much easier to parse for the human brainnum = 1_000_000

Page 17: Clean code

Use Rdoc and its conventions for API documentation. Don't put an empty line between the comment block and the def

Limit lines to 80 characters

Avoid trailing whitespace

End each file with a newline

Page 18: Clean code

Syntax

Page 19: Clean code

Methods with parentheses

Use def with parentheses when there are parameters

# baddef some_method() # body omittedend

# gooddef some_method # body omittedend

# baddef some_method_with_parameters param1, param2 # body omittedend

# gooddef some_method_with_parameters(param1, param2) # body omittedend

Page 20: Clean code

Optional arguments

Define optional arguments at the end of the list of arguments

# baddef some_method(a = 1, b = 2, c, d) puts "#{a}, #{b}, #{c}, #{d}"end

# gooddef some_method(c, d, a = 1, b = 2) puts "#{a}, #{b}, #{c}, #{d}"end

Page 21: Clean code

Parallel assignment

Avoid the use of parallel assignment for defining variables

# bada, b, c, d = 'foo', 'bar', 'baz', 'foobar'

# gooda = 'foo'b = 'bar'c = 'baz'd = 'foobar'

a = 'foo'b = 'bar'

a, b = b, a

puts a # => 'bar'puts b # => 'foo'

Page 22: Clean code

Nested ternary operator

Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested

# badsome_condition ? (nested_condition ? nested_something : nested_something_else) : something_else

# goodif some_condition nested_condition ? nested_something : nested_something_elseelse something_elseend

Page 23: Clean code

Expressions which return a result

Leverage the fact that if and case are expressions which return a result

# goodresult = if condition x else y end

# badif condition result = xelse result = yend

result = condition ? x : y

Page 24: Clean code

and - or

Always use && and || instead of “and” and “or”

# badif some_condition and some_other_condition do_somethingend

# goodif some_condition && some_other_condition do_somethingend

Page 25: Clean code

Condition of single-line body

Favor modifier if/unless usage when you have a single-line body

# badif some_condition do_somethingend

# gooddo_something if some_condition

# another good optionsome_condition && do_something

Page 26: Clean code

Avoid if for negative conditions

Favor unless over if for negative conditions (or control flow ||)

# baddo_something if !some_condition

# baddo_something if not some_condition

# gooddo_something unless some_condition

# another good optionsome_condition || do_something

Page 27: Clean code

unless with else

Do not use unless with else. Rewrite these with the positive case first

# goodif success? puts 'success'else puts 'failure'end

# badunless success? puts 'failure'else puts 'success'end

Page 28: Clean code

Parentheses around the condition

Don't use parentheses around the condition of an if/unless/while/until

# goodif x > 10 # body omittedend

# badif (x > 10) # body omittedend

Page 29: Clean code

while/until: single-line body

Favor modifier while/until usage when you have a single-line body

# badwhile some_condition do_somethingend

# gooddo_something while some_condition

Page 30: Clean code

while for negative conditions

Favor until over while for negative conditions

# baddo_something while !some_condition

# gooddo_something until some_condition

Page 31: Clean code

Parentheses with no arguments

Omit parentheses for method calls with no arguments

# badKernel.exit!()2.even?()fork()'test'.upcase()

# goodKernel.exit!2.even?fork'test'.upcase

Page 32: Clean code

Use the proc invocation shorthand when the invoked method is the only operation of a block

# badnames.map { |name| name.upcase }

# goodnames.map(&:upcase)

Page 33: Clean code

do...end for blockPrefer {...} over do...end for single-line blocks. Avoid using {...} for multi-line blocks

# badnames.select do |name| name.start_with?('S')end.map { |name| name.upcase }

# goodnames.select { |name| name.start_with?('S') }.map(&:upcase)

# badnames.each do |name| puts nameend

# goodnames.each { |name| puts name }

Page 34: Clean code

Return keyword

Avoid return where not required for flow of control

# baddef some_method(some_arr) return some_arr.sizeend

# gooddef some_method(some_arr) some_arr.sizeend

Page 35: Clean code

Self keyword

Avoid self where not required. (It is only required when calling a self write accessor.)

# gooddef ready? if last_reviewed_at > last_updated_at worker.update(content, options) self.status = :in_progress end status == :verifiedend

# baddef ready? if self.last_reviewed_at > self.last_updated_at self.worker.update(self.content, self.options) self.status = :in_progress end self.status == :verifiedend

Page 36: Clean code

Self assignment operators

Use shorthand self assignment operators whenever applicable

# goodx += yx *= yx **= yx /= yx ||= yx &&= y

# badx = x + yx = x * yx = x**yx = x / yx = x || yx = x && y

Page 37: Clean code

Initialize variables if nil

Use ||= to initialize variables only if they're not already initialized

# badname = name ? name : 'Bozhidar'

# badname = 'Bozhidar' unless name

# good - set name to 'Bozhidar', only if it's nil or falsename ||= 'Bozhidar'

Page 38: Clean code

Space before parenthesis of method params

Do not put a space between a method name and the opening parenthesis

# badf (3 + 2) + 1

# goodf(3 + 2) + 1

Page 39: Clean code

Comments

Page 40: Clean code

Comments

Good code is its own best documentation. As you're about to add a comment, ask yourself, "How can I improve the code so that this comment isn't needed?" Improve the code and then document it to make it even clearer.

-- Steve McConnell

Page 41: Clean code

Comments

Write self-documenting code and ignore the rest of this section. Seriously!

Write comments in English

Use one space between the leading # character of the comment and the text of the comment

Keep existing comments up-to-date. An outdated comment is worse than no comment at all

Avoid writing comments to explain bad code. Refactor the code to make it self-explanatory

Page 42: Clean code

Superfluous comments

Avoid superfluous comments

# badcounter += 1 # Increments counter by one.

Page 43: Clean code

Block comments

Don't use block comments

# bad=begincomment lineanother comment line=end

# good# comment line# another comment line

Page 44: Clean code

Referenceshttps://github.com/bbatsov/ruby-style-guide

Page 45: Clean code

Questions?