"I could list all of the qualities that I notice in clean code, but there is one overarching quality that leads to all of them. Clean code always looks like it was written by someone who cares. There is nothing obvious that you can do to make it better. All of those things were thought about by the code’s author, and if you try to imagine improvements, you’re led back to where you are, sitting in appreciation of the code someone left for you—code left by someone who cares deeply about the craf."
"Clean code can be read, and enhanced by a developer other than its original author. It has unit and acceptance tests. It has meaningful names. It provides one way rather than many ways for doing one thing. It has minimal dependencies, which are explicitly defined, and provides a clear and minimal API. Code should be literate since depending on the language, not all necessary information can be expressed clearly in code alone."
"Runs all the tests, contains no duplication, expresses all the design ideas that are in the system, minimizes the number of entities such as classes, methods, functions, and the like."
"You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem."
So we should refactor all the time
Class or method should have only one reason to change and a reason can viewed as someone who interacts with the system.
In [1]:
#bad
class FooController
#...
def show
if foo_has_something?
#do something
end
#do something else
end
private
def foo_has_something?
@foo.something.count > 0
end
#...
end
Out[1]:
In [2]:
#good
#foor_controller.rb
class FooController
#...
def show
if @foo.has_something?
#do something
end
#do something else
end
#...
end
#foo.rb
class Foo
def foo_has_something?
something.count > 0
end
end
Out[2]:
In [3]:
#bad
class Notifier
def send_message(message)
# send message
end
def generate_reports
# generate reports
end
def authenticate
# do authentication
end
end
Out[3]:
In [4]:
#good
class Notifier
def send_message(message)
# send message
end
end
class NotifierReport
def generate
# generate reports
end
end
class NotifierAuthentication
def authenticate
# do authentication
end
end
Out[4]:
In [5]:
#bad
class GraphicEditor
def draw_shape(shape)
if s.m_type==1
draw_circle(shape);
elsif s.m_type==2
draw_rectangle(shape);
end
end
def draw_circle(circle) end #draw the circle
def draw_rectangle(rectangle) end #draw the rectangle
end
class Shape
attr_accessor :m_type
end
class Rectangle < Shape
def initialize
m_type=1
end
end
class Circle < Shape
def initialize
m_type=2
end
end
Out[5]:
In [ ]:
#good
class GraphicEditor
def draw_shape(shape)
shape.draw
end
end
class Shape
#default behavior for shapes
end
class Rectangle < Shape
def draw
#draw the rectangle
end
end
class Circle < Shape
def draw
#draw the circle
end
end
In [ ]:
#bad
class Canvas
def draw(component)
case component.type
when 'popup'
generate_popup_html(component)
when 'section'
generate_section_html(component)
end
end
def generate_popup_html(popup_component)
#build html without html, head and body tags
end
def generate_section_html(section_component)
#build complete HTML
end
end
In [ ]:
#bad
class Component
def type=(type)
@type=type
end
def type
@type
end
end
class PopupComponent
def initializer
type='popup'
end
#...
end
class SectionComponent
def initializer
type='section'
end
#..
end
In [ ]:
#good
class Canvas
def draw(component)
component.html
end
end
class Component
#some default behavior
end
class PopupComponent < Component
def html
#build html without html, head and body tags
end
end
class SectionComponent < Component
def html
#build complete HTML
end
end
In [ ]:
#bad
class Canvas
def draw component
component.draw
end
end
class Component
#doesn't implement draw
end
class PopupComponent < Component
def draw
end
end
In [ ]:
#good
class Canvas
def draw component
component.draw
end
end
class Component
def draw
end
end
class PopupComponent < Component
def draw
end
end
In [ ]:
#bad
class Component
def draw_section_header
end
def draw_content
end
end
class PopupComponent < Component
# ..
end
class SectionComponent < Component
# ..
end
In [ ]:
#good
class Component
def draw_content
end
end
class PopupComponent < Component
# ..
end
class SectionComponent < Component
def draw_section_header
end
end
In [ ]:
#bad
class MyController
def index
connection = DB.open
connection.execute("<query here>")
@pages = #..treat query
end
end
In [ ]:
#good
class MyController
def index
@pages = Page.all
end
end
class Page < Database::AbstractModel
end
class Database::AbstractModel
def self.all
#connect and select from database
end
end
What happens if a team don't follow a style guide?
Thus follow the style guide of your team