Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Kill the Controllers
Kill the Controllers
A terrible great way refactor large applications.
Yes, there are models, fetched and
created by the controller
Yes, views, too. The controller makes
em!
API Queries, UI, an...
State
API
Models
Views
Layout
Storage
Controller
API
Models
Views
Controller
MVC?
MVC?❌
MQVLCS
Storage
Controller
Layout
View
Query
Model
wat
credit: LimeCoconutShake from www.skyblock.net
The benefits are many!
• Classes focus on one task
• Controllers don’t “do it all”
• Less code bloat all around
• Testable...
– Colin T.A. Gray
“Don’t quote me on any of that.”
• Layout?
• Storage? WTF is that?
• Models & Queries?It’s your call.
Again, up to you.
There’s a gem for that. ;-)
credit: Gant Laborde
• Animations
• Events
• Styles
• Imagine a controller and a view
got together and had an adorable
love child
• Move your U...
• Support for iOS and OS X
• Support for CALayer, NSMenu
• Frame and AutoLayout DSLs
• Add your own helpers just by
defini...
class LoginLayout < MK::Layout # or < MK::WindowLayout
# or < MK::MenuLayout
view :username_field
view :submit_button # @l...
def login_label_style
initial do # only apply when views are created
text 'Login'
backgroundColor UIColor.clearColor
font ...
# separate method to work with controller.topLayoutGuide
def add_constraints(controller)
constraints(self.view) do
origin ...
MotionKit Extensions
def label_style
frame from_top(:container, width: 200)
frame below(:button)
frame left_of(:other_labe...
MotionKit Extensions
Constraints
def label_style
constraints do
left.equals(:superview, :left).plus(8)
right.equals(:butto...
MotionKit Extensions
NSMenu
class MainMenu < MK::Menu
def layout
add 'File' do
add 'Open', action: 'open:', key: 'o'
add '...
MotionKit Extensions
def label_style
autoresizing_mask :pin_to_top
layer do
backgroundColor UIColor.blackColor.CGColor
end...
shadow_color UIColor.colorWithRed(0.133, green: 0.133, blue: 0.133)
text_color UIColor.colorWithRed(0.6, green: 0.6, blue:...
shadow_color '#222222'
text_color '#999999'
font 'Avenir-Medium', size: 20
line_break_mode :word_wrap
text_alignment :cent...
MotionKit::Events
Decouple your UI events
class LoginLayout < MK::Layout
def login_button_style
target.on :touch do
trigge...
Roadmap
• View Layout helpers
• Spec helpers
• Layouts (e.g. Linear flow)
• Tutorials
• Screencasts
• Documentation
– Colin T.A. Gray
“Oh yeah, Jamon I forgot to tell you.”
class LoginLayout < MK::Layout
view :username_field
view :submit_button
def layout
add Android::Widget::LinearLayout, :log...
Kill the Controllers!
• Controllers should do the minimum
amount of “paper pushing”
• UI and animations → Layout
• Talking...
DEMO
Example of a LoginController written with
Storage and Layout classes.
You can see some similar code here:
github.com/...
Colin T.A. Gray
Community Manager at HipByte
Engineer at Jukely
github.com/colinta
github.com/rubymotion/motion-kit
gem in...
Upcoming SlideShare
Loading in …5
×

Kill the Controllers, and an introduction to MotionKit

2,273 views

Published on

This presentation is in two parts. The first part goes over how I refactored the Jukely app to have better separation of concerns by breaking up the controller into a "Storage" (aka Adapter, Repository) class and a "Layout" class. This technique worked very well for me, and resulted in cleaner code, more testable classes, and controllers that were easy to understand.

I also present MotionKit, which is a gem that is designed to fulfill that "Layout" role. You can design and update your views very easily using MotionKit, and it can be used on iOS, OS X, and we already have Android support on the way!

MotionKit was written by me and Jamon Holmgren.

Published in: Software
  • Be the first to comment

Kill the Controllers, and an introduction to MotionKit

  1. 1. Kill the Controllers
  2. 2. Kill the Controllers A terrible great way refactor large applications.
  3. 3. Yes, there are models, fetched and created by the controller Yes, views, too. The controller makes em! API Queries, UI, animations, network availability, login status, UI events, ticket purchasing, Facebook login, caching, scrolling updates, image downloading and processing, search filters, recommendations, notifications, sharing…
  4. 4. State API Models Views Layout Storage Controller API Models Views Controller
  5. 5. MVC?
  6. 6. MVC?❌
  7. 7. MQVLCS
  8. 8. Storage Controller Layout View Query Model
  9. 9. wat credit: LimeCoconutShake from www.skyblock.net
  10. 10. The benefits are many! • Classes focus on one task • Controllers don’t “do it all” • Less code bloat all around • Testable controllers • Easier to add new features • Easier to read and understand
  11. 11. – Colin T.A. Gray “Don’t quote me on any of that.”
  12. 12. • Layout? • Storage? WTF is that? • Models & Queries?It’s your call. Again, up to you. There’s a gem for that. ;-)
  13. 13. credit: Gant Laborde
  14. 14. • Animations • Events • Styles • Imagine a controller and a view got together and had an adorable love child • Move your UI code out of your controller:
  15. 15. • Support for iOS and OS X • Support for CALayer, NSMenu • Frame and AutoLayout DSLs • Add your own helpers just by defining a class
  16. 16. class LoginLayout < MK::Layout # or < MK::WindowLayout # or < MK::MenuLayout view :username_field view :submit_button # @layout.submit_button def layout background_color UIColor.blackColor add UILabel, :login_label add UIView, :login_container do add UITextField, :username_field add UIButton, :submit_button end end end
  17. 17. def login_label_style initial do # only apply when views are created text 'Login' backgroundColor UIColor.clearColor font UIFont.boldSystemFontOfSize(40) textAlignment UITextAlignmentCenter layer do shadowRadius 20 shadowOpacity 0.5 masksToBounds false end constraints do width('100%') center_x.equals(:superview) end end end
  18. 18. # separate method to work with controller.topLayoutGuide def add_constraints(controller) constraints(self.view) do origin [0, 0] width.equals(:superview) height.equals(:superview) end constraints(:login_label) do below(controller.topLayoutGuide).plus(50) # define top_margin: 50 # below(controller.topLayoutGuide).plus(:top_margin) end end
  19. 19. MotionKit Extensions def label_style frame from_top(:container, width: 200) frame below(:button) frame left_of(:other_label) x 0 y 0 right 320 bottom '100% - 8' end Frames
  20. 20. MotionKit Extensions Constraints def label_style constraints do left.equals(:superview, :left).plus(8) right.equals(:button, :left).minus(8) top_left.equals(:superview) height.is <= 100 end end
  21. 21. MotionKit Extensions NSMenu class MainMenu < MK::Menu def layout add 'File' do add 'Open', action: 'open:', key: 'o' add 'Close', action: 'close:', key: 'w' add 'Foo', :foo_menu add 'Bar', :bar_menu do add 'Baz' end end end end
  22. 22. MotionKit Extensions def label_style autoresizing_mask :pin_to_top layer do backgroundColor UIColor.blackColor.CGColor end title 'Send' title 'Done', state: UIControlStateDisabled portrait do frame [[0, 0], [100, 100]] end landscape do frame [[20, 0], [140, 100]] end end
  23. 23. shadow_color UIColor.colorWithRed(0.133, green: 0.133, blue: 0.133) text_color UIColor.colorWithRed(0.6, green: 0.6, blue: 0.6) font UIFont.fontWithName(‘Avenir-Medium’, size: 20) line_break_mode UILineBreakModeWordWrap text_alignment NSTextAlignmentCenter baseline_adjustment UIBaselineAdjustmentNone SweetKit Uses SugarCube methods to turn this…
  24. 24. shadow_color '#222222' text_color '#999999' font 'Avenir-Medium', size: 20 line_break_mode :word_wrap text_alignment :center baseline_adjustment :none SweetKit …into this!
  25. 25. MotionKit::Events Decouple your UI events class LoginLayout < MK::Layout def login_button_style target.on :touch do trigger(:login, username_field.text.to_s, @password_field.text.to_s) end end end class LoginController < UIViewController def viewDidLoad super @layout = LoginLayout.new(root: self.view) @layout.on :login do |username, password| handle_login(username, password) end end end
  26. 26. Roadmap • View Layout helpers • Spec helpers • Layouts (e.g. Linear flow) • Tutorials • Screencasts • Documentation
  27. 27. – Colin T.A. Gray “Oh yeah, Jamon I forgot to tell you.”
  28. 28. class LoginLayout < MK::Layout view :username_field view :submit_button def layout add Android::Widget::LinearLayout, :login_container do orientation VERTICAL add Android::View::TextView, :username_field add Android::View::Button, :submit_button end end def submit_button_style text 'Login' end end MotionKit on Android
  29. 29. Kill the Controllers! • Controllers should do the minimum amount of “paper pushing” • UI and animations → Layout • Talking to the API → Storage • etc. (Misc Task → Misc Class)
  30. 30. DEMO Example of a LoginController written with Storage and Layout classes. You can see some similar code here: github.com/rubymotion/motion-kit-events
  31. 31. Colin T.A. Gray Community Manager at HipByte Engineer at Jukely github.com/colinta github.com/rubymotion/motion-kit gem install motion-kit github.com/colinta/motion-xray gem install motion-xray

×