object_dojo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|