DATA ENCAPSULATION Built-in data types: int, float, boolean, char, String, [], List<>, Map<>, Set<> Ultimately, all of our data is stored using these data types. However, it is often best to wrap these data types in classes that provide higher-level, domain-specific abstractions. 1. Primitive Obsession class PhoneBookEntry { private String _name; private String _address; private String _phoneNumber; } class PhoneBookEntry { private Name _name; private Address _address; private PhoneNumber _phoneNumber; } 2. Encapsulating Collections // NO ABSTRACTION List phoneBook; // SHOULD WRAP THE DATA STRUCTURE IN A CLASS THAT // MODELS THE DOMAIN AND PROVIDES ALL OPERATIONS // NEEDED BY THE PROGRAM class PhoneBook { private List _entries; } We typically need the following operations: 1. Add 2. Update 3. Delete 4. Data Integrity Enforcement 5. Iterate 6. Search 7. Domain-specific Algorithms // POOR ABSTRACTION class PhoneBook { private List _entries; // LAZY way to support Add, Update, Delete, Iterate, Search List getEntries() { return _entries; } // Domain-specific Algorithms ... } Exposes internal implementation Provides no data integrity enforcement Lacks operations needed by the program class PhoneBook { private List _entries; public Result addEntry(PhoneBookEntry entry) { ... } public Result updateEntry(PhoneBookEntry before, PhoneBookEntry after) { ... } public Result deleteEntry(PhoneBookEntry entry) { ... } public Iterator findAll() { ... } public PhoneBookEntry findByPhoneNumber(PhoneNumber value) { ... } public Iterator findByName(Name value) { ... } public Iterator findByAddress(Address value) { ... } // Domain-specific Algorithms ... } // Read-Only Search Results class PhoneBook { private List _entries; public Result addEntry(PhoneBookEntry entry) { ... } public Result updateEntry(PhoneBookEntry before, PhoneBookEntry after) { ... } public Result deleteEntry(PhoneBookEntry entry) { ... } //*** public Iterator findAll() { return _entries.iterator(); } OR public Iterator findAll() { return java.util.Collections.unmodifiableList(_entries).iterator(); } //*** public PhoneBookEntry findByPhoneNumber(PhoneNumber value) { ... } public Iterator findByName(Name value) { ... } public Iterator findByAddress(Address value) { ... } // Domain-specific Algorithms ... } Indexing class PhoneBook { private List _entries; private Map _indexByPhoneNumber; private Map> _indexByName; private Map> _indexByAddress; public Result addEntry(PhoneBookEntry entry) { ... } public Result updateEntry(PhoneBookEntry before, PhoneBookEntry after) { ... } public Result deleteEntry(PhoneBookEntry entry) { ... } public Iterator findAll() { ... } public PhoneBookEntry findByPhoneNumber(PhoneNumber value) { ... } public Iterator findByName(Name value) { ... } public Iterator findByAddress(Address value) { ... } // Domain-specific Algorithms ... } Enable/Disable class PhoneBook { private List _entries; private Map _indexByPhoneNumber; private Map> _indexByName; private Map> _indexByAddress; public Result canAddEntry(PhoneBookEntry entry) { ... } public Result addEntry(PhoneBookEntry entry) { Result result = canAddEntry(entry); if (result.getStatus() == false) { return result; } else { ... } } public Result canUpdateEntry(PhoneBookEntry before, PhoneBookEntry after) { ... } public Result updateEntry(PhoneBookEntry before, PhoneBookEntry after){ Result result = canUpdateEntry(before, after); if (result.getStatus() == false) { return result; } else { ... } } public Result canDeleteEntry(PhoneBookEntry entry) { ... } public Result deleteEntry(PhoneBookEntry entry) { Result result = canDeleteEntry(entry); if (result.getStatus() == false) { return result; } else { ... } } public Iterator findAll() { ... } public PhoneBookEntry findByPhoneNumber(PhoneNumber value) { ... } public Iterator findByName(Name value) { ... } public Iterator findByAddress(Address value) { ... } // Domain-specific Algorithms ... }