In Clean Code:
public class Point {
public double x;
public double y;
}
The author wrote about the above Point()
class:
This exposes implementation. Indeed, it would expose implementation
even if the variables were private and we were using single variable
getters and setters.
This means I must burn my school copybooks.
Why is combining getters, setters and private access modifier not enough?
Best Answer
The example given, of a
Point
class with two public members of typedouble
namedx
andy
, exposes its implementation by allowing anyone who has an object of typePoint
to know about its implementation. In this case, the entire implementation is exposed.If you changed the public members to private and created a pair of getters and setters, you still expose its implementation. If you look at the interface of an object and see that it has methods like
double getX()
,double getY()
,setX(double x)
, andsetY(double y)
, then you aren't going to be sitting there thinking, "Gee, I wonder how they implemented that. I can't tell."The second version of
Point
isn't really different from the first one, except that in most languages it will have a lot of unnecessary boilerplate. In both cases, looking at the object's interface tells you about how it is implemented.If we wanted to change the internal representation of a
Point
to polar coordinates, we run into problems. We can still use the old interface, but it's clunky. A call tosetX()
is going to have to do an internal conversion to rectangular coordinates, change x, and then convert back to polar, introducing unnecessary rounding errors and extra computations.If we had started out by designing an interface for a
Point
without reference to an implementation, we wouldn't have that sort of problem. Say we decide that a point has an x and y coordinate, and also an angle and magnitude. We could havedouble x()
,double y()
,double angle()
, anddouble magnitude()
methods. We could make them immutable, but let's say we didn't. So we needrectangular(double x, double y)
andpolar(double angle, double magnitude)
to move the point.What do we know about the implementation? Well, we know something, since a two-dimensional point is a very simple thing, but we don't know whether the object's internal representation is in polar or rectangular coordinates. The internal representation might even include both polar and rectangular coordinates, either with booleans to keep track of whether a particular set of coordinates is up to date, or else forcing everything to always be up to date automatically.
So in this case the implementation isn't exposed, since we can only guess how it was implemented.