4 ms·
In a purely oop language, data structures exist as an implementation detail, but you can never access them directly (as in, bypassing the object interface). Tha
by danmaz74 7y ago
In a purely oop language, data structures exist as an implementation detail, but you can never access them directly (as in, bypassing the object interface). That's by design.
- hudon 7y agoI get that in your application, you may want to keep a linked list behind its interface 90% of the time. However, considering your system as a whole, at some point you may want to take that linked list data and write it to a database, in which case the cleanest thing is to bypass the interface and extract the "data structure object" so to speak and deal with it in a database-related object, rather than encumbering your LinkedList object with database behaviors.
- pault 7y agoI have these kinds of arguments with my C# co-workers all the time, and they usually have some annoyingly reasonable solution like "create a database serialization class with a linked list consumer". :)
- wvenable 7y ago> in which case the cleanest thing is to bypass the interface and extract the "data structure object" That doesn't seem like the cleanest to me. Instead, you'd use the interface to read/write to the list as you write/read it to storage. At no time do you want to reach into the LinkedList object and access it's internal mechanism.
- jayd16 7y agoThis is a violation of OOP. Instead, consider methods that produce and consume a serialized representation of the data instead. Things like Java serialization and Python pickle attempt to do what you say and are considered failures (or at least security risks) because they allow a third party to act on object implementation internals. Security aside, a denormalized representation of data could be different than the implementation specific representation that's encapsulated inside an object.
- Silhouette 7y agoBut this is partly a self-made problem, because in this OOP model you have decided that the internal representation of your data is to be hidden and therefore the data is only accessible via the provided interface. In practice, it is debatable how often that is helpful when you're implementing generic data structures. An alternative is to specify the representation explicitly and provide a set of functions designed to work with it, but also to allow direct access by other functions when that is useful. You can still build a layer of more abstract interfaces on top and write more generic algorithms in terms of those interfaces rather than any specific concrete representation, as for example Haskell's typeclass system does.
- jayd16 7y ago>An alternative is to specify the representation explicitly and provide a set of functions designed to work with it, but also to allow direct access by other functions when that is useful. I don't see that as an alternative. I consider this natural OOP. You don't lose anything by strictly enforcing the encapsulation because you can always explicitly provide low level methods into the data structures. Conversely, you lose all safety when you open up encapsulation. The method API of an object is the contract it provides. If you go around that contract it's much harder to make safe implementation changes. Because of this, low level access should be opt in, in the way you describe.
- Silhouette 7y agoYou don't lose anything by strictly enforcing the encapsulation because you can always explicitly provide low level methods into the data structures. But then you're not really gaining anything either, unless perhaps you have some mechanism to enforce that the low-level access should only be used in specific circumstances when it is deliberately intended. It's like writing classes that have a few data members, but then writing direct get and set accessors for each of them anyway. There's no more complicated invariant that you're enforcing at that point, and without any non-trivial invariants to be enforced, the whole argument for encapsulation and data hiding becomes moot. Conversely, you lose all safety when you open up encapsulation. The method API of an object is the contract it provides. Do you always need that safety, though? If your data is defined to be stored in a certain representation, and direct access to that underlying representation in that format is available if needed, isn't that representation now just another part of the contract? Again, you're balancing two competing priorities: is there some invariant to be enforced that is sufficiently complicated for data hiding to be a useful safeguard, and is it useful to interact efficiently with, or make safe assumptions about performance based on, the true data representation? Which one is the more important consideration must surely depend on how complicated your representation and any related invariants are. Being able to pattern match against values of some relatively simple algebraic data type can be very useful, for example. On the other hand, it's not much fun to accidentally corrupt the super-efficient look-up structure at the heart of your whole system that now uses a complicated set of hash tables and the odd Bloom filter internally after someone spent three weeks optimising it for a 50% speed boost.
- ivan_gammel 7y agoThis reminded me of design antipattern “Public Morozov”, named after Soviet pioneer Pavlik Morozov, who denounced his father to the secret police. In this design antipattern implementation details are exposed via convenient public methods.
- marcosdumay 7y agoIt's one of the most efficient ways. But it's not the cleanest way by any measure. It has tighter internal coupling than any other easy to imagine way. Most of the times, people will use the list normal interface to take the data. If performance is a requirement, most OOP people will create a database interface, that the linked list class can write without taking outside of its interface. Most FP people would do it the other way around, and create an interface to applying data to a function that the list can implement. Either way, it can tie with the dirty introspection in performance.
- stcredzero 7y agoIn a purely oop language, data structures exist as an implementation detail, but you can never access them directly In Smalltalk, you can have a TreeNode class and instantiate TreeNode instances. This is often the way that binary trees are implemented in Smalltalk. In that case, data structures exist as a design of interacting objects. In that case, you can molest them fairly directly using the object interface. The same goes for Java and C#. Basically, you can design in such a way, that you can essentially have C or Fortran in any language, even a pure OO language like Smalltalk. The right way to do this in Smalltalk, is to use a Facade, which can be used to hide the guts of your data structure.