Note of CLEAN CODE chapter 6 -Object / Data Structure

Why do we keep variablas privates? We do not want anyone else to depend on them. We want to keep the freedom to change their type or implementation on a whim or an impulse.

Why do so many programmers automatically add setters and getters to their objects exposing their private variables as if they were public?

Data Abstraction

//this class exposes the variables
public class Point{
    public int x;
    public int y;
}

It is supposed to be used in rectangular coordinate, and it forces us to manipulate those coordinates independetly. Even if the variables are private, we were using single variable getters and setters.

public interface Point{
    int getX();
    int getY();
    int getR();
    int getTheta();
    void setCartesian(int x, int y);
    void setPolar(int r, int theta);
}

The latter one uses interface to represents a data structure and you can use it for rectangular or polar coordinates.

But ir represents more than just a data structure. Methods enforce an access policy. You can use one coordinate individually but you have to set coordinates together as an atomic operation

Hiding implementations is about abstraction(putting a layer of functions among variables) A class is not merely pushing out variables through setters and getters, rather allosw its user to manipulate the essence of data, without having to know the implementation.

public interface Vehicle{
    double getFuelTankCapacity();
    double getGasolineVolume();
}

This one uses concrete terms to communicate the level of a vehicle, whereas the second one does so with an abstraction of percentage.

public interface Vehicle{
    double getPercentageFuelRemaining();
}

The second is preferable because we do not need to expose data details, instead we wan to express them in an abstraction or abstract terms.

It is implemented not merely by getters and setters (It is the worst option), but serious thoughts need to be put into put into the best way to represent the data that an object contains.

Data Object Anti-Symmetry

public class Square{
    public Point leftTop;
    public int sideLength;
}

public class Circle{
    public Point center;
    public int radius;
}

public class Geometry throws  NoSuchShapeExceptio{
    public int area(Object shape){
        if(shape instanceof Square){
            return shape.sideLength * shape.sideLength;
        }
        else if(shape instanceof Circle){
            return shape.radius * shape.radius * Math.pi;
        }
        else{
            throw new NoSuchShapeException();
        }
    }
}

Data structure expose their data and have no meaningful functions. (Process oriented design) All behaviors is in the Geometry class

public class Square implements Shape{
    public Point leftTop;
    public int sideLength;
    public int area(){
        return sideLength * sideLength;
    }
}

public class Circle implements Shape{
    public Point center;
    public int radius;
    public int area(){
        return radius * radius * Math.pi;
}

For the object-oriented programmers, if a new class is added, you do not have to change all functions in Geometry. In contrary, if you add something in Geometry, Circle and Square are not affected.

As we see the complimentary nature of these two definitions, they are virtually opposite.

  • PO code makes it easy to add new functions without changing existing data structures, but hard to add new data structures because all functions have to change.
  • OO makes it easy to add new classes without changing existing function, but hard to add new functions because all the classes must change.

The Law of Demeter

An object should not expose its internal structure through accessors.

A method f of a class C should only call the methods of these

  1. C
  2. Objects created by f
  3. Objects passed as arguments to f
  4. Objects held in an instance variable of C

It should not invoke methods on objects that are returned by any allowed functions.

Following code violates this rule, because it invoke getDir from the object return by getOption

ctxt.getOption().getDir().getAbsolutePath();

Train Wrecks

Chains of calls are sloppy style and should be avoided (split them)

Option o = ctxt.getOption();
Direction d = o.getDir();
String dir = d.getAbsolutePath();

Whether it is a violation of The Law of Demeter depends on whether Option and Direction are objects or data structures.

If they are objects, knowledge of their innards is absolutely violation.

On the other hand, if they are data structures without behavior, The Law of Demeter does not apply. Like this

ctxt.Option.dir.absolutePath;

Hybrids

Don’t make your class half of objects and half of data structures.

It will make it hard to add new functions but also make it hard to add new data sctructures.

(BTW, DS is more like struct in C language, without any behavior(or you can only use getters or setter in this struct), while an object focuses on the behavior but ignore the components)

(If you can get or set the variables about a class and use other class functions, it is a hybird~~)

Hiding Structure

If o, d and ctxt are objects with real behaviors, they should hide their internal structure like these;

ctxt.getAbsolutePathOfDirectionOption();

ctxt.getScratchDirectoryOption().getAbsolutePath(); // this one presumes getScratchDirectoryOption() returns a data structure

If we still need to do something to the result dir like this

String outputFile = dir + "/" + name.replace(".", "/") + ".class";
FileOutputStream fo = new FileOutputStream(outputFile);

The admixture of different levels of details is troubling. In the case, why not just put them into a function?

FileOutputStream fo = ctxt.createFileOutputStream(classFileName);

Data Transfer Objects

The quintessential form of data tranfer objects is a class with public varibales and no function(Or java bean form, but from author’s perspective, it provides no benefit).

The form is useful in communicating with database and parsing message from sockets.

Active Record

It is a special form of DTO, a type of data structure with public variables(or bean form) but have navigational methods like save and find.

They are typically translations from database tables or other data structures.

Conclusion

Good software developers will understand issues in OOD and POD without prejudice and choose the best approach that is appropriate for the job at hand.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值