Use a consistent structure in the class definition.
Class Person
# Extend and include the Go
extend Somemodule
include Anothermodule
# constants are 5/>some_constant =
# Afterwards we have attribute macros
Attr_reader:name # followed by the other
macros (if a NY)
Validates:name
# public class methods are next with line
def self.some_method
end
# followed B Y Public instance Methods
def Some_method end
# Protected and private methods the are grouped near the
end
protected
def some_protected_method
end
private
def some_private_method
End
Prefer to use module, rather than classes with only class methods. Categories should be used only when creating instances that are reasonable.
# Bad
class SomeClass
def self.some_method
# body omitted
end
def self.some_other_method
End
End
# good
module SomeClass
module_function
def some_method
# body omitted
end
def some_other_method
End
When you want to turn the instance method of a module into a class method, the preference for using module_function is better than extend self.
# bad
module Utilities
extend self
def parse_something (string) # does stuff here-end
def Other_utility_method (number, String)
# do some the stuff
end
# good
module Utilities
module_function
def parse_something (string) # do stuff-here-end
def other_utility_method ( Number, String)
# do some more stuff
end
When designing class hierarchies make sure this they conform to the
Liskov substitution principle.
Ensure that they conform to the Liskov substitution principle principles when designing class levels. (Translator Note: The LSP principle probably means: if an instance of the parent class is referenced in a function, it must be replaced with an instance of its subclass, and the basic function of the function will not change.) (Although functionality is allowed to be extended))
Liskov substitution principle: subtypes must be able to replace their base types <br/>
1. If each type is a T1 object O1, there is a type of T2 object O2, so that all program P defined by T1 when all the object O1 are substituted for O2, the behavior of program P is not changed, then the type T2 is the subtype of type T1. <br/>
2. In other words, if a software entity uses a base class, it must apply to its subclasses, and it cannot detect the difference between the base class object and the subclass object at all. The base class can be truly reused only if the derived class replaces the base class while the functionality of the software entity has not changed. <br/>
3. The principle of the Richter substitution, proposed by Barbar Liskov (Barbara Richter), is the cornerstone of succession reuse. <br/>
4. Whether an inheritance conforms to the principle of the Richter substitution, it is possible to determine whether the inheritance is reasonable (whether it is hidden or flawed).
Try to make your class as robust as possible [SOLID] (http://en.wikipedia.org/wiki/solid_object-oriented_design\). (
Always provide a to_s method for your own class to represent objects contained by this class (instance) object.
Class Person
attr_reader:first_name,: last_name
def initialize (first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def to_s
' # @first_name # @last_name
End
Use the attr feature member to define accessors or modifier methods for individual instance variables.
# bad
class person
def initialize (first_name, last_name)
@first_name = first_name
@last_name = last_ Name
end
def first_name
@first_name
end
def last_name
@last_name
End
# Good
class person
attr_reader:first_name,: last_name
def initialize (first_name, last_name)
@first_name = first_name
@last_name = last_name
End
Avoid using attr. Use Attr_reader and attr_accessor as substitutes.
# bad-creates A single attribute accessor (deprecated in 1.9)
attr:something, True
Attr:one,: Two,: three # behaves as Attr_reader
# good
attr_accessor:something
Attr_reader:one, two,: three
Consider using struct.new, which can define some trivial accessors,
Constructor (constructors) and comparison (comparison) operations.
# Good
class person
attr_reader:first_name,: last_name
def initialize (first_name, last_name)
@first _name = first_name
@last_name = last_name
end
# better
class Person < Struct.new (: First_ Name,: last_name) End
Consider using Struct.new, which defines the trivial accessors (accessors), constructors (constructor), and comparison operators (comparison operators) for you.
# Good
class person
attr_accessor:first_name,: last_name
def initialize (first_name, last_name)
@first_name = first_name
@last_name = last_name
end
# better person
= struct.new (: first_ Name,: last_name) do end
Don't go extend a struct.new-it's already a new class. Extending it creates an extra class hierarchy
And it could make a weird mistake if the file was loaded multiple times.
Consider adding a factory method to provide a flexible way to create a specific class instance.
Class Person
def self.create (Potions_hash)
# body omitted
end
Duck type (duck-typing) is superior to inheritance.
# Bad
class Animal
# abstract method
def speak
end
# Extend Superclass
class Duck & Lt Animal
def speak
puts ' quack! Quack '
end
# Extend Superclass
class Dog < Animal
def speak
puts ' bau! bau! '
End
# Good
class Duck
def speak
puts ' quack! Quack '
end
class Dog
def speak
puts ' bau! bau! '
End End
Avoid the usage of class (@@) variables due to their "nasty" behavior
In inheritance.
Avoid using class variables (@@) because of their annoying inheritance habits (you can also modify the class variables of the parent class in subclasses).
Class Parent
@ @class_var = ' Parent '
def Self.print_class_var
puts @ @class_var
end
class Child < Parent
@ @class_var = ' child '
end
Parent.print_class_var # => 'll print ' child '
As the example above sees, all subclasses share class variables, and you can modify class variables directly, and it's a better idea to use class instance variables at this point.
Assign them the right visibility (private, protected) based on the purpose of the method, and do not let all methods be public (this is the default setting). This is Ruby, not Python.
Public, protected, and private visibility keywords should have the same indentation as their (specified) methods. And leave a space between the different visibility keys.
Class SomeClass
def public_method
#
... End
Private
def private_method
#
... End
def another_private_method
#
... End End
Use Def Self.method to define a single instance method. This makes the code easier because the class name is not duplicated when the code is refactored.
Class TestClass
# bad
def testclass.some_method
# body omitted
end
# good
def self.some_other _method
# Body omitted
end
# Also possible and convenient the have to define many
S.
Class << self
def first_method
# body omitted
end
def second_method_etc
# body omitted< C17/>end End-
class singletontest
def size
end
test1 = Singletontest.new
test2 = singletontest.new
def test2.size
ten
end
Test1.size # => 25
Test2.size # => 10
In this case, test1 and test2 belong to the same category, but test2 have a redefined size method, so the behavior of the two is different. The method of giving only one object is called a single instance method (singleton methods).