2. Iain Hecker
• Ruby developer at Finalist IT Group
• 4 years of Ruby experience
• Contributed to Rails core / i18n
• 9 gems released
• http://iain.nl
• http://github.com/iain
• @iain_nl
4. symptoms
• maintaining code is annoying
• adding features is a pain
• development speed is low
• system is unstable, but you don't exactly know why
• inconsistency and side effects fuck everything up
• fear of upgrading
• "I'm not touching that code!"
8. "I need to do ..... because the code needs ....."
vs.
"I need to do ..... because the business needs ....."
9. lower accidental complexity
• use great frameworks (like Rails)
• test all the fucking time
• refactor all the fucking time
• use programming patterns (like MVC)
• pair-programming
21. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
User
Agreement
22. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
23. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
Party
Department
Person
Group
Member
24. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Group
Member
25. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
29. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
30. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
31. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
32. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
33. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
34. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
35. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
36. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
37. bounded contexts
• boundaries lower complexity
• different contexts can interfere
• leaking between boundaries is called coupling
• side effects are bound to one context
40. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
41. As an council member (gemeenteraadslid)
I can see which agreements have been made
So I can supervise the execution of my policy
42. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
43. As a civil servant (ambtenaar)
I can see which agreements have been made
So I know what to work on
44. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
45. adding real value
• find what is important for your users
• invest time and effort in designing those core domains
• slack your efforts in support domains
• use existing products for generic support domains (like authentication)
48. models
• describe a version of reality to solve a certain problem
• do not represent technical terms like 'database tables'
• have a meaning in the business domain
49.
50. AgreementReference RecentView UserSession
AgreementSubscription
AgreementType
SearchSubscription
User
Agreement
Search
ProgressNote Party
Department
Mutation
Person
Meeting Group
Notification
Member
75. } implementation detail
}
class Group < ActiveRecord::Base
end
module Agreement
class Involvement
has_one :charged
has_one :charger
domain logic
has_one :responsible
end
class Charged < Group
end
class Charger < Group
end
class Responsible < Group
end
end
76. class Group < ActiveRecord::Base
delegate :count, :to => :tasks, :prefix => true
end
module Agreement
class Charged < Group
def busy?
tasks_count > 0
end
end
class Charger < Group
def busy?
tasks_count > 4
end
end
end
79. class Post < ActiveRecord::Base
scope :published, where(:published => true)
end
class PostsController < ApplicationController
respond_to :html
def index
respond_with(@posts = Post.published)
end
def show
respond_with(@post = Post.published.find(params[:id]))
end
end
80. class Post < ActiveRecord::Base
scope :published, where(:published => true)
scope :visible, where(:visible => true)
end
class PostsController < ApplicationController
respond_to :html
def index
respond_with(@posts = Post.published.visible.all)
end
def show
respond_with(@post = Post.published.visible.find(params[:id])
end
end
81. class Post < ActiveRecord::Base
scope :published, where(:published => true)
scope :visible, where(:visible => true)
scope :for_frontend, published.visible
end
class PostsController < ApplicationController
respond_to :html
def index
respond_with(@posts = Post.for_frontend.all)
end
def show
respond_with(@post = Post.for_frontend.find(params[:id])
end
end
85. # app/models/frontend/post.rb
module Frontend
class Post < ::Post
default_scope published.visible
end
end
# app/controllers/frontend/posts_controller.rb
module Frontend
class PostsController
respond_to :html
def index
respond_with(@posts = Post.all)
end
def show
respond_with(@post = Post.find(params[:id]))
end
end
end
86. module PersonalModel
extend ActiveSupport::Concern
included do
attr_accessor :current_user
module Public
before_update :check_current_user
class Comment < ::Comment
before_destroy :check_current_user
include PersonalModel
end
attr_accessible :body
end
def owned_record?
end
current_user == user
end
def check_current_user
raise UnauthorizedUserError.new(self) unless owned_record?
end
end
87. works great for
• (default) scopes
• validations
• attr_protected / attr_accessible
• associations
• any other piece of code