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.

Object? You Keep Using that Word

1,136 views

Published on

Presented at Dynabyte (13th April 2016)

I do not think it means what you think it means. What object means to many programmers is managers, views, controllers, getters and setters, megalithic frameworks, spaghetti inheritance, lots of mocks and large classes. But is this what object-oriented development is really about?

The original vision of objects was focused more on the problem domain than the solution domain. Objects were supposed to be small, properly encapsulated abstractions composed from other objects. Classes were a mechanism for expressing objects, not the editing black hole of the development process.

Think you know objects? This talk strips back the layers of habits, frameworks and legacy to cast objects in a new but old light.

Published in: Software
  • Be the first to comment

Object? You Keep Using that Word

  1. 1. Object? You keep using that word... @KevlinHenney
  2. 2. / WordFriday
  3. 3. Agglutination is a process in linguistic morphology derivation in which complex words are formed by stringing together morphemes, each with a single grammatical or semantic meaning. Languages that use agglutination widely are called agglutinative languages. http://en.wikipedia.org/wiki/Agglutination
  4. 4. pneumonoultramicroscopicsilicovolcanoconiosis Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz fylkestrafikksikkerhetsutvalgssekretariatslederfunksjonene muvaffakiyetsizleştiricileştiriveremeyebileceklerimizdenmişsinizcesine hippopotomonstrosesquipedaliophobia
  5. 5. http://www.bonkersworld.net/object-world/
  6. 6. http://www.bonkersworld.net/object-world/ OBJECT-ORIENTED VenetianBlind Door Television Picture Glass Sofa TelevisionRemoteControl Peephole
  7. 7. People will be using the words you choose in their conversation for the next 20 years. You want to be sure you do it right. Unfortunately, many people get all formal [...]. Just calling it what it is isn't enough.
  8. 8. They have to tack on a flowery, computer science-y, impressive sounding, but ultimately meaningless word, like Object, Thing, Component, Part, Manager, Entity, or Item.
  9. 9. http://classnamer.com/
  10. 10. http://methodnamer.com/
  11. 11. public interface BookEntity ... public interface BookEntityFactory ... public interface ISBNValidator ... public interface CatalogueRepository ... public interface CatalogueRepositoryProvider ... public abstract class AbstractBookEntity implements BookEntity public class BookEntityImpl extends AbstractBookEntity ... public class BookEntityFactoryImpl implements BookEntityFactory ... public class ISBNValidatorImpl implements ISBNValidator ... public class CatalogueRepositoryImpl implements CatalogueRepository ... public class CatalogueRepositoryProviderImpl implements CatalogueRepositoryProvider ...
  12. 12. public interface Book ... public final class ISBN ... public interface Catalogue ... public class DescriptionOfCatalogueImplementation implements Catalogue ...
  13. 13. managerialism, noun  belief in or reliance on the use of professional managers in administering or planning an activity  application of managerial techniques of businesses to the running of other organisations, such as the civil service or local authorities  belief in the importance of tightly managed organisations, as opposed to individuals, or groups that do not resemble an organisation Concise Oxford English Dictionary ∙ Dictionary.com ∙ Wikipedia
  14. 14. One way to name classes is to give each a unique name, indicative of its purpose. Unique names give you the opportunity to convey a lot of information without creating names that are long and unwieldy. This is exactly the right thing to do if the names are in common use.
  15. 15. LoanMember BookCopy
  16. 16. LoanIMember IBookCopy Member BookCopy
  17. 17. Loan Member BookCopy
  18. 18. role, noun  an actor's part in a play, film, etc.  a person or thing's function in a particular situation  a function, part or expected behaviour performed in a particular operation or process Concise Oxford English Dictionary ∙ Merriam-Webster's Collegiate Dictionary
  19. 19. LoanBorrower LoanItem Member BookCopy
  20. 20. interface
  21. 21. TreeBuilderParser
  22. 22. TreeBuilderParser BuilderImpl
  23. 23. TreeParserListenerParser Builder
  24. 24. Tree ParserListenerParser Builder
  25. 25. You can communicate how the new class is the same by naming some superclass. It need not be the immediate superclass, if some distant ancestor communicates more clearly. You can communicate how the new class is different by finding a word that accurately highlights the reason the new class isn't just the superclass.
  26. 26. Connection Connection Factory Connection Impl
  27. 27. Connection Connection Pool Pooled Connection
  28. 28. public Connection createConnection(Provider provider) throws ConnectionFailureException ...
  29. 29. public Connection connectTo(Provider ofUpdates) throws ConnectionFailure ...
  30. 30. OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them. Alan Kay
  31. 31. William Cook, "On Understanding Data Abstraction, Revisited"
  32. 32. Ignorance Apathy Selfishness
  33. 33. Identity State Behaviour
  34. 34. Stack
  35. 35. Stack {push, pop, depth, top}
  36. 36. Stack[T] { push(T), pop(), depth() : Integer, top() : T }
  37. 37. An interface is a contract to deliver a certain amount of service. Clients of the interface depend on the contract, which is usually documented in the interface specification. Butler W Lampson "Hints for Computer System Design"
  38. 38. Stack[T] { push(T item), pop(), depth() : Integer, top() : T } given: before = depth() postcondition: depth() = before + 1 ∧ top() = item precondition: depth() > 0 given: before = depth() precondition: before > 0 postcondition: depth() = before – 1 given: result = depth() postcondition: result ≥ 0
  39. 39. alphabet(Stack) = {push, pop, depth, top}
  40. 40. trace(Stack) = {⟨ ⟩, ⟨push⟩, ⟨depth⟩, ⟨push, pop⟩, ⟨push, top⟩, ⟨push, depth⟩, ⟨push, push⟩, ⟨depth, push⟩, ⟨depth, depth⟩, ⟨push, push, pop⟩, ...}
  41. 41. Non-EmptyEmpty depth depth top push pop [depth > 1] push pop [depth = 1]
  42. 42. public class Stack_spec { public static class A_new_stack { @Test public void has_no_depth()  @Test() public void has_no_top()  } public static class An_empty_stack { @Test() public void throws_when_popped()  @Test public void acquires_depth_by_retaining_a_pushed_item_as_its_top()  } public static class A_non_empty_stack { @Test public void becomes_deeper_by_retaining_a_pushed_item_as_its_top()  @Test public void on_popping_reveals_tops_in_reverse_order_of_pushing()  } }
  43. 43. public class Stack_spec { public static class A_new_stack { @Test public void has_no_depth()  @Test() public void has_no_top()  } public static class An_empty_stack { @Test() public void throws_when_popped()  @Test public void acquires_depth_by_retaining_a_pushed_item_as_its_top()  } public static class A_non_empty_stack { @Test public void becomes_deeper_by_retaining_a_pushed_item_as_its_top()  @Test public void on_popping_reveals_tops_in_reverse_order_of_pushing()  } }
  44. 44. public class Stack_spec { public static class A_new_stack { @Test public void has_no_depth()  @Test() public void has_no_top()  } public static class An_empty_stack { @Test() public void throws_when_popped()  @Test public void acquires_depth_by_retaining_a_pushed_item_as_its_top()  } public static class A_non_empty_stack { @Test public void becomes_deeper_by_retaining_a_pushed_item_as_its_top()  @Test public void on_popping_reveals_tops_in_reverse_order_of_pushing()  } }
  45. 45. Many objects have no conceptual identity. These objects describe some characteristic of a thing.
  46. 46. When you care only about the attributes of an element of the model, classify it as a value object. Make it express the meaning of the attributes it conveys and give it related functionality. Treat the value object as immutable. Don't give it any identity and avoid the design complexities necessary to maintain entities.
  47. 47. Identity State Behaviour
  48. 48. Identity State Behaviour
  49. 49. Encapsulation Inheritance Polymorphism
  50. 50. Encapsulation Polymorphism Inheritance
  51. 51. Encapsulation Polymorphism Inheritance
  52. 52. encapsulate, verb  enclose (something) in or as if in a capsule.  express the essential feature of (someone or something) succinctly.  provide an interface for (a piece of software or hardware) to allow or simplify access for the user. The New Oxford Dictionary of English
  53. 53. In many object-oriented programming languages the concept of inheritance is present, which provides a mechanism for sharing code among several classes of objects. Many people even regard inheritance as the hallmark of object-orientedness in programming languages. We do not agree with this view, and argue that the essence of object- oriented programming is the encapsulation of data and operations in objects and the protection of individual objects against each other. Pierre America "A Behavioural Approach to Subtyping in Object-Oriented Programming Languages"
  54. 54. In many object-oriented programming languages the concept of inheritance is present, which provides a mechanism for sharing code among several classes of objects. Many people even regard inheritance as the hallmark of object-orientedness in programming languages. We do not agree with this view, and argue that the essence of object- oriented programming is the encapsulation of data and operations in objects and the protection of individual objects against each other. The author considers this principle of protection of objects against each other as the basic and essential characteristic of object-oriented programming. It is a refinement of the technique of abstract data types, because it does not only protect one type of objects against all other types, but one object against all other ones. As a programmer we can consider ourselves at any moment to be sitting in exactly one object and looking at all the other objects from outside. Pierre America "A Behavioural Approach to Subtyping in Object-Oriented Programming Languages"
  55. 55. Object-oriented programming does not have an exclusive claim to all these good properties. Systems may be modeled by other paradigms. Resilience can be achieved just as well by organizing programs around abstract data types, independently of taxonomies; in fact, data abstraction alone is sometimes taken as the essence of object orientation.
  56. 56. abstraction, n. (Logic)  the process of formulating a generalized concept of a common property by disregarding the differences between a number of particular instances. On such an account, we acquired the concept of red by recognizing it as common to, and so abstracting it from the other properties of, those individual objects we were originally taught to call red.  an operator that forms a class name or predicate from any given expression. E J Borowski and J M Borwein Dictionary of Mathematics
  57. 57.  T   RecentlyUsedList  { new : RecentlyUsedList[T], isEmpty : RecentlyUsedList[T]  Boolean, size : RecentlyUsedList[T]  Integer, add : RecentlyUsedList[T]  T  RecentlyUsedList[T], get : RecentlyUsedList[T]  Integer  T, equals : RecentlyUsedList[T]  RecentlyUsedList[T]  Boolean }
  58. 58. public class RecentlyUsedList { private … public boolean isEmpty() … public int size() … public void add(String toAdd) … public String get(int index) … public boolean equals(RecentlyUsedList other) … }
  59. 59. public class RecentlyUsedList { private … public boolean isEmpty() … public int size() … public void add(String toAdd) … public String get(int index) … public boolean equals(RecentlyUsedList other) … public boolean equals(Object other) … }
  60. 60. public class RecentlyUsedList { private List<String> items = new ArrayList<String>(); public boolean isEmpty() { return items.isEmpty(); } public int size() { return items.size(); } public void add(String toAdd) { items.remove(toAdd); items.add(toAdd); } public String get(int index) { return items.get(size() – index – 1); } public boolean equals(RecentlyUsedList other) { return other != null && items.equals(other.items); } public boolean equals(Object other) { return other instanceof RecentlyUsedList && equals((RecentlyUsedList) other); } }
  61. 61. typedef struct RecentlyUsedList RecentlyUsedList; RecentlyUsedList * create(); void destroy(RecentlyUsedList *); bool isEmpty(const RecentlyUsedList *); int size(const RecentlyUsedList *); void add(RecentlyUsedList *, int toAdd); int get(const RecentlyUsedList *, int index); bool equals(const RecentlyUsedList *, const RecentlyUsedList *);
  62. 62. struct RecentlyUsedList { int * items; int length; };
  63. 63. RecentlyUsedList * create() { RecentlyUsedList * result = (RecentlyUsedList *) malloc(sizeof(RecentlyUsedList)); result->items = 0; result->length = 0; return result; } void destroy(RecentlyUsedList * self) { free(self->items); free(self); } bool isEmpty(const RecentlyUsedList * self) { return self->length == 0; } int size(const RecentlyUsedList * self) { return self->length; } static int indexOf(const RecentlyUsedList * self, int toFind) { int result = -1; for(int index = 0; result == -1 && index != self->length; ++index) if(self->items[index] == toFind) result = index; return result; } static void removeAt(RecentlyUsedList * self, int index) { memmove(&self->items[index], &self->items[index + 1], (self->length - index - 1) * sizeof(int)); --self->length; } void add(RecentlyUsedList * self, int toAdd) { int found = indexOf(self, toAdd); if(found != -1) removeAt(self, found); self->items = (int *) realloc(self->items, (self->length + 1) * sizeof(int)); self->items[self->length] = toAdd; ++self->length; } int get(const RecentlyUsedList * self, int index) { return self->items[self->length - index - 1]; } bool equals(const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { return lhs->length == rhs->length && memcmp(lhs->items, rhs->items, lhs->length * sizeof(int)) == 0; }
  64. 64. struct RecentlyUsedList { std::vector<int> items; };
  65. 65. extern "C" { RecentlyUsedList * create() { return new RecentlyUsedList; } void destroy(RecentlyUsedList * self) { delete self; } bool isEmpty(const RecentlyUsedList * self) { return self->items.empty(); } int size(const RecentlyUsedList * self) { return self->items.size(); } void add(RecentlyUsedList * self, int toAdd) { std::vector<int>::iterator found = std::find(self->items.begin(), self->items.end(), toAdd); if(found != self->items.end()) self->items.erase(found); self->items.push_back(toAdd); } int get(const RecentlyUsedList * self, int index) { return self->items[self->items.size() - index - 1]; } bool equals(const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { return lhs->items == rhs->items; } }
  66. 66. OO ≡ ADT?
  67. 67. OO ≡ ADT/
  68. 68. William Cook, "On Understanding Data Abstraction, Revisited"
  69. 69. public class RecentlyUsedList { ... public boolean equals(RecentlyUsedList other) { return other != null && items.equals(other.items); } public boolean equals(Object other) { return other instanceof RecentlyUsedList && equals((RecentlyUsedList) other); } }
  70. 70. bool equals(const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { return lhs->length == rhs->length && memcmp(lhs->items, rhs->items, lhs->length * sizeof(int)) == 0; }
  71. 71. extern "C" { ... bool equals(const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { return lhs->items == rhs->items; } }
  72. 72. bool equals( const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { bool result = size(lhs) == size(rhs); for(int index = 0; result && index != size(lhs); ++index) result = get(lhs, index) == get(rhs, index); return result; }
  73. 73. extern "C" bool equals( const RecentlyUsedList * lhs, const RecentlyUsedList * rhs) { bool result = size(lhs) == size(rhs); for(int index = 0; result && index != size(lhs); ++index) result = get(lhs, index) == get(rhs, index); return result; }
  74. 74. public class RecentlyUsedList { ... public boolean equals(RecentlyUsedList other) { boolean result = other != null && size() == other.size(); for(int index = 0; result && index != size(); ++index) result = get(index).equals(other.get(index)); return result; } public boolean equals(Object other) { return other instanceof RecentlyUsedList && equals((RecentlyUsedList) other); } }
  75. 75. One of the most pure object-oriented programming models yet defined is the Component Object Model (COM). It enforces all of these principles rigorously. Programming in COM is very flexible and powerful as a result. There is no built-in notion of equality. There is no way to determine if an object is an instance of a given class. William Cook "On Understanding Data Abstraction, Revisited"
  76. 76. public class RecentlyUsedList { ... public boolean equals(RecentlyUsedList other) { boolean result = other != null && size() == other.size(); for(int index = 0; result && index != size(); ++index) result = get(index).equals(other.get(index)); return result; } public boolean equals(Object other) { return other instanceof RecentlyUsedList && equals((RecentlyUsedList) other); } }
  77. 77. public class RecentlyUsedList { ... public boolean equals(RecentlyUsedList other) { boolean result = other != null && size() == other.size(); for(int index = 0; result && index != size(); ++index) result = get(index).equals(other.get(index)); return result; } }
  78. 78. In a purist view of object-oriented methodology, dynamic dispatch is the only mechanism for taking advantage of attributes that have been forgotten by subsumption. This position is often taken on abstraction grounds: no knowledge should be obtainable about objects except by invoking their methods. In the purist approach, subsumption provides a simple and effective mechanism for hiding private attributes.
  79. 79. William Cook, "On Understanding Data Abstraction, Revisited"
  80. 80. public interface RecentlyUsedList { boolean isEmpty(); int size(); void add(String toAdd); String get(int index); boolean equals(RecentlyUsedList other); }
  81. 81. public class RecentlyUsedListImpl implements RecentlyUsedList { private List<String> items = …; public boolean isEmpty() … public int size() … public void add(String toAdd) … public String get(int index) … public boolean equals(RecentlyUsedList other) … public boolean equals(Object other) … }
  82. 82. public class ArrayListBasedRecentlyUsedList implements RecentlyUsedList { private List<String> items = …; public boolean isEmpty() … public int size() … public void add(String toAdd) … public String get(int index) … public boolean equals(RecentlyUsedList other) … public boolean equals(Object other) … }
  83. 83. public class RandomAccessRecentlyUsedList implements RecentlyUsedList { private List<String> items = …; public boolean isEmpty() … public int size() … public void add(String toAdd) … public String get(int index) … public boolean equals(RecentlyUsedList other) … public boolean equals(Object other) … }
  84. 84. RecentlyUsedList list = new RandomAccessRecentlyUsedList();
  85. 85. William Cook, "On Understanding Data Abstraction, Revisited"

×