object_dojo 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +32 -0
- data/README.markdown +32 -0
- data/Rakefile +6 -0
- data/bin/dojo +33 -0
- data/config/rules.yml +7 -0
- data/lib/class_structure.rb +26 -0
- data/lib/class_validator.rb +29 -0
- data/lib/dojo.rb +18 -0
- data/lib/extensions.rb +8 -0
- data/lib/object_dojo/version.rb +3 -0
- data/lib/rules.rb +7 -0
- data/lib/rules/avoid_accessor.rb +10 -0
- data/lib/rules/avoid_keyword.rb +13 -0
- data/lib/rules/class_line_limit.rb +13 -0
- data/lib/rules/first_class_collections.rb +13 -0
- data/lib/rules/instance_variable_limit.rb +15 -0
- data/lib/rules/method_chaining_limit.rb +15 -0
- data/lib/rules/method_indentation.rb +25 -0
- data/object_dojo.gemspec +23 -0
- data/spec/class_structure_spec.rb +161 -0
- data/spec/dojo_spec.rb +4 -0
- data/spec/rules/avoid_accessor_spec.rb +78 -0
- data/spec/rules/avoid_keyword_spec.rb +22 -0
- data/spec/rules/class_line_limit_spec.rb +28 -0
- data/spec/rules/first_class_collections_spec.rb +20 -0
- data/spec/rules/instance_variable_limit_spec.rb +32 -0
- data/spec/rules/method_chaining_limit_spec.rb +28 -0
- data/spec/rules/method_indentation_spec.rb +72 -0
- data/spec/spec_helper.rb +7 -0
- metadata +95 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
object_dojo (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
metaclass (0.0.1)
|
11
|
+
mocha (0.10.0)
|
12
|
+
metaclass (~> 0.0.1)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rspec (2.8.0)
|
15
|
+
rspec-core (~> 2.8.0)
|
16
|
+
rspec-expectations (~> 2.8.0)
|
17
|
+
rspec-mocks (~> 2.8.0)
|
18
|
+
rspec-core (2.8.0)
|
19
|
+
rspec-expectations (2.8.0)
|
20
|
+
diff-lcs (~> 1.1.2)
|
21
|
+
rspec-mocks (2.8.0)
|
22
|
+
trollop (1.16.2)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
mocha
|
29
|
+
object_dojo!
|
30
|
+
rake
|
31
|
+
rspec
|
32
|
+
trollop
|
data/README.markdown
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
ObjectDojo is a utility to improve your Object oriented programming skills using rules described in the article "Object Calisthenics" by JeffBay:
|
2
|
+
|
3
|
+
[www.xpteam.com/jeff/writings/objectcalisthenics.rtf](www.xpteam.com/jeff/writings/objectcalisthenics.rtf)
|
4
|
+
|
5
|
+
### The Rules
|
6
|
+
|
7
|
+
1. One level of indentation per method
|
8
|
+
2. Don’t use the ELSE keyword
|
9
|
+
3. Wrap all primitives and Strings
|
10
|
+
4. First class collections
|
11
|
+
5. One dot per line
|
12
|
+
6. Don’t abbreviate
|
13
|
+
7. Keep all entities small
|
14
|
+
8. No classes with more than two instance variables
|
15
|
+
9. No getters/setters/properties
|
16
|
+
|
17
|
+
### Usage
|
18
|
+
|
19
|
+
Run the command line utility dojo in your current project folder.
|
20
|
+
|
21
|
+
myapp$ dojo
|
22
|
+
|
23
|
+
### Configure
|
24
|
+
|
25
|
+
The rules can be configured by passing command line options. To get the full list of command line options
|
26
|
+
|
27
|
+
$ dojo -h
|
28
|
+
|
29
|
+
#### Supported languages
|
30
|
+
|
31
|
+
The current version supports only Ruby.
|
32
|
+
Support for other languages like Java, C# and Python will be added in the future.
|
data/Rakefile
ADDED
data/bin/dojo
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'dojo'
|
7
|
+
require 'yaml'
|
8
|
+
require 'trollop'
|
9
|
+
|
10
|
+
default_options = YAML::load_file(File.expand_path(File.dirname(__FILE__) + '/../config/rules.yml'))['rules'].symbolize_keys!
|
11
|
+
|
12
|
+
options = Trollop::options do
|
13
|
+
version "object_dojo"
|
14
|
+
banner <<-EOS
|
15
|
+
ObjectDojo is a utility to practice Object oriented programming.
|
16
|
+
It checks the rules described in the article "Object Calisthenics" by Jeff Bay.
|
17
|
+
|
18
|
+
www.xpteam.com/jeff/writings/objectcalisthenics.rtf
|
19
|
+
|
20
|
+
Usage:
|
21
|
+
dojo [options] <path>+
|
22
|
+
where [options] are:
|
23
|
+
EOS
|
24
|
+
opt :max_indent, "Level of indentation per method", default: default_options[:max_indent]
|
25
|
+
opt :avoid_keywords, "Keywords to avoid in code", :type => String, default: default_options[:avoid_keywords]
|
26
|
+
opt :max_collections, "Number of first class collections in class", default: default_options[:max_collections]
|
27
|
+
opt :max_chaining, "Number of dots or chained method calls per line", default: default_options[:max_chaining]
|
28
|
+
opt :max_lines, "Lines of code per class", default: default_options[:max_lines]
|
29
|
+
opt :max_instance_vars, "Number of instance variables per class", default: default_options[:max_instance_vars]
|
30
|
+
end
|
31
|
+
|
32
|
+
dojo = Dojo.new(ARGV.last)
|
33
|
+
dojo.validate(default_options.merge(options))
|
data/config/rules.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class ClassStructure
|
2
|
+
def initialize(code)
|
3
|
+
@code = code
|
4
|
+
end
|
5
|
+
|
6
|
+
def instance_variables
|
7
|
+
@code.scan(/\s+\@\w+/).map {|name| name.strip.sub('@','')}.uniq
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_names
|
11
|
+
@code.scan(/def \w+/).map {|name| name.sub('def ','')}.uniq
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_accessor_method?
|
15
|
+
all_instance_variables = instance_variables
|
16
|
+
method_names.any? {|method_name| instance_variables.include?(method_name.gsub('=',''))}
|
17
|
+
end
|
18
|
+
|
19
|
+
def line_count
|
20
|
+
@code.split("\n").reject{|line| line.strip.size==0}.size
|
21
|
+
end
|
22
|
+
|
23
|
+
def collection_count
|
24
|
+
@code.scan(/\s+@\w+\s*\=\s*(\[.*?\]|\{.*?\}|Array\.new|Set\.new|Hash\.new)/).size
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ClassValidator
|
2
|
+
def initialize(file, options={})
|
3
|
+
@file = file
|
4
|
+
@options = options
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate
|
8
|
+
code = File.open(@file).read
|
9
|
+
rules.each do |rule|
|
10
|
+
next if rule.valid?(code)
|
11
|
+
puts "#{@file}: #{rule.message}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def rules
|
18
|
+
options = @options
|
19
|
+
[
|
20
|
+
MethodIndentation.new(options[:max_indent]),
|
21
|
+
*options[:avoid_keywords].split(',').map {|keyword| AvoidKeyword.new(keyword)},
|
22
|
+
FirstClassCollections.new(options[:max_collections]),
|
23
|
+
MethodChainingLimit.new(options[:max_chaining]),
|
24
|
+
ClassLineLimit.new(options[:max_lines]),
|
25
|
+
InstanceVariableLimit.new(options[:max_instance_vars]),
|
26
|
+
AvoidAccessor.new
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
data/lib/dojo.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'class_structure'
|
2
|
+
require 'class_validator'
|
3
|
+
require 'rules'
|
4
|
+
require 'extensions'
|
5
|
+
|
6
|
+
class Dojo
|
7
|
+
def initialize(dir, file_filter = "**/*.rb")
|
8
|
+
@dir = dir
|
9
|
+
@file_filter = file_filter
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate(options)
|
13
|
+
Dir.glob("#{@dir}/#{@file_filter}").each do |file|
|
14
|
+
validator = ClassValidator.new(file, options)
|
15
|
+
validator.validate
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/extensions.rb
ADDED
data/lib/rules.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class InstanceVariableLimit
|
2
|
+
|
3
|
+
def initialize(max)
|
4
|
+
@max = max
|
5
|
+
end
|
6
|
+
|
7
|
+
def valid?(code)
|
8
|
+
class_structure = ClassStructure.new(code)
|
9
|
+
class_structure.instance_variables.size <= @max
|
10
|
+
end
|
11
|
+
|
12
|
+
def message
|
13
|
+
"has more than #{@max} instance variables"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class MethodIndentation
|
2
|
+
TABS = 2
|
3
|
+
|
4
|
+
def initialize(max)
|
5
|
+
@max = max + 2 # including class and def indent
|
6
|
+
end
|
7
|
+
|
8
|
+
def valid?(method)
|
9
|
+
max_indent(method) <= @max
|
10
|
+
end
|
11
|
+
|
12
|
+
def message
|
13
|
+
"indentation is more than #{@max} levels"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def max_indent(code)
|
19
|
+
indents = code.split("\n").collect do |line|
|
20
|
+
match = line.match(/^(\s*)/)
|
21
|
+
match ? match[1].length/TABS : 0
|
22
|
+
end
|
23
|
+
indents.max - indents.min
|
24
|
+
end
|
25
|
+
end
|
data/object_dojo.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "object_dojo/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "object_dojo"
|
7
|
+
s.version = ObjectDojo::VERSION
|
8
|
+
s.authors = ["Sathish"]
|
9
|
+
s.email = ["sathish316@gmail.com"]
|
10
|
+
s.homepage = "http://www.github.com/sathish316/object_dojo"
|
11
|
+
s.summary = %q{ObjectDojo is a utility to improve your Object oriented programming skills using rules described in the article "Object Calisthenics" by JeffBay}
|
12
|
+
s.description = %q{ObjectDojo is a utility to improve your Object oriented programming skills using rules described in the article "Object Calisthenics" by JeffBay}
|
13
|
+
s.rubyforge_project = "object_dojo"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ClassStructure do
|
4
|
+
describe "instance variables" do
|
5
|
+
it "should return unique instance variable names" do
|
6
|
+
class_structure = ClassStructure.new <<-CODE
|
7
|
+
class Person
|
8
|
+
def initialize(first, last)
|
9
|
+
@first, @last = first, last
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
@first + @last
|
14
|
+
end
|
15
|
+
end
|
16
|
+
CODE
|
17
|
+
|
18
|
+
class_structure.instance_variables.sort.should == ['first', 'last']
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be empty if there are no instance variables" do
|
22
|
+
class_structure = ClassStructure.new <<-CODE
|
23
|
+
class Person
|
24
|
+
end
|
25
|
+
CODE
|
26
|
+
class_structure.instance_variables.should be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not include class variables" do
|
30
|
+
class_structure = ClassStructure.new <<-CODE
|
31
|
+
class Person
|
32
|
+
@@count = 0
|
33
|
+
end
|
34
|
+
CODE
|
35
|
+
class_structure.instance_variables.should be_empty
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "method names" do
|
40
|
+
it "should return unique method names" do
|
41
|
+
class_structure = ClassStructure.new <<-CODE
|
42
|
+
class Person
|
43
|
+
def foo
|
44
|
+
end
|
45
|
+
|
46
|
+
def bar
|
47
|
+
end
|
48
|
+
|
49
|
+
def first
|
50
|
+
@first
|
51
|
+
end
|
52
|
+
|
53
|
+
def last
|
54
|
+
@last
|
55
|
+
end
|
56
|
+
end
|
57
|
+
CODE
|
58
|
+
|
59
|
+
class_structure.method_names.should == ['foo', 'bar', 'first', 'last']
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be empty if there are no methods" do
|
63
|
+
class_structure = ClassStructure.new <<-CODE
|
64
|
+
class Person
|
65
|
+
attr_accessor :first, :last
|
66
|
+
end
|
67
|
+
CODE
|
68
|
+
|
69
|
+
class_structure.method_names.should be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "has accessor method" do
|
74
|
+
it "should be true if there are getter methods" do
|
75
|
+
class_structure = ClassStructure.new <<-CODE
|
76
|
+
class Person
|
77
|
+
def name
|
78
|
+
@name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
CODE
|
82
|
+
|
83
|
+
class_structure.should have_accessor_method
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be true if there are setter methods" do
|
87
|
+
class_structure = ClassStructure.new <<-CODE
|
88
|
+
class Person
|
89
|
+
attr_accessor :first, :last
|
90
|
+
def name=(name)
|
91
|
+
@name = name
|
92
|
+
end
|
93
|
+
end
|
94
|
+
CODE
|
95
|
+
|
96
|
+
class_structure.should have_accessor_method
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should be false if there are no accessor methods" do
|
100
|
+
class_structure = ClassStructure.new <<-CODE
|
101
|
+
class Person
|
102
|
+
def name
|
103
|
+
@first + @last
|
104
|
+
end
|
105
|
+
end
|
106
|
+
CODE
|
107
|
+
|
108
|
+
class_structure.should_not have_accessor_method
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "collection count" do
|
113
|
+
it "should count the number of Arrays" do
|
114
|
+
class_structure = ClassStructure.new <<-CODE
|
115
|
+
@foo = []
|
116
|
+
@bar=[1,2,3]
|
117
|
+
CODE
|
118
|
+
class_structure.collection_count.should == 2
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should count the number of Hashes" do
|
122
|
+
class_structure = ClassStructure.new <<-CODE
|
123
|
+
@foo = {}
|
124
|
+
@bar={a: 1, b: 2}
|
125
|
+
@baz = {'a' => 1, 'b' => 2}
|
126
|
+
CODE
|
127
|
+
class_structure.collection_count.should == 3
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should count the number of Arrays declared using new" do
|
131
|
+
class_structure = ClassStructure.new <<-CODE
|
132
|
+
@foo = []
|
133
|
+
@bar=Array.new(5)
|
134
|
+
CODE
|
135
|
+
class_structure.collection_count.should == 2
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should count the number of Hashes declared using new" do
|
139
|
+
class_structure = ClassStructure.new <<-CODE
|
140
|
+
@bar=Hash.new
|
141
|
+
CODE
|
142
|
+
class_structure.collection_count.should == 1
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should count the number of Sets declared using new" do
|
146
|
+
class_structure = ClassStructure.new <<-CODE
|
147
|
+
@foo = Set.new
|
148
|
+
@bar=Set.new
|
149
|
+
CODE
|
150
|
+
class_structure.collection_count.should == 2
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should count only instance collections" do
|
154
|
+
class_structure = ClassStructure.new <<-CODE
|
155
|
+
@foo = []
|
156
|
+
@@bar = []
|
157
|
+
CODE
|
158
|
+
class_structure.collection_count.should == 1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/spec/dojo_spec.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe AvoidAccessor do
|
4
|
+
let(:rule) {AvoidAccessor.new}
|
5
|
+
|
6
|
+
it "should be valid if there are no accessors" do
|
7
|
+
rule.should be_valid <<-CODE
|
8
|
+
class Foo
|
9
|
+
def initialize(x,y)
|
10
|
+
@x = x
|
11
|
+
@y = y
|
12
|
+
end
|
13
|
+
end
|
14
|
+
CODE
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be invalid if attr_reader is used" do
|
18
|
+
rule.should_not be_valid <<-CODE
|
19
|
+
class Foo
|
20
|
+
attr_reader :x
|
21
|
+
def initialize(x)
|
22
|
+
@x = x
|
23
|
+
end
|
24
|
+
end
|
25
|
+
CODE
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be invalid if attr_writer is used" do
|
29
|
+
rule.should_not be_valid <<-CODE
|
30
|
+
class Foo
|
31
|
+
attr_writer :x
|
32
|
+
def initialize(x)
|
33
|
+
@x = x
|
34
|
+
end
|
35
|
+
end
|
36
|
+
CODE
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be invalid if attr_accessor is used" do
|
40
|
+
rule.should_not be_valid <<-CODE
|
41
|
+
class Foo
|
42
|
+
attr_accessor :x
|
43
|
+
def initialize(x)
|
44
|
+
@x = x
|
45
|
+
end
|
46
|
+
end
|
47
|
+
CODE
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be invalid if getter is used" do
|
51
|
+
rule.should_not be_valid <<-CODE
|
52
|
+
class Foo
|
53
|
+
def initialize(value)
|
54
|
+
@value = value
|
55
|
+
end
|
56
|
+
|
57
|
+
def value
|
58
|
+
@value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
CODE
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be invalid if writer is used" do
|
65
|
+
rule.should_not be_valid <<-CODE
|
66
|
+
class Foo
|
67
|
+
def initialize(value)
|
68
|
+
@value = value
|
69
|
+
end
|
70
|
+
|
71
|
+
def value=(value)
|
72
|
+
@value = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
CODE
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe AvoidKeyword do
|
4
|
+
let(:rule) {AvoidKeyword.new('else')}
|
5
|
+
|
6
|
+
it "should be invalid if keyword used in code" do
|
7
|
+
rule.should_not be_valid <<-CODE
|
8
|
+
if dojo
|
9
|
+
:code
|
10
|
+
else
|
11
|
+
:play_games
|
12
|
+
end
|
13
|
+
CODE
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be valid if keyword is not used in code" do
|
17
|
+
rule.should be_valid <<-CODE
|
18
|
+
return :code if dojo
|
19
|
+
:play_games
|
20
|
+
CODE
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe ClassLineLimit do
|
4
|
+
let(:rule) {ClassLineLimit.new(5)}
|
5
|
+
|
6
|
+
it "should be valid if max length is not exceeded" do
|
7
|
+
rule.should be_valid <<-CODE
|
8
|
+
class Foo
|
9
|
+
|
10
|
+
def initialize(bar)
|
11
|
+
@bar = bar
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
CODE
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be invalid if max length is exceeded" do
|
19
|
+
rule.should_not be_valid <<-CODE
|
20
|
+
class Foo
|
21
|
+
def initialize(bar, baz)
|
22
|
+
@bar = bar
|
23
|
+
@baz = baz
|
24
|
+
end
|
25
|
+
end
|
26
|
+
CODE
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FirstClassCollections do
|
4
|
+
let(:rule) {FirstClassCollections.new(1)}
|
5
|
+
|
6
|
+
it "should be invalid if there is more than 1 collection" do
|
7
|
+
ClassStructure.any_instance.stubs(:collection_count).returns(2)
|
8
|
+
rule.should_not be_valid <<-CODE
|
9
|
+
@foo = []
|
10
|
+
@bar = []
|
11
|
+
CODE
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be valid if there is <= 1 collection" do
|
15
|
+
ClassStructure.any_instance.stubs(:collection_count).returns(1)
|
16
|
+
rule.should be_valid <<-CODE
|
17
|
+
@foo = [1,2,3]
|
18
|
+
CODE
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe InstanceVariableLimit do
|
4
|
+
let(:rule) {InstanceVariableLimit.new(2)}
|
5
|
+
|
6
|
+
it "should be invalid if limit is exceeded" do
|
7
|
+
rule.should_not be_valid <<-CODE
|
8
|
+
class Foo
|
9
|
+
def initialize(x,y,z)
|
10
|
+
@x = x
|
11
|
+
@y = y
|
12
|
+
@z = @x * @y
|
13
|
+
end
|
14
|
+
end
|
15
|
+
CODE
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be valid if limit is not exceeded" do
|
19
|
+
rule.should be_valid <<-CODE
|
20
|
+
class Foo
|
21
|
+
def initialize(x,y,z)
|
22
|
+
@x = x
|
23
|
+
@y = y
|
24
|
+
end
|
25
|
+
|
26
|
+
def perimeter
|
27
|
+
@x + @y
|
28
|
+
end
|
29
|
+
end
|
30
|
+
CODE
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MethodChainingLimit do
|
4
|
+
|
5
|
+
let(:rule) {MethodChainingLimit.new(1)}
|
6
|
+
|
7
|
+
it "should be valid if there is 1 dot per line" do
|
8
|
+
rule.should be_valid <<-CODE
|
9
|
+
foo.bar
|
10
|
+
bar.baz
|
11
|
+
baz.foo
|
12
|
+
CODE
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be invalid if there are more than 1 dots per line" do
|
16
|
+
rule.should_not be_valid <<-CODE
|
17
|
+
foo
|
18
|
+
foo.bar
|
19
|
+
bar.baz.foo
|
20
|
+
CODE
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should ignore decimals and count only method chaining" do
|
24
|
+
rule.should be_valid <<-CODE
|
25
|
+
foo.bar = 5.67
|
26
|
+
CODE
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe MethodIndentation do
|
4
|
+
let(:rule) {MethodIndentation.new(1)}
|
5
|
+
|
6
|
+
it "should be invalid if level of indentation is more than 2" do
|
7
|
+
rule.should_not be_valid <<-CODE
|
8
|
+
class Foo
|
9
|
+
def foo
|
10
|
+
bars.each do |bar|
|
11
|
+
bazs.each do |baz|
|
12
|
+
bar * baz
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
CODE
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be valid if level of indentation is 2" do
|
21
|
+
rule.should be_valid <<-CODE
|
22
|
+
class Foo
|
23
|
+
def foo
|
24
|
+
bars.each do |bar|
|
25
|
+
bar * bar
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
CODE
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be valid if level of indentation is 0" do
|
33
|
+
rule.should be_valid <<-CODE
|
34
|
+
class Foo
|
35
|
+
def foo
|
36
|
+
foos.first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
CODE
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be valid if level of indentation is 0 with multiple methods" do
|
43
|
+
rule.should be_valid <<-CODE
|
44
|
+
class Foo
|
45
|
+
def foo
|
46
|
+
foos.first
|
47
|
+
end
|
48
|
+
|
49
|
+
def bar
|
50
|
+
bars.first
|
51
|
+
end
|
52
|
+
CODE
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should be invalid if level of indentation is more than 2 with multiple methods" do
|
56
|
+
rule.should_not be_valid <<-CODE
|
57
|
+
class Foo
|
58
|
+
def foo
|
59
|
+
bars.each do |bar|
|
60
|
+
bazs.each do |baz|
|
61
|
+
bar * baz
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def bar
|
67
|
+
bars.first
|
68
|
+
end
|
69
|
+
end
|
70
|
+
CODE
|
71
|
+
end
|
72
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: object_dojo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sathish
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-11 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: ObjectDojo is a utility to improve your Object oriented programming skills
|
15
|
+
using rules described in the article "Object Calisthenics" by JeffBay
|
16
|
+
email:
|
17
|
+
- sathish316@gmail.com
|
18
|
+
executables:
|
19
|
+
- dojo
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- Gemfile
|
25
|
+
- Gemfile.lock
|
26
|
+
- README.markdown
|
27
|
+
- Rakefile
|
28
|
+
- bin/dojo
|
29
|
+
- config/rules.yml
|
30
|
+
- lib/class_structure.rb
|
31
|
+
- lib/class_validator.rb
|
32
|
+
- lib/dojo.rb
|
33
|
+
- lib/extensions.rb
|
34
|
+
- lib/object_dojo/version.rb
|
35
|
+
- lib/rules.rb
|
36
|
+
- lib/rules/avoid_accessor.rb
|
37
|
+
- lib/rules/avoid_keyword.rb
|
38
|
+
- lib/rules/class_line_limit.rb
|
39
|
+
- lib/rules/first_class_collections.rb
|
40
|
+
- lib/rules/instance_variable_limit.rb
|
41
|
+
- lib/rules/method_chaining_limit.rb
|
42
|
+
- lib/rules/method_indentation.rb
|
43
|
+
- object_dojo.gemspec
|
44
|
+
- spec/class_structure_spec.rb
|
45
|
+
- spec/dojo_spec.rb
|
46
|
+
- spec/rules/avoid_accessor_spec.rb
|
47
|
+
- spec/rules/avoid_keyword_spec.rb
|
48
|
+
- spec/rules/class_line_limit_spec.rb
|
49
|
+
- spec/rules/first_class_collections_spec.rb
|
50
|
+
- spec/rules/instance_variable_limit_spec.rb
|
51
|
+
- spec/rules/method_chaining_limit_spec.rb
|
52
|
+
- spec/rules/method_indentation_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
homepage: http://www.github.com/sathish316/object_dojo
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
hash: -1806527109624100395
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
hash: -1806527109624100395
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project: object_dojo
|
80
|
+
rubygems_version: 1.8.10
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: ObjectDojo is a utility to improve your Object oriented programming skills
|
84
|
+
using rules described in the article "Object Calisthenics" by JeffBay
|
85
|
+
test_files:
|
86
|
+
- spec/class_structure_spec.rb
|
87
|
+
- spec/dojo_spec.rb
|
88
|
+
- spec/rules/avoid_accessor_spec.rb
|
89
|
+
- spec/rules/avoid_keyword_spec.rb
|
90
|
+
- spec/rules/class_line_limit_spec.rb
|
91
|
+
- spec/rules/first_class_collections_spec.rb
|
92
|
+
- spec/rules/instance_variable_limit_spec.rb
|
93
|
+
- spec/rules/method_chaining_limit_spec.rb
|
94
|
+
- spec/rules/method_indentation_spec.rb
|
95
|
+
- spec/spec_helper.rb
|