Object Oriented Views / Aki Salmi
Transcript of Object Oriented Views / Aki Salmi
Object Oriented Views
Aki Salmi @rinkkasatiainen
I like to do crazy stuff
codefreeze.fi experimental coding
Programmer @Ambientia
skype: rinkkasatiainentwitter: @rinkkasatiainenweb: rinkkasatiainen.fiemail: [email protected]
Goal for this talk
is to
Initiate discussion
anyone @ Socrates 2014
Content
• Background
• A way to solve
• Discussion
• Open Space: Mob Programming?
Very Brief Background
• Confluence plugin
• real production code (used by thousands, daily)
We have all seen
Controllers like
This
/INDEX (1 of many actions)
ParamsService
“DAO”“or not DAO”
DAO-DAO-DAO
ServiceService
DomainServiceRender
Not that, not today
Let’s assume we’re working with thin
controllers
Have we seen
views like
this Only today: logic in a view
So how then?
How about Code I’ve written myself?
Not much better
A Deeper Dive
Params
BUILD CONTEXT
GET MODEL
RENDEROR RENDER
But there is a catch
Render Many Blogs Or 1, or 0
... based on object types
Build a ‘different’ domain entity?
Build ‘real’
Domain
Build ‘real’
Domain
Build a ‘different’ Context
BUILD context
Diff context
no context
Render ‘different’ template
Templ_0Templ_1
Templ_n
Seems like a violation of SRP
(Single Responsibility Principle)
What did we see
• build parameters
• build context (on 2 places)
• build domain
• render different data, differently, based on the domain entity
Visually
Controller
HTTP GET
Domain
View 0 View 1 View N
It works
..sort of
• most of the bugs I introduced, were on this behavior of the system.
• This class
• Concepts introduced by this class
• Integration with Confluence API
• especially ‘null’s
What IF
Controller
HTTP GET
Domain
View 0 View 1 View N
What IF... C’s responsibility
• Given a set of parameters...
• Build Model (service / repository)
• Render Template with model given
• and let other’s to figure out which is the view to render
Decorate / Exhibit
Controller
HTTP GET
Domain
View
Exhibit
1) build model
2) render
3) exhibit
View tmpl
4) render
How does it work
few design decision done by me
• avoid nulls
• separate Read Model from Write Model
• 1st class collections
• Separated Query and Command Controller (sort of CQRS)
Domain Entity: Group
<if> ReadOrWriteModel
<if> ReadModel <if> WriteModel
GroupEntity GroupDescrGroupList
Domain Entity: Group
<if> ReadOrWriteModel
<if> ReadModel <if> WriteModel
GroupEntity GroupDescrGroupList
Domain Entity: Group
GroupEntity* immutable
* final private prop* behavior rich
GroupDescriptor* public properties
* tiny behavior
AGroupThatDoesNotExistYet
AGroup
Domain Entity: Group
<if> ReadOrWriteModel
<if> ReadModel <if> WriteModel
GroupEntity GroupDescrGroupList
Domain Entity: Group
GroupList* behavior: iterate
Introducing Exhibits
• Introduced by Avdi Grimm
• sort of presenter-decorator
Exhibit Characteristics
• Wraps a single model instance
• Is a true Decorator
• Brings together model and context
• Encapsulates the decision about how to render an object
• May modify the behavior of an object
Exhibit BExhibit A
Exhibit visually
Model object
Exhibits: Group
<if> Exhibit+ renderBody()
GroupListExh GroupList
GroupExhibit GroupEntity
EditGroupExh GroupDesc
GroupWPicture
Exhibits: Group
GroupListExh ListView
GroupExhibit GroupView
EditGroupExh EditGroup
GroupWPicture GPictureView
REST viewHTTP PATH Contr#Action Domain Class
GET /foo(.:format) foos#index FooList
POST /foo(.:format) foos#create FooDescriptor
GET /foo/new foos#new FooDescriptor
GET /foo/:id/edit foos#edit FooDescriptor
GET /foo/:id foos#show FooEntry
PATCH/PUT /foo/:id foos#update FooDescriptor
DELETE /foo/:id foos#delete FooDescriptor
Creating exhibits the ruby way 1/2
Avdi Grimm: Object on Rails, Listing 76
Creating exhibits the ruby way 2/2
Avdi Grimm: Object on Rails, Listing 77
Creating exhibits the Java 8 way 1/N
Time for some code Confluence plugin Velocity templates
View
Controller
Exhibit A
Exhibit B
Exhibit C
Exhibit D
Decorate / Exhibit
Controller
HTTP GET
Domain
View
Exhibit
1) build model
2) render
3) exhibit
View tmpl
4) render
And visually
Surroundings
Exhibit templates
RemotePictureExhibit ||DefaultPictureExhibit
UserProfileExhibitCould be composite
Did it work - in retrospect
• No issues in production with this code
• It is not, by far, easy to grasp. Without someone explaining
What I did not show
• transformations of domain entities:
• Request -> Write -> Persistence
• Persistence -> Write (-> Read)
• Composite Exhibit - how to show 0, 1 or many concepts, dynamically, based on the ModelObject rendered
What could I experiment
• Capabilities for exhibits
• Capability.mobile
• Capability.REST
• Capability.json
Thanks! Questions?
skype: @rinkkasatiainentwitter: @rinkkasatiainenemail: [email protected]