CSC/ECE 517 Fall 2012/ch1 1w23 ph: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(125 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Ruby Coding Guidelines =
== '''Ruby Coding Guidelines''' ==


Designed and developed in the mid-1990s by Yukihiro "Matz" Matsumoto in Japan, Ruby embodies syntax inspired by Perl with Smalltalk-like features and was also influenced by Eiffel and Lisp. Ruby Coding Guidelines include best practices followed generally for most of the object oriented programming languages as Ruby is entirely 'Object Oriented'. Also known as 'Ruby Coding conventions', these are a set of guidelines that recommend programming style, practices and methods for each aspect of a piece of program written in Ruby.  
[http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby] Coding Guidelines include best practices followed generally for most of the [http://en.wikipedia.org/wiki/Category:Object-oriented_programming_languages object oriented programming languages] as Ruby is entirely 'Object Oriented'. Also known as 'Ruby Coding conventions', these are a set of guidelines that recommend programming style, practices and methods for each aspect of a piece of program written in Ruby.  


Software programmers are highly recommended to follow these guidelines to help improve the readability of their source code and make software maintenance easier. Naming conventions, class and member design principles, maintainability, performance, documentation and layout are the important areas where these guidelines have to be followed. More important than the reasons for having a guideline is actually adhering to it consistently.  Having a coding guideline documented and available means nothing if developers are not using it consistently.
Software programmers are highly recommended to follow these guidelines to help improve the readability of their source code and make software maintenance easier. Naming conventions, class and member design principles, maintainability, performance, documentation and layout are the important areas where these guidelines have to be followed. More important than the reasons for having a guideline is actually adhering to it consistently.  Having a coding guideline documented and available means nothing if developers are not using it consistently.
Line 7: Line 7:
__TOC__
__TOC__


== '''Types of Guidelines''' ==
Coding guidelines in Ruby can be defined individually for major sections that code consists of. Naming , Class Design , Member Design , Maintainability, Performance, Documentation and Layout guidelines are illustrated below. These guidelines contain sections common to all of these as well as sections which apply to each one individually.


== Importance of guidelines ==
=== Naming Guidelines<ref>http://itsignals.cascadia.com.au/?p=7</ref> ===
== Types of Guidelines ==  
----
=== Naming Guidelines ===
Ruby uses the first character of the name to help it determine it’s intended use.
Ruby uses the first character of the name to help it determine it’s intended use.
*Local Variables
The standard Ruby file extension is .rb, although many people working on [http://en.wikipedia.org/wiki/Unix UNIX]-like systems don't bother with it for stand-alone scripts. Whether or not one uses it for scripts is up to them, but they will need to use it for library files or they will not be found by the interpreter.
:Lowercase letter followed by other characters, naming convention states that it is better to use underscores rather than camelBack for multiple word names, e.g. mileage, variable_xyz
 
*Instance Variables
*'''Local Variables'''
:Instance variables are defined using the single "at" sign (@) followed by a name. It is suggested that a lowercase letter should be used after the @, e.g. @colour
:Should use lowercase letter followed by other characters. Naming convention states that it is better to use underscores rather than [http://en.wikipedia.org/wiki/CamelCase camelBack] for multiple word names, e.g. average, variable_xyz
*Instance Methods
*'''Instance Variables'''
:Method names should start with a lowercase letter, and may be followed by digits, underscores, and letters, e.g. paint, close_the_door
:Instance variables are defined using the single "at" sign (@) followed by a name. It is suggested that a lowercase letter should succeed @, e.g. @color
*Class Variables
*'''Instance Methods'''
:Class variable names start with a double "at" sign (@@) and may be followed by digits, underscores, and letters, e.g. @@colour
:Method names should start with a lowercase letter, and may be followed by digits, underscores, and letters. The name should possibly be a verb e.g. move, display_details
*Constant  
*'''Class Variables'''
:Constant names start with an uppercase letter followed by other characters. Constant objects are by convention named using all uppercase letters and underscores between words, e.g. THIS_IS_A_CONSTANT
:Class variable names start with a double "at" sign (@@) and may be followed by digits, underscores, and letters, e.g. @@color
*Class and Module  
*'''Constant'''
:Class and module names starts with an uppercase letter, by convention they are named using MixedCase, e.g. module Encryption, class MixedCase
:Constant names usually start with an uppercase letter followed by other characters. Constant objects are by convention named using all uppercase letters and underscores between words, e.g. THIS_IS_A_CONSTANT
*Global Variables
*'''Class and Module'''
:Class names are recommended to be be nouns. In the case of modules, it's harder to make a clear recommendation. The names of [http://en.wikipedia.org/wiki/Mixin mix-ins] (which are just modules), however,  should probably be adjectives, such as the standard [http://en.wikibooks.org/wiki/Ruby_Programming/Reference/Objects/Enumerable Enumerable] and [http://www.ruby-doc.org/core-2.0.0/Comparable.html Comparable] modules. Class and module names starts with an uppercase letter, by convention they are named using MixedCase, e.g. module Encryption, class MixedCase
*'''Global Variables'''
:Starts with a dollar ($) sign followed by other characters, e.g. $global
:Starts with a dollar ($) sign followed by other characters, e.g. $global
*Model Naming Convention
 
:Table: orders
Considering customer order information as the data being used for an application, below naming guidelines give an idea of good class/table/file names.
:Class: Order
*'''Model Naming Convention'''
:File: /app/models/order.rb
<pre>
:Primary Key: id
Table: orders
:Foreign Key: customer_id
Class: Order
File: /app/models/order.rb
Primary Key: id
Foreign Key: customer_id
Link Tables: items_orders
Link Tables: items_orders
*Controller Naming Convention
</pre>
:Class: OrdersController
 
:File: /app/controllers/orders_controller.rb
*'''Controller Naming Convention'''
:Layout: /app/layouts/orders.html.erb
<pre>
*View Naming Convention
Class: OrdersController
:Helper: /app/helpers/orders_helper.rb
File: /app/controllers/orders_controller.rb
:Helper Module: OrdersHelper
Layout: /app/layouts/orders.html.erb
:Views: /app/views/orders/… (list.html.erb for example)
</pre>
*Tests Naming Convention
*'''View Naming Convention'''
:Unit: /test/unit/order_test.rb
<pre>
:Functional: /test/functional/orders_controller_test.rb
Helper: /app/helpers/orders_helper.rb
:Fixtures: /test/fixtures/orders.yml
Helper Module: OrdersHelper
Views: /app/views/orders/… (list.html.erb for example)
</pre>
*'''Tests Naming Convention'''
<pre>
Unit: /test/unit/order_test.rb
Functional: /test/functional/orders_controller_test.rb
Fixtures: /test/fixtures/orders.yml
</pre>


=== Class Design Guidelines ===
=== Class Design Guidelines ===
----
A class in Ruby always starts with the keyword class followed by the name of the class. The name should always be in initial capitals. Class Customer can be displayed as:
<pre>
class Customer
end
</pre>
A class is terminated by using the keyword end. All the data members in the class are between the class definition and the end keyword.
Ruby blurs the distinction between design and implementation. Ideas that have to be expressed at the design level in other languages can be implemented directly in Ruby. To help in this process, Ruby has support for some design-level strategies. These strategies can be used to design classes accordingly as suitable for different types of  applications.
*'''[http://en.wikipedia.org/wiki/Visitor_pattern The Visitor pattern]''' is a way of traversing a collection without having to know the internal organization of that collection.
*'''[http://en.wikipedia.org/wiki/Delegation_pattern Delegation]''' is a way of composing classes more flexibly and dynamically than can be done using standard inheritance.
*The '''[http://en.wikipedia.org/wiki/Singleton_pattern Singleton pattern]''' is a way of ensuring that only one instantiation of a particular class exists at a time.
*The '''[http://en.wikipedia.org/wiki/Observer_pattern Observer pattern]''' implements a protocol allowing one object to notify a set of interested objects when certain changes have occurred.
Normally, all four of these strategies require explicit code each time they're implemented. With Ruby, they can be abstracted into a library and reused freely and transparently.
=== Member Design Guidelines ===
=== Member Design Guidelines ===
----
While defining class members, it is very important to keep in mind the access restrictions. Scope and life-time of class members are different for different restrictions, as illustrated below.
<pre>
public
totally accessible.
protected
accessible only by instances of class and direct descendants. Even through hasA relationships. (see below)
private
accessible only by instances of class (must be called nekkid no “self.” or anything else).
class A
  # Restriction used w/o arguments set the default access control.
  protected
  def protected_method
    # nothing
  end
end
class B < A
  def test_protected
    myA = A.new
    myA.protected_method
  end
  # Used with arguments, sets the access of the named methods and constants.
  public :test_protected
end
b = B.new.test_protected
</pre>
=== Maintainability Guidelines ===
=== Maintainability Guidelines ===
=== Performance Guidelines ===
----
*Avoid nesting loops more than three levels deep
Maintainability guidelines are important to programmers for a number of reasons:
: Nesting not only slows your code down but also can make maintenance of the codebase difficult if it goes too many levels deep. Limiting nesting of loops and functions to three levels or less is a good rule of thumb to keep your code performant.
<blockquote>
*Avoid unnecessary variable assignments
*40%-80% of the lifetime cost of a piece of software goes to maintenance.
: New programmers, tend to assign variables more than necessary.  A great example is when someone defines a variable to store a return value and then returns that variable; just return the value directly.
*Hardly any software is maintained for its whole life by the original author.
*Reduce usage of disk I/O
*Code conventions improve the readability of the software, allowing engineers to understand new code more quickly and thoroughly.
: Disk I/O is one of the biggest bottlenecks remaining in computing. Read/write operations to disk are extremely slow and it’s best to avoid using the disk whenever possible. Many people are now using software such as memcached which allows data to be stored in memory and only periodically written to disk. The speed improvement while using a memory caching system is tremendous.
*If you ship your source code as a product, you need to make sure it is as well packaged and clean as any other product you create.
*Use Ruby Enterprise Edition
</blockquote>
: Ruby Enterprise edition provides up to 33% lower memory usage.  In order to take advantage of these performance gains though you must be sure to program according to their guidelines.
The following guidelines are to be followed to improve the software maintainability
*Avoid method calls as much as possible
* '''Profile your code regularly'''
: Method calls are very expensive operations and should be avoided when necessary.
: If you profile your code regularly you’ll be able to tell if the latest change to the code will have an adverse effect on performance.  Integrate profiling into your testing process and make it automated to ensure that it’s not forgotten.  Like unit testing and BDD([http://en.wikipedia.org/wiki/Behavior-driven_development Behavior-driven development]) profiling goes a long way.
*Use efficient Ruby idioms
 
: Program into the language rather than in the language.  Performance will suffer if you try to write your Ruby code like you would PHP, Perl, or any other language.  Learn the Ruby way of doing things.
=== Performance Guidelines<ref>http://blog.monitis.com/index.php/2012/02/08/20-ruby-performance-tips/</ref> ===
*Use interpolated strings instead of concatenated strings
----
: Interpolated strings are faster than concatenated strings in almost all interpreted languages; Ruby is no exception.  Using the << operator makes a method call which and method calls should be avoided when possible.
The key parameter on which a software application is rated is by its performance. It is the time taken by the application to respond to a user's request. Performance of ruby can be improved significantly by following certain coding guidelines, as below.
put “Hello there, #{name}!
 
vs.
*'''Avoid nesting loops more than three levels deep'''
puts “Hello there, ” << name = “!”
: Nesting affects the performance of the code proportionally with the increasing levels in loops. Limiting nesting to three levels is one good practice to keep the code's performance well.
*Destructive operations are faster
 
: Ruby’s in-place methods that modify the actual value instead of working on a copy of it are much faster, but be careful as they sometimes behave strangely (i.e., for!)
*'''Avoid unnecessary variable assignments'''
*Avoid unnecessary calls to uniq on arrays
: New programmers, often use unwanted variables in code.  A great example is when someone defines a variable to store a return value and then returns that variable; just return the value directly.
 
*'''Reduce usage of disk I/O'''
: Disk I/O is a very costly operation as far as computing is concerned. Keeping it to the minimal improves the application response time drastically. Using disk I/O, makes the application extremely slow. Using storage systems such as memcached reduces disk I/O operations to a great extent as lot of data is kept in memory. The speed improvement while using a memory caching system is tremendous.
 
*'''Use Ruby Enterprise Edition'''
: Ruby Enterprise edition provides up to [http://www.rubyenterpriseedition.com/faq.html#thirty_three_percent_mem_reduction 33% lower memory] usage.  Though, to get benefited by this performance one needs to follow their guidelines.
 
*'''Avoid method calls as much as possible'''
: Method calls are expensive operations in ruby. They should be avoided to keep up the performance of the application.
 
*'''Use interpolated strings instead of concatenated strings'''
: Concatenated strings calls a method to get executed. So, it affects the performance as it is one of the most frequently used operation. Its better to replace them with Interpolated strings which runs faster as it doesn't invoke a method call.
<pre>
put “Hello there, #{name}!”vs.puts “Hello there, ” << name = “!”
</pre>
 
*'''Destructive operations are faster'''
: Ruby’s in-place methods that which modifies the actual value than working on a copy of the data are much faster. But this should be handled carefully as original data gets disturbed.
 
*'''Avoid unnecessary calls to uniq on arrays'''
: In many cases methods are already calling uniq on an array and there’s no need for you to call it yet again.
: In many cases methods are already calling uniq on an array and there’s no need for you to call it yet again.
*For loops are faster than .each
 
: When you use .each you encounter per-request execution; for loops avoid this expensive operation.
*'''For loops are faster than .each'''
*Use x.blank? over x.nil? || x.empty?
: .each uses an enumeration object behind the scene which adds a delay in execution. Using for instead of .each would improve performance but for short loops only.<ref>http://stackoverflow.com/questions/6406112/why-are-ruby-method-calls-particularly-slow-in-comparison-to-other-languages</ref>
 
*'''Use x.blank? over x.nil? || x.empty?'''
: When using ActionPack there’s no need for x.nil? or x.empty?; x.blank? checks for both of these.
: When using ActionPack there’s no need for x.nil? or x.empty?; x.blank? checks for both of these.
*Avoid calls to parse_date and strftime
: Both of these are very expensive operations.  Use regular expressions when parsing out date/time components.
*Don’t use unnecessary block parameters
: If you won’t be using the parameter in the block don’t specify it in the parameter list.  Go through your code and ensure that any parameters declared are used or removed.
*Know your gems
: Not all libraries are created with performance in mind.  Many gems are slapped together to solve a particular problem that author was having.  Before you introduce a new gem into your performance-oriented production codebase be sure to perform thorough benchmarking and testing against other gems that perform the same tasks.
* Profile your code regularly
: If you profile you code regularly you’ll be able to tell if the latest change to the code will have an adverse effect on performance.  Integrate profiling into your testing process and make it automated to ensure that it’s not forgotten.  Like unit testing and BDD profiling goes a long way.
*Improve your algorithms before you try to improve your code
: Algorithmic improvements are almost always going to have more of an impact on the performance of your code than tweaks to the way your code is written will.  Make sure your algorithm is designed to be efficient and has no extraneous methods or calls.  Also, test for most frequent cases first and exit loops as soon as possible.
*Test the most frequently occurring case first
: When using if statements or a case statement always test the cases in the order that they occur most frequently.  This allows less code to run before a decision is made.  It may not seem like much but over several hundred or thousand runs through the decision logic you’ll notice a definite performance gain.
*Optimize the way you access global constants
: Be sure to precede a global constant with it’s namespace and the double colon operator (Namespace::constant_name) to reduce the time needed to query the library.
*Use explicit returns
: Although Ruby will automatically return the result of the last completed operation if no return value is provided you should use explicit return values.  Explicit returns are faster, especially in older Ruby versions such as 1.8.x.


=== Documentation Guidelines ===
*'''Avoid calls to parse_date and strftime'''
=== Layout Guidelines ===
: Both these calls are very expensive. using regular expressions would improve the time.
 
*'''Know your gems'''
: All libraries are not efficient. Many gems may need to be removed to problem to fix a problem with the code. This is a common scenario when many gems are installed. So performing bench marking and testing a gem with others that perform same task would help in picking the right gem.
 
*'''Improve your algorithms before you try to improve your code'''
: Algorithmic improvements results in evident improvements in performance of the code. It is always ideal to design an efficient algorithm without unwanted method calls.
 
*'''Test the most frequently occurring case first'''
: While using if statements or a case statement always test the cases that occur most frequently. This allows less code to run before a decision is made.  It may not seem like much but over several hundred or thousand runs through the decision logic you’ll notice a definite performance gain.
 
*'''Optimize the way you access global constants'''
: While accessing the global constants one should use namespace before the constants to avoid entire library search for the constant.
*'''Use explicit returns'''
: Even though the result of last operation is returned for a method, using explicit returns would speed up the code. Explicit returns are faster, especially in older Ruby versions such as 1.8.x.
 
=== Documentation Guidelines<ref>http://guides.rubyonrails.org/api_documentation_guidelines.html</ref> ===
----
 
Documentation comments<ref>http://www.jetbrains.com/ruby/webhelp/documenting-source-code-in-rubymine.html</ref> can be created in accordance with [http://rdoc.sourceforge.net/ RDoc] and [http://yardoc.org/ YARD] syntax. Note that RDoc highlighting in documentation comments can be turned enabled or disabled in the Appearance page of the editor settings.
 
The most common Documentation guidelines are listed below.
*Write simple, declarative sentences. Brevity is a plus: get to the point.
*Write in present tense: "Returns a hash that...", rather than "Returned a hash that..." or "Will return a hash that...".
*Start comments in upper case. Follow regular punctuation rules:
<pre>
# Declares an attribute reader backed by an internally-named
# instance variable.
def attr_internal_reader(*attrs)
  ...
end
</pre>
*Communicate to the reader the current way of doing things, both explicitly and implicitly. Use the idioms recommended in edge. Reorder sections to emphasize favored approaches if needed, etc. The documentation should be a model for best practices and canonical, modern Rails usage.
 
Documentation has to be concise but comprehensive. Explore and document edge cases.
 
=== Layout Guidelines<ref>http://www.caliban.org/ruby/rubyguide.shtml</ref> ===
----
Designing the layout of any application determines the readability factor for other developers.
Designing the layout of any application determines the readability factor for other developers.
Most followed order of code is as follows:
Most followed order of code is as follows:


<pre>
header block with author's name, Perforce Id tag and a brief description of what the program or library is for.
header block with author's name, Perforce Id tag and a brief description of what the program or library is for.
require statements
require statements
Line 102: Line 214:
class and module definitions
class and module definitions
main program section
main program section
</pre>
*'''Spreading Code Out and Lining it Up'''
:This is very important for readability. Basically the principle is to:
:*separate each component part by white space.
:*align everything meaningfully.
:As such one can easily scan up and down the code and see the patterns. This is very important not only for understanding the code, but also for looking for anomalies and as a tool for rationalizing and consolidating the code.
:Code that has a lot of 'noise' - a lot of unnecessary variation and untidiness - is code that one can waste a lot of time working on. Well written and formatted code is code that is easy and quick to work with. It is code that allows one to easily 'see the wood from the trees'.
== '''Code Analysis Tools''' ==
Ruby itself goes a long way towards helping developers write clear code.
*'''The Ruby debugger''' is a library loaded into Ruby at run-time.
This is done as follows:
<pre>
ruby -r debug [
            options
            ] [
            programfile
            ] [
            arguments
            ]
</pre>
The debugger can do all the usual things one would expect it to, such as set breakpoints, step into and over code, print out the call stack, etc.
While tools for the mainstream languages such as Java and C++ have reached a certain maturity, tools for Ruby are still growing. And they might be needed more and more as Ruby's usage spreads from early adopters to the early majority, and SLOC (Source Lines Of Code) continues to increase. Automatic tools<ref>http://www.ruby-toolbox.com/categories/code_metrics</ref> can be used to detect several types of problems including inconsistent style, long methods and repeated code.
*[http://github.com/roodi/roodi/tree/master '''Roodi'''] (Ruby Object Oriented Design Inferometer) - this parses Ruby code and warns about design issues from the list  configured, ie: Class line count check, for loop check, parameter number check, cyclomatic checks and 10 other checks
*[http://github.com/troessner/reek '''Reek'''] - similar in concept to Roodi
*[http://saikuro.rubyforge.org/ '''Saikuro'''] - designed to check cyclomatic complexity
*[http://ruby.sadi.st/Flog.html '''Flog'''] - created by Ryan Davis, this computes a score of code written: the higher the score is, the worse your code is. ABC metrics (Assignments, Branches and Calls) are taken into account to compute the score
*[http://www.harukizaemon.com/simian/ '''Simian'''] - a similarity analyzer, this can be used for duplication identification (a $99 license is needed for commercial use)
*[http://ruby.sadi.st/Flay.html '''Flay'''] - this is another free tool from Ryan Davis that finds structural similarities in code
[[File:Code Analysis Outputs.png|frame|none|alt=Code Analysis Tool Results|Code Analysis Tool Results]]
== '''Summary''' ==
Ruby developers should follow a certain criteria or guidelines during software development. Coding standards are set of rules, guidelines and regulations on the manner of writing a code that helps programmers and developers read and understand quickly the source code that conforms to style and help avoid introducing misunderstanding and faults.
Particularly in Ruby development, coding standards are extremely important; therefore Ruby developers should put an importance to them. This is because these standards offer higher uniformity and consistency when writing code by different programmers. This could result in a code that's simple to know and preserve, thus reducing the project’s overall expenses.
Some of the benefits of using coding standards are:
*Easy to understand and maintained
*Boost the code’s readability
*Maintainable applications
*Eradicates complexity
*Separate documents look more appropriate
== '''See Also''' ==
*http://www.caliban.org/ruby/rubyguide.shtml
*http://github.com/styleguide/ruby
*http://www.ruby-doc.org/docs/ProgrammingRuby/
*http://www.ruby-lang.org/en/documentation/
*http://en.wikibooks.org/wiki/Ruby_programming_language


== Code Analysis Tools ==
== '''References''' ==
== Summary ==
<references/>
== See Also ==
== References ==

Latest revision as of 20:24, 24 September 2013

Ruby Coding Guidelines

Ruby Coding Guidelines include best practices followed generally for most of the object oriented programming languages as Ruby is entirely 'Object Oriented'. Also known as 'Ruby Coding conventions', these are a set of guidelines that recommend programming style, practices and methods for each aspect of a piece of program written in Ruby.

Software programmers are highly recommended to follow these guidelines to help improve the readability of their source code and make software maintenance easier. Naming conventions, class and member design principles, maintainability, performance, documentation and layout are the important areas where these guidelines have to be followed. More important than the reasons for having a guideline is actually adhering to it consistently. Having a coding guideline documented and available means nothing if developers are not using it consistently.

Types of Guidelines

Coding guidelines in Ruby can be defined individually for major sections that code consists of. Naming , Class Design , Member Design , Maintainability, Performance, Documentation and Layout guidelines are illustrated below. These guidelines contain sections common to all of these as well as sections which apply to each one individually.

Naming Guidelines<ref>http://itsignals.cascadia.com.au/?p=7</ref>


Ruby uses the first character of the name to help it determine it’s intended use. The standard Ruby file extension is .rb, although many people working on UNIX-like systems don't bother with it for stand-alone scripts. Whether or not one uses it for scripts is up to them, but they will need to use it for library files or they will not be found by the interpreter.

  • Local Variables
Should use lowercase letter followed by other characters. Naming convention states that it is better to use underscores rather than camelBack for multiple word names, e.g. average, variable_xyz
  • Instance Variables
Instance variables are defined using the single "at" sign (@) followed by a name. It is suggested that a lowercase letter should succeed @, e.g. @color
  • Instance Methods
Method names should start with a lowercase letter, and may be followed by digits, underscores, and letters. The name should possibly be a verb e.g. move, display_details
  • Class Variables
Class variable names start with a double "at" sign (@@) and may be followed by digits, underscores, and letters, e.g. @@color
  • Constant
Constant names usually start with an uppercase letter followed by other characters. Constant objects are by convention named using all uppercase letters and underscores between words, e.g. THIS_IS_A_CONSTANT
  • Class and Module
Class names are recommended to be be nouns. In the case of modules, it's harder to make a clear recommendation. The names of mix-ins (which are just modules), however, should probably be adjectives, such as the standard Enumerable and Comparable modules. Class and module names starts with an uppercase letter, by convention they are named using MixedCase, e.g. module Encryption, class MixedCase
  • Global Variables
Starts with a dollar ($) sign followed by other characters, e.g. $global

Considering customer order information as the data being used for an application, below naming guidelines give an idea of good class/table/file names.

  • Model Naming Convention
Table: orders
Class: Order
File: /app/models/order.rb
Primary Key: id
Foreign Key: customer_id
Link Tables: items_orders
  • Controller Naming Convention
Class: OrdersController
File: /app/controllers/orders_controller.rb
Layout: /app/layouts/orders.html.erb
  • View Naming Convention
Helper: /app/helpers/orders_helper.rb
Helper Module: OrdersHelper
Views: /app/views/orders/… (list.html.erb for example)
  • Tests Naming Convention
Unit: /test/unit/order_test.rb
Functional: /test/functional/orders_controller_test.rb
Fixtures: /test/fixtures/orders.yml

Class Design Guidelines


A class in Ruby always starts with the keyword class followed by the name of the class. The name should always be in initial capitals. Class Customer can be displayed as:

class Customer
end

A class is terminated by using the keyword end. All the data members in the class are between the class definition and the end keyword.

Ruby blurs the distinction between design and implementation. Ideas that have to be expressed at the design level in other languages can be implemented directly in Ruby. To help in this process, Ruby has support for some design-level strategies. These strategies can be used to design classes accordingly as suitable for different types of applications.

  • The Visitor pattern is a way of traversing a collection without having to know the internal organization of that collection.
  • Delegation is a way of composing classes more flexibly and dynamically than can be done using standard inheritance.
  • The Singleton pattern is a way of ensuring that only one instantiation of a particular class exists at a time.
  • The Observer pattern implements a protocol allowing one object to notify a set of interested objects when certain changes have occurred.

Normally, all four of these strategies require explicit code each time they're implemented. With Ruby, they can be abstracted into a library and reused freely and transparently.

Member Design Guidelines


While defining class members, it is very important to keep in mind the access restrictions. Scope and life-time of class members are different for different restrictions, as illustrated below.

public
totally accessible.
protected
accessible only by instances of class and direct descendants. Even through hasA relationships. (see below)
private
accessible only by instances of class (must be called nekkid no “self.” or anything else).
class A
  # Restriction used w/o arguments set the default access control.
  protected

  def protected_method
    # nothing
  end
end

class B < A
  def test_protected
    myA = A.new
    myA.protected_method
  end

  # Used with arguments, sets the access of the named methods and constants.
  public :test_protected
end

b = B.new.test_protected

Maintainability Guidelines


Maintainability guidelines are important to programmers for a number of reasons:

  • 40%-80% of the lifetime cost of a piece of software goes to maintenance.
  • Hardly any software is maintained for its whole life by the original author.
  • Code conventions improve the readability of the software, allowing engineers to understand new code more quickly and thoroughly.
  • If you ship your source code as a product, you need to make sure it is as well packaged and clean as any other product you create.

The following guidelines are to be followed to improve the software maintainability

  • Profile your code regularly
If you profile your code regularly you’ll be able to tell if the latest change to the code will have an adverse effect on performance. Integrate profiling into your testing process and make it automated to ensure that it’s not forgotten. Like unit testing and BDD(Behavior-driven development) profiling goes a long way.

Performance Guidelines<ref>http://blog.monitis.com/index.php/2012/02/08/20-ruby-performance-tips/</ref>


The key parameter on which a software application is rated is by its performance. It is the time taken by the application to respond to a user's request. Performance of ruby can be improved significantly by following certain coding guidelines, as below.

  • Avoid nesting loops more than three levels deep
Nesting affects the performance of the code proportionally with the increasing levels in loops. Limiting nesting to three levels is one good practice to keep the code's performance well.
  • Avoid unnecessary variable assignments
New programmers, often use unwanted variables in code. A great example is when someone defines a variable to store a return value and then returns that variable; just return the value directly.
  • Reduce usage of disk I/O
Disk I/O is a very costly operation as far as computing is concerned. Keeping it to the minimal improves the application response time drastically. Using disk I/O, makes the application extremely slow. Using storage systems such as memcached reduces disk I/O operations to a great extent as lot of data is kept in memory. The speed improvement while using a memory caching system is tremendous.
  • Use Ruby Enterprise Edition
Ruby Enterprise edition provides up to 33% lower memory usage. Though, to get benefited by this performance one needs to follow their guidelines.
  • Avoid method calls as much as possible
Method calls are expensive operations in ruby. They should be avoided to keep up the performance of the application.
  • Use interpolated strings instead of concatenated strings
Concatenated strings calls a method to get executed. So, it affects the performance as it is one of the most frequently used operation. Its better to replace them with Interpolated strings which runs faster as it doesn't invoke a method call.
put “Hello there, #{name}!”vs.puts “Hello there, ” << name = “!”
  • Destructive operations are faster
Ruby’s in-place methods that which modifies the actual value than working on a copy of the data are much faster. But this should be handled carefully as original data gets disturbed.
  • Avoid unnecessary calls to uniq on arrays
In many cases methods are already calling uniq on an array and there’s no need for you to call it yet again.
  • For loops are faster than .each
.each uses an enumeration object behind the scene which adds a delay in execution. Using for instead of .each would improve performance but for short loops only.<ref>http://stackoverflow.com/questions/6406112/why-are-ruby-method-calls-particularly-slow-in-comparison-to-other-languages</ref>
  • Use x.blank? over x.nil? || x.empty?
When using ActionPack there’s no need for x.nil? or x.empty?; x.blank? checks for both of these.
  • Avoid calls to parse_date and strftime
Both these calls are very expensive. using regular expressions would improve the time.
  • Know your gems
All libraries are not efficient. Many gems may need to be removed to problem to fix a problem with the code. This is a common scenario when many gems are installed. So performing bench marking and testing a gem with others that perform same task would help in picking the right gem.
  • Improve your algorithms before you try to improve your code
Algorithmic improvements results in evident improvements in performance of the code. It is always ideal to design an efficient algorithm without unwanted method calls.
  • Test the most frequently occurring case first
While using if statements or a case statement always test the cases that occur most frequently. This allows less code to run before a decision is made. It may not seem like much but over several hundred or thousand runs through the decision logic you’ll notice a definite performance gain.
  • Optimize the way you access global constants
While accessing the global constants one should use namespace before the constants to avoid entire library search for the constant.
  • Use explicit returns
Even though the result of last operation is returned for a method, using explicit returns would speed up the code. Explicit returns are faster, especially in older Ruby versions such as 1.8.x.

Documentation Guidelines<ref>http://guides.rubyonrails.org/api_documentation_guidelines.html</ref>


Documentation comments<ref>http://www.jetbrains.com/ruby/webhelp/documenting-source-code-in-rubymine.html</ref> can be created in accordance with RDoc and YARD syntax. Note that RDoc highlighting in documentation comments can be turned enabled or disabled in the Appearance page of the editor settings.


The most common Documentation guidelines are listed below.

  • Write simple, declarative sentences. Brevity is a plus: get to the point.
  • Write in present tense: "Returns a hash that...", rather than "Returned a hash that..." or "Will return a hash that...".
  • Start comments in upper case. Follow regular punctuation rules:
# Declares an attribute reader backed by an internally-named 
# instance variable.
def attr_internal_reader(*attrs)
  ...
end
  • Communicate to the reader the current way of doing things, both explicitly and implicitly. Use the idioms recommended in edge. Reorder sections to emphasize favored approaches if needed, etc. The documentation should be a model for best practices and canonical, modern Rails usage.

Documentation has to be concise but comprehensive. Explore and document edge cases.

Layout Guidelines<ref>http://www.caliban.org/ruby/rubyguide.shtml</ref>


Designing the layout of any application determines the readability factor for other developers. Most followed order of code is as follows:

header block with author's name, Perforce Id tag and a brief description of what the program or library is for.
require statements
include statements
class and module definitions
main program section
  • Spreading Code Out and Lining it Up
This is very important for readability. Basically the principle is to:
  • separate each component part by white space.
  • align everything meaningfully.
As such one can easily scan up and down the code and see the patterns. This is very important not only for understanding the code, but also for looking for anomalies and as a tool for rationalizing and consolidating the code.
Code that has a lot of 'noise' - a lot of unnecessary variation and untidiness - is code that one can waste a lot of time working on. Well written and formatted code is code that is easy and quick to work with. It is code that allows one to easily 'see the wood from the trees'.

Code Analysis Tools

Ruby itself goes a long way towards helping developers write clear code.

  • The Ruby debugger is a library loaded into Ruby at run-time.

This is done as follows:

ruby -r debug [
            options
            ] [
            programfile
            ] [
            arguments
            ]

The debugger can do all the usual things one would expect it to, such as set breakpoints, step into and over code, print out the call stack, etc.

While tools for the mainstream languages such as Java and C++ have reached a certain maturity, tools for Ruby are still growing. And they might be needed more and more as Ruby's usage spreads from early adopters to the early majority, and SLOC (Source Lines Of Code) continues to increase. Automatic tools<ref>http://www.ruby-toolbox.com/categories/code_metrics</ref> can be used to detect several types of problems including inconsistent style, long methods and repeated code.

  • Roodi (Ruby Object Oriented Design Inferometer) - this parses Ruby code and warns about design issues from the list configured, ie: Class line count check, for loop check, parameter number check, cyclomatic checks and 10 other checks
  • Reek - similar in concept to Roodi
  • Saikuro - designed to check cyclomatic complexity
  • Flog - created by Ryan Davis, this computes a score of code written: the higher the score is, the worse your code is. ABC metrics (Assignments, Branches and Calls) are taken into account to compute the score
  • Simian - a similarity analyzer, this can be used for duplication identification (a $99 license is needed for commercial use)
  • Flay - this is another free tool from Ryan Davis that finds structural similarities in code
Code Analysis Tool Results
Code Analysis Tool Results

Summary

Ruby developers should follow a certain criteria or guidelines during software development. Coding standards are set of rules, guidelines and regulations on the manner of writing a code that helps programmers and developers read and understand quickly the source code that conforms to style and help avoid introducing misunderstanding and faults.

Particularly in Ruby development, coding standards are extremely important; therefore Ruby developers should put an importance to them. This is because these standards offer higher uniformity and consistency when writing code by different programmers. This could result in a code that's simple to know and preserve, thus reducing the project’s overall expenses.

Some of the benefits of using coding standards are:

  • Easy to understand and maintained
  • Boost the code’s readability
  • Maintainable applications
  • Eradicates complexity
  • Separate documents look more appropriate

See Also

References

<references/>