列举下面这段程序10个设计问题(从concise, correctness, clarity, maintainability, optimality角度考虑)(可假设Content, ContentField 类已存在)import java.util.*;public abstract class ContentMap {
private static final int MAX_LENGTH = 65535;
private String data1;
private String data2;
private String data3;
private final int numFields;
public ContentMap(final Content content, final int numFields) {
this.numFields = numFields;
if (content != null) {
for (int i = 1; i <= numFields; i++) {
final ContentField field = content.getField(i);
if (field != null)
setData(i, field.getData());
}
}
} public void displayField(final int dataNum) {
final StringBuffer buf = new StringBuffer();
if (getData(dataNum) != null && getData(dataNum).length() >MAX_LENGTH) {
buf.append(getData(dataNum).substring(0, MAX_LENGTH));
} else {
buf.append(getData(dataNum));
}
System.out.println(buf.toString());
} public List<String> getFields() {
final List<String> fields = new ArrayList<String>();
for (int i = 1; i <= numFields; i++) {
fields.add(getData(i));
}
return fields;
} public void setData(final int dataNum, final String data) {
switch (dataNum) {
case 1:
data1 = data;
break;
case 2:
data2 = data;
break;
case 3:
data3 = data;
break;
default:
break;
}
} public String getData(final int dataNum) {
switch (dataNum) {
case 1:
return getData1();
case 2:
return getData2();
case 3:
return getData3();
default:
return "";
}
}
public String getData1() {
return data1;
}
public void setData1(final String data1) {
this.data1 = data1;
}
public String getData2() {
return data2;
}
public void setData2(final String data2) {
this.data2 = data2;
}
public String getData3() {
return data3;
}
public void setData3(final String data3) {
this.data3 = data3;
}
}

解决方案 »

  1.   

    我对这类问题最感兴趣了,粗浅提了12条,
    我的终极问题是:
    这个类本身存在的价值不大。
    import java.util.*;/**
     * 第七点:代码总体风格应该保持前后一致,如getData和setData两个方法中,对switch逻辑的处理风格完全不同。
     * 第八点:几乎所有变量和参数都是final,有必要吗?
     * 第十二点:整个类的意义是什么,还不如直接使用Content这个类来封装这些方法。
     * @author jinxfei
     *
     */
    public abstract class ContentMap {
    private static final int MAX_LENGTH = 65535;
    private String data1;//第一点:data1 data2 data3的命名让人疑惑
    private String data2;
    private String data3;
    private final int numFields; /**
     *第二点:Content既然已经封装成类,则numFields不应该作为独立变量传进来,这样不易保证程序完整性
     *第十一点:如果这个对象构造的时候numFields>3,数据丢失,因为getFields方法会将超出的数据返回为空串。既然定死只有data1-3,那么应该在这个方法中做长度检查
     * @param content
     * @param numFields
     */
    public ContentMap(final Content content, final int numFields) {
    this.numFields = numFields;
    if (content != null) {
    for (int i = 1; i <= numFields; i++) {
    final ContentField field = content.getField(i);
    if (field != null)
    setData(i, field.getData());
    }
    }
    } /**
     * 第四点:根据这个方法的逻辑,使用StringBuffer的意义不大,反而会增加程序的可读性
     * 第五点:getData(dataNum)被多次调用,增加了不必要的开销
     * @param dataNum
     */
    public void displayField(final int dataNum) {
    final StringBuffer buf = new StringBuffer();
    if (getData(dataNum) != null && getData(dataNum).length() > MAX_LENGTH) {
    buf.append(getData(dataNum).substring(0, MAX_LENGTH));
    } else {
    buf.append(getData(dataNum));
    }
    System.out.println(buf.toString());
    } public List<String> getFields() {
    final List<String> fields = new ArrayList<String>();
    for (int i = 1; i <= numFields; i++) {
    fields.add(getData(i));
    }
    return fields;
    } /**
     *第三点:既然已经有data1-3的set get方法,该方法内不应该再给data1-3直接赋值。
     *第九点:由于dataNum不为1/2/3时,程序实际上没有执行任何动作,数据被丢弃,但没有任何提示,不利于调试发现问题,建议抛出异常
     * @param dataNum
     * @param data
     */
    public void setData(final int dataNum, final String data) {
    switch (dataNum) {
    case 1:
    data1 = data;
    break;
    case 2:
    data2 = data;
    break;
    case 3:
    data3 = data;
    break;
    default:
    break;
    }
    } /**
     * 第六点:该方法功能没问题,但建议遵循单点返回的原则,不应在每个case中return。
     * 第十点:当dataNum超过范围后,返回空串,无法判断是数据本身就是空串,还是dataNum超限,建议抛出异常
     * @param dataNum
     * @return
     */
    public String getData(final int dataNum) {
    switch (dataNum) {
    case 1:
    return getData1();
    case 2:
    return getData2();
    case 3:
    return getData3();
    default:
    return "";
    }
    } public String getData1() {
    return data1;
    } public void setData1(final String data1) {
    this.data1 = data1;
    } public String getData2() {
    return data2;
    } public void setData2(final String data2) {
    this.data2 = data2;
    } public String getData3() {
    return data3;
    } public void setData3(final String data3) {
    this.data3 = data3;
    }
    }
      

  2.   

    第四点:根据这个方法的逻辑,使用StringBuffer的意义不大,反而会增加程序的可读性应为:反而会降低程序的可读性
      

  3.   

    这样的“非技术”问题,版主其实应该多加一些推荐。我感觉我的回答还是很到位的(得意ing)。