Neither java.util.Queue nor java.util.Stack enforce queue or stack disciplines. As such they are unsuitable for teaching queues and stacks, and unsuitable for use in software engineering.
If I have a Stack that is shared among various modules, perhaps maintained by various people, I want to know that no one is accessing it beyond push and pop at the top. Otherwise, there is no way to have any confidence that any contract or class invariants are being maintained.
I have no issue with Stack methods empty(), peek(), pop(), or push(). My objection to search is minor: this isn't part of the idea of the stack, so it should not be in the public interface.
But Stack also inherits a number of methods from java.util.Vector, including removeElementAt() and insertElementAt(). This is not a stack. It can be used as a stack, but the programmer has no assurance that other pieces of code are treating it as a stack.
The Queue interface is not as bad. The interface's six methods make it look like the committees that added to it over time were a bit confused or at least not in agreement with one another, but, nonetheless, insertion is always at the tail, and removal is always at the head.
But Queue extends java.util.Collection, which adds a number of non-queue-like methods. Many of these methods allow treating a queue like a stream, which is more convenient than removing item-by-item, deciding if each item fits some criteria, and then adding those meeting the criteria back into a queue.
My main issue with java.util.Queue is shared with java.util.Stack: the is-a relation does not work. A subclass of either could satisfy the Liskov substitution principle, but the child would be neither stack nor queue.
One fix would be to define more reasonable Stack and Queue classes, and declare them final. What I really want is a way to declare an interface that restricts the addition of methods.
Showing posts with label OOP. Show all posts
Showing posts with label OOP. Show all posts
Monday, February 26, 2018
Monday, March 29, 2010
Private Data, Getters, Setters, and the Like
I'm not sure that I'm getting the rationale for class-level private declarations. Given that public "getters" and "setters" can access and even alter private data, what's the use of the private declaration in the first place?
Making data members private allows us to control access to them. First, most (probably) classes don't have setters and getters. Second, setters and getters can be instrumented so that accesses and changes can be tracked, logged, etc. This instrumentation can be useful for debugging. If a private field is getting set to a bad value, one just has to put debug code in the setter rather than hunting down every line that modifies the field.
Another reason, probably at least as important, is for maintenance, upgrades, etc. If I implement a structure with a private array today but later decide it should be a set or a list, I don't have to worry that the change will ripple through client code, breaking the installed base.
Finally, a class interface should have a specification, or a contract. If private data is being modified outside the class, it's not possible for the class to enforce the contract, and debugging the class spreads out from the class itself to the entire system. This complicates development and maintenance.
[suggested by a colleague an hour after I posted the above]
Setters can validate data, making sure it's in the correct range, consistent with other values, etc., before setting the field.
Making data members private allows us to control access to them. First, most (probably) classes don't have setters and getters. Second, setters and getters can be instrumented so that accesses and changes can be tracked, logged, etc. This instrumentation can be useful for debugging. If a private field is getting set to a bad value, one just has to put debug code in the setter rather than hunting down every line that modifies the field.
Another reason, probably at least as important, is for maintenance, upgrades, etc. If I implement a structure with a private array today but later decide it should be a set or a list, I don't have to worry that the change will ripple through client code, breaking the installed base.
Finally, a class interface should have a specification, or a contract. If private data is being modified outside the class, it's not possible for the class to enforce the contract, and debugging the class spreads out from the class itself to the entire system. This complicates development and maintenance.
[suggested by a colleague an hour after I posted the above]
Setters can validate data, making sure it's in the correct range, consistent with other values, etc., before setting the field.
Subscribe to:
Posts (Atom)