Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to write good code.

How to write good code.

My presentation at VarnaConf.
Code from the presentation: https://github.com/RStankov/varna-conf-2012
Video from the presentation: https://www.youtube.com/watch?v=avhljVTlHZE

Radoslav Stankov

August 11, 2012
Tweet

More Decks by Radoslav Stankov

Other Decks in Technology

Transcript

  1. $('.accordion-menu .item a').each(function() { $(this).bind('click', function() { var title =

    this.className; var theul = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } else { } }); });
  2. $('.accordion-menu .item a').each(function() { $(this).bind('click', function() { var title =

    this.className; var theul = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } else { } }); });
  3. $('.accordion-menu .item a').each(function() { $(this).bind('click', function() { var title =

    this.className; var theul = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } }); });
  4. $('.accordion-menu .item a').each(function() { $(this).bind('click', function() { var title =

    this.className; var theul = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } }); });
  5. $('.accordion-menu .item a').click(function() { var title = this.className; var theul

    = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  6. $('.accordion-menu .item a').click(function() { var title = this.className; var theul

    = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  7. $('.accordion-menu .item a').click(function() { var title = this.className; var theul

    = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  8. $('.accordion-menu .item a').click(function() { var title = this.className; var theul

    = $('#' + title); if (theul.length > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  9. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul'); if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  10. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul'); if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  11. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul'); if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } else { theul.slideUp(); var theli = dropa.parent('li'); theli.animate({'padding-bottom': '20px'}); } } });
  12. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul'); if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown() } else { theul.slideUp() } var theli = dropa.parent('li') theli.animate({'padding-bottom': '20px'}); } });
  13. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul'); if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown() } else { theul.slideUp() } var theli = dropa.parent('li') theli.animate({'padding-bottom': '20px'}); } });
  14. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown() } else { theul.slideUp() } } });
  15. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.css('display') == 'none') { theul.slideDown() } else { theul.slideUp() } } });
  16. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  17. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  18. $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  19. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  20. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  21. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  22. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  23. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  24. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  25. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  26. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  27. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  28. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  29. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page]) Copy & Paste
  30. class MostLikedFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('votes_count') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end MostLikedFriendImages.new(current_user).images(params[:page])
  31. class MostLikedFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('votes_count') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end MostLikedFriendImages.new(current_user).images(params[:page])
  32. class MostLikedFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('votes_count') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end MostLikedFriendImages.new(current_user).images(params[:page])
  33. class MostLikedFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('votes_count') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end MostLikedFriendImages.new(current_user).images(params[:page])
  34. class MostLikedFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('votes_count') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end MostLikedFriendImages.new(current_user).images(params[:page])
  35. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  36. class NewsestFriendImages def initialize(user) @user = user end def images(page)

    friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end NewsestFriendImages.new(current_user).images(params[:page])
  37. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  38. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  39. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  40. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  41. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  42. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  43. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end FriendImages.new(current_user).images('created_at', params[:page]) FriendImages.new(current_user).images('likes_count', params[:page])
  44. API = 'api' SOURCE_TYPE = '/:source_type' SOURCE_ID = '/:id' SOURCE_DATE

    = '/:year/:month/:day' SUBTYPE = '/:subtype' SUBID = '/:subtype_id' API_GET = API + SOURCE_TYPE + SOURCE_ID API_GET_DETAILS = API + SOURCE_TYPE + SOURCE_ID + '/details' API_GET_VERSION = API + SOURCE_TYPE + SOURCE_ID + '/on' + SOURCE_DATE API_GET_SUBTYPE = API + SOURCE_TYPE + SOURCE_ID + '/sub' + SUBTYPE + SUBID
  45. def api_path(rest = '') BASE_PATH + rest end def token(string)

    SEPARATOR + string end SEPARATOR = '/' API = 'api' SOURCE_TYPE = ':source_type' SOURCE_ID = ':id' YEAR = ':year' MONTH = ':month' DAY = ':day' SUBTYPE = ':subtype' SUBID = ':subtype_id' DETAILS = 'details' ON = 'on' SUB = 'sub' BASE_PATH = token(API) + token(SOURCE_TYPE) + token(SOURCE_ID) DATE_PART = token(YEAR) + token(MONTH) + token(DAY) SUB_PART = token(SUBTYPE) + token(SUBID) API_GET = api_path() API_GET_DETAILS = api_path(token(DETAILS)) API_GET_VERSION = api_path(token(ON) + token(DATE_PART)) API_GET_SUBTYPE = api_path(token(SUB) + token(SUB_PART))
  46. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end
  47. Keep all lines of code in a method at the

    same level of abstraction.
  48. class FriendImages def initialize(user) @user = user end def images(sorting,

    page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end end
  49. def images(sorting, page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id:

    friends, visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order(sorting) images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end
  50. def images(sorting, page) images = find_images_of(friends) images = apply_age_restritions_to(images) images

    = order_by(images, sorting) images = paginate(images, page) decorate(images) end
  51. def friends Friendship.where(user_id: @user.id).pluck('friend_id') end def find_images_of(friends) Image.where(user_id: friends, visible_to_friends:

    true) end def apply_age_restritions_to(images) images.where('minimum_age >= ?', @user.age) end def order_by(sorting) images.order(sorting) end def paginate(page) images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) end def decorate(images) images.map { |image| ImageDecorator.new(image) } end
  52. • You can play with yourself. • You can play

    with your own toys (but you can't take them apart), • You can play with toys that were given to you. • And you can play with toys you've made yourself.
  53. • Your method can call other methods in its class

    directly • Your method can call methods on its own fields directly (but not on the fields' fields) • When your method takes parameters, your method can call methods on those parameters directly. • When your method creates local objects, that method can call methods on the local objects.
  54. def friends Friendship.where(user_id: @user.id).pluck('friend_id') end def find_images_of(friends) Image.where(user_id: friends, visible_to_friends:

    true) end def apply_age_restritions_to(images) images.where('minimum_age >= ?', @user.age) end def order_by(sorting) images.order(sorting) end def paginate(page) images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) end def decorate(images) images.map { |image| ImageDecorator.new(image) } end
  55. def friends Friendship.friend_ids_of(@user) end def find_images_of(friends) Image.of(friends) end def apply_age_restritions_to(images)

    images.appropriate_for(@user.age) end def order_by(sorting) images.order(sorting) end def paginate(page) images.paginate(page) end def decorate(images) images.map { |image| ImageDecorator.new(image) } end
  56. def images(sorting, page) images = find_images_of(friends) images = apply_age_restritions_to(images) images

    = order_by(images, sorting) images = paginate(images, page) decorate(images) end
  57. def images(page) friends = Friendship.where(user_id: @user.id).pluck('friend_id') images = Image.where(user_id: friends,

    visible_to_friends: true) images = images.where('minimum_age >= ?', @user.age) images = images.order('created_at') images = images.limit(PER_PAGE).offset(page.to_i.abs * PER_PAGE) images.map { |image| ImageDecorator.new(image) } end
  58. • Duplicated Code • Long Method • Large Class •

    Long Parameter List • Shotgun Surgery • Feature Envy • Data Clumps • Case Statements • Parallel Inheritance Hierarchies • Speculative Generality • Temporary Field • Message Chains • Middle Man • Alternative Classes with Different Interfaces • Refused Bequest • Comments • Repetitive Boilerplate • и т.н....
  59. Retrospection ✓ DRY ✓ SLAP ✓ Law of demeter ✓

    Tools ✓ Code smells ✓ Out side the box