2013年8月

编程中的硬编码问题

在计算机程序或文本编辑中,硬编码是指将可变变量用一个固定值来代替的方法。用这种方法编译后,如果以后需要更改此变量就非常困难了。大部分程序语言里,可以将一个固定数值定义为一个标记,然后用这个特殊标记来取代变量名称。当标记名称改变时,变量名不变,这样,当重新编译整个程序时,所有变量都不再是固定值,这样就更容易的实现了改变变量的目的。尽管通过编辑器的查找替换功能也能实现整个变量名称的替换,但也很有可能出现多换或者少换的情况,而在计算机程序中,任何小错误的出现都是不可饶恕的。最好的方法是单独为变量名划分空间,来实现这种变化,就如同前面说的那样,将需要改变的变量名暂时用一个定义好的标记名称来代替就是一种很好的方法。通常情况下,都应该避免使用硬编码方法。

java小例子: int a=2,b=2;

硬编码:if(a==2) return false;

不是硬编码 if(a==b) return true;

一个简单的版本:顾名思义, 就是把数值写成常数而不是变量.

如求圆的面积的问题 PI(3.14)

3.14*r*r (这个3.14就是hardcode)

V_PI*r*r (这里的V_PI用的是变量形式,就不是hardcode).

 

 

硬编码对于程序员来说都不陌生,只是个很简单的概念,但是它却常常出现在N多程序中.
在开发的时候,开发人员有时候图方便,赶进度,或者想不到更好的方法,只好将某些业务逻辑固定死,常见如下判断
if (a == "拟制中"){ .... }
也许好一些的会用数字代替 比如用个"02"代替,也许程序跑个1两个月甚至一两年都没问题
但是需求更改或者用户环境变化了,那问题就会暴露,而且影响是明显的.
比如用户改成英文环境了,变量a的值变成了英文字符串"drafting",那么这个判断就不成成立了,如果这个判断是涉及到流程,这一步出错,程序再往下走也就是一错再错.也许有人说,不用字符串判断,改成数字就可以避免,但是也许某天这个数字跟其他业务逻辑发生重叠,那还是没实现根治,解决方法我相信大伙都明白,其实只是简单的设置一个变量保存常量,比如
string Drafting = "拟制中", if (a == Drafting){ .... }
那么a的值改了,相应修改drafting的值,哪怕是a变成英文,也可以事先改变好Drafting的值,这样简单处理,即可实现编码更改的无缝兼容,让编码变"软"了.当然前提是在开发的时候就做好.

再比如某些系统设计到人员权限等信息,某某单据必须让管理员甲审核,开发时管理员是甲,但是不久甲离职或调动了不当管理员了,但是系统审核的单据信息还是发给甲,如果甲的人员信息还保存在数据库中,程序还能跑,而实际上HR会毫不留情的删除掉甲的信息并且不通知开发人员.这样程序还继续执行的话,要么抛个空指针异常,要么抛个范围溢出异常,影响后续流程.而事实上,只要设置一个管理员标记,或者动态给个方法获取管理员,也就省了后续麻烦

当然硬编码的现象并不是仅仅出现在逻辑判断中,比如javascript,如果写的脚本仅仅能在IE运行,那么也就成了典型的硬编码了,诸多现实的例子就不举例了.所以,对于程序员来说,硬编码好比是程序的硬伤,追根到底不仅编码人员有责任,设计人员也因改意识到根据用户需求展开可扩展的设计.

Java包的静态导入import static和import的区别

import static静态导入是JDK1.5中的新特性。
一般我们导入一个类都用 import com.....ClassName;
而静态导入是这样:import static com.....ClassName.*;

这里的多了个static,还有就是类名ClassName后面多了个 .* ,意思是导入这个类里的静态方法。

当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。
然后在这个类中,就可以直接用方法名调用静态方法,而不必用ClassName.方法名 的方式来调用。

这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(...);
就可以将其写入一个静态方法print(...),在使用时直接print(...)就可以了。

但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便

example:
在Java 5中,import语句得到了增强,以便提供甚至更加强大的减少击键次数功能,虽然一些人争议说这是以可读性为代价的。
这种新的特性成为静态导入。
当你想使用static成员时,可以使用静态导入(在API中的类和你自己的类上,都可以使用该特性)。下面是静态导入前后的代码实例:

在静态导入之前:

public class TestStatic {
    public static void main(String[] args) {
       System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.toHexString(42));
    }
}

在静态导入之后:

import static java.lang.System.out;
import static java.lang.Integer.*;

public class TestStaticImport {
    public static void main(String[] args) {
        out.println(MAX_VALUE);
        out.println(toHexString(42));
    }
}

两个类都产生相同的输出:
2147483647
2a
让我们看一下使用静态导入特性的代码中将发生什么:

  1. 虽然该特性通常称为“静态导入”,但语法必须是import static,后面跟你想导入的static成员的完全限定名称,或者通配符。在本例中,我们在System类的out对象上进行静态导入。

  2. 在本例中,我们可能想使用java.lang.Integer类的几个static成员。该静态导入语句使用通配符来表达“我想在此类中的所有静态成员上进行静态导入”。

  3. 现在我们终于看到静态导入特性的好处!我们不必在System.out.println中键入System。太好了!另外,我们不必在Integer.MAX_VALUE中键入Integer。因此,在这行代码中,我们能够将快捷方式用于静态方法和一个常量。

  4. 最后,我们进行更多的快捷操作,这次针对Integer类的方法。

关于该特性,我们已经有点儿讽刺意味儿了,但不仅我们是这样的。我们不认为节省少量的击键次数会让代码难于阅读一点,但许多开发人员要求将它添加到语言中。

下面是使用静态导入的几条原则:

你必须说import static, 不能说static import。
提防含糊不清的命名static成员。例如,如果你对Integer类和Long类执行了静态导入,引用MAX_VALUE将导致一个编译器错误,因为Integer和Long都有一个MAX_VALUE常量,并且Java不会知道你在引用哪个MAX_VALUE。
你可以在static对象引用、常量(记住,它们是static 或final)和static方法上进行静态导入。