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

7a0e72a6f55811246bb5d9a946fd2e49?s=128

Radoslav Stankov

August 11, 2012
Tweet

Transcript

  1. 3.
  2. 4.
  3. 5.
  4. 6.
  5. 7.
  6. 8.
  7. 9.
  8. 12.
  9. 13.
  10. 15.

    $('.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 { } }); });
  11. 16.

    $('.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 { } }); });
  12. 17.

    $('.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'}); } } }); });
  13. 18.

    $('.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'}); } } }); });
  14. 19.

    $('.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'}); } } });
  15. 20.

    $('.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'}); } } });
  16. 26.

    $('.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'}); } } });
  17. 27.

    $('.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'}); } } });
  18. 28.

    $('.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'}); } } });
  19. 29.

    $('.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'}); } } });
  20. 30.

    $('.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'}); } } });
  21. 31.

    $('.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'}); } });
  22. 32.

    $('.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'}); } });
  23. 33.

    $('.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() } } });
  24. 34.

    $('.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() } } });
  25. 35.

    $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  26. 36.

    $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  27. 37.

    $('.accordion-menu .item a').click(function() { var theul = $(this).next('ul') if (theul.length

    > 0) { if (theul.is(':visible')) { theul.slideDown() } else { theul.slideUp() } } });
  28. 51.
  29. 52.

    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])
  30. 53.

    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])
  31. 54.

    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])
  32. 55.

    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])
  33. 56.

    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])
  34. 57.

    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])
  35. 58.

    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. 59.

    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. 60.

    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])
  38. 61.

    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])
  39. 62.

    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
  40. 63.

    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])
  41. 64.

    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])
  42. 65.

    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])
  43. 66.

    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])
  44. 67.

    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])
  45. 70.

    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])
  46. 71.

    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])
  47. 72.

    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])
  48. 73.

    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])
  49. 74.

    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])
  50. 75.

    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])
  51. 76.

    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])
  52. 77.

    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])
  53. 78.

    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])
  54. 82.

    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
  55. 83.

    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))
  56. 84.
  57. 85.
  58. 86.

    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
  59. 88.

    Keep all lines of code in a method at the

    same level of abstraction.
  60. 89.

    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
  61. 90.

    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
  62. 91.

    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
  63. 92.

    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
  64. 94.

    • 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.
  65. 95.

    • 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.
  66. 96.

    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
  67. 97.

    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
  68. 98.

    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
  69. 100.

    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
  70. 103.

    • 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 • и т.н....
  71. 112.

    Retrospection ✓ DRY ✓ SLAP ✓ Law of demeter ✓

    Tools ✓ Code smells ✓ Out side the box
  72. 113.
  73. 115.
  74. 117.