论坛首页 编程语言技术论坛

动态类型 or 健壮代码?That's a question

浏览 17331 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-06-14  
看到很多人在讨论提高语言的动态性,甚至有一篇帖子说语言的发展就是为了增强动态性,说实话我是一点也不明白,在我看来,大型、复杂的软件开发面临的一个很要命的问题就是复杂性太大,而强类型的语言能够很有力的提高代码的健壮性(当初我选择学习java的一个原因就是c可以根据内存结构随便cast,而java不考虑内存中的数据结构,首先要确保满足LSP,这在企业开发中可以最大限度的确保健壮性),如果要求“运行期改变变量类型”,那么程序员也许能够获得一点方便,但是这使得编译器甚至运行期解释器不能协助帮助我们判断代码是否正常,实在是得不偿失。
我请教了robbin,不过他的看法似乎与我一样,
robbin 写道
IDE可以在一定程度上进行语法和类型检查,不过总体来说,类型安全是动态语言的弱点之一。

我不相信大多数人不明白这个道理,但是动态语言却越来越流行,我也不知道自己什么地方弄错了,希望知道大家的看法。
   发表时间:2005-06-14  
我个人觉得这个问题是一个“仁者见仁,智者见智”的问题,我的看法是:静态类型的语言确实可以借助编译器或者IDE减少出错的可能性,但是也同时限制了我们生产力(看看到处的造型操作吧)。而动态类型的语言本身在这方面是有优势的,比如python,ruby等,这些语言的简练和可以完成的事情让我惊讶。脚本语言通常更能够拓展人的思维能力,写起来天马行空,无拘无束,这正是吸引我的地方。

有些人写程序是为了工作,有些人是为了享受。那么假如有人把写程序当成一种快乐的话,我相信他更能接受脚本语言的创造性。
0 请登录后投票
   发表时间:2005-06-14  
snowway 写道
我个人觉得这个问题是一个“仁者见仁,智者见智”的问题,我的看法是:静态类型的语言确实可以借助编译器或者IDE减少出错的可能性,但是也同时限制了我们生产力(看看到处的造型操作吧)。而动态类型的语言本身在这方面是有优势的,比如python,ruby等,这些语言的简练和可以完成的事情让我惊讶。脚本语言通常更能够拓展人的思维能力,写起来天马行空,无拘无束,这正是吸引我的地方。

先说说cast的问题,cast本身只是一个语法问题,关键是──编程语言允许在什么情况下cast。

我真正会的语言只有一个java,所以只能以java为例,java中的造型操作是满足LSP的,由于面向对象理论的保证,这种cast是可靠的,安全的。
一个例外是旧的colletion框架,由于以Object来处理,导致类型信息丢失,错误不能被发现,正是因为对这种错误深恶痛绝,所以tiger一出来的时候我是很欣赏它的泛型能力的,而现在,在进一步了解后,我们发现它为了考虑jvm的兼容把泛型作成了一个半吊子,又觉得有些可惜。
可见,正是由于类型信息的缺失为我们增添了麻烦,而在一个合理的分类层次体系中,cast操作是可靠而且意义的。我们可以讨论把cast这样的代码消除掉,但不等于把类型信息也弱化,这无异于自废武功。

软件开发不是完全的天马行空,就算只有一个人开发,你后面的代码也会受到前面的代码逻辑的约束,因此无拘无束恐怕不现实,强类型所能做的,就是尽可能的提醒你这些业已存在的约束。
snowway 写道
有些人写程序是为了工作,有些人是为了享受。那么假如有人把写程序当成一种快乐的话,我相信他更能接受脚本语言的创造性。

看了你的观点,我倒是同意要分情况讨论,不是不是按照写程序的目的(工作 or 享受),而是按照所开发程序的规模,少量的代码用弱类型语言(比如家中的电脑要自动做点事,我肯定用脚本),大规模的开发──虽然我也一样感到享受──还是应该用强类型语言。
只是这样说来,python和ruby这种东西的适用范围似乎就受到了相当的限制......
0 请登录后投票
   发表时间:2005-06-14  
刚才拿python做了一下实验,发现确实是不考虑类型信息的:
#!/usr/bin/python
# Filename: typed.py

class Teacher:
    '''Represents a teacher.'''
    def __init__(self, name, salary);:
        self.name = name
        self.salary = salary
        print '(Initialized Teacher: %s);' % self.name

    def tell(self);:
        print 'Teacher\'s Salary: "%d"' % self.salary

class Student:
    def __init__(self, name, sId);:
        self.name = name
        self.sId = sId
        print '(Initialized Student: %s);' % self.name

t = Teacher('Mrs. Shrividya', 400);
s = Student('John', 'S00001');

print # prints a blank line

t = s
t.tell();
这样,在运行时就会出错
fsword@family:~/workspace/python$ python typed.py
(Initialized Teacher: Mrs. Shrividya);
(Initialized Student: John);

Traceback (most recent call last);:
  File "typed.py", line 29, in ?
    t.tell();
AttributeError: Student instance has no attribute 'tell'

可以看到,这个错误不是t = s是发生的,而是t.tell()时发生的。

这倒也罢了,问题是如果Student类具有了tell方法,那么这个逻辑错误就会藏起来。
#!/usr/bin/python
# Filename: typed.py

class Teacher:
    '''Represents a teacher.'''
    def __init__(self, name, salary);:
        self.name = name
        self.salary = salary
        print '(Initialized Teacher: %s);' % self.name

    def tell(self);:
        print 'Teacher\'s Salary: "%d"' % self.salary

class Student:
    def __init__(self, name, sId);:
        self.name = name
        self.sId = sId
        print '(Initialized Student: %s);' % self.name
 
    def tell(self);:
        print 'Student\'s ID: "%s"' % self.name

t = Teacher('Mrs. Shrividya', 400);
s = Student('John', 'S00001');

print # prints a blank line

t = s
t.tell();

这时即使是runtime,我们也没有看到错误
fsword@family:~/workspace/python$ python typed.py
(Initialized Teacher: Mrs. Shrividya)
(Initialized Student: John)

Student's ID: "John"
真是不理解阿,对于简单的类型之间cast随便点也无可厚非,可是类之间也这样就太不好了,既然python有类型系统,为什么不用呢?而且还有很多人喜欢这样?
    
0 请登录后投票
   发表时间:2005-06-15  
在使用JavaScript得时候,弱类型让我很郁闷。
主要是需要合作,类型限制在那里就不言自明,没有类型限制,反而多出很多判断类型的代码来。

如果自己简单用用还是很简便的。

鱼和熊掌
0 请登录后投票
   发表时间:2005-06-15  
fsword 写道
软件开发不是完全的天马行空,就算只有一个人开发,你后面的代码也会受到前面的代码逻辑的约束,因此无拘无束恐怕不现实,强类型所能做的,就是尽可能的提醒你这些业已存在的约束。


我想你误会了我对“天马行空”的意思,我这里并不是说想到哪里写到哪里,程序还是必须应该有良好结构和合适模型的。脚本语言可以快速的实现原型,让语言最小限度的限制您自由发挥想象力的能力。

fsword 写道

看了你的观点,我倒是同意要分情况讨论,不是不是按照写程序的目的(工作 or 享受),而是按照所开发程序的规模,少量的代码用弱类型语言(比如家中的电脑要自动做点事,我肯定用脚本),大规模的开发──虽然我也一样感到享受──还是应该用强类型语言。
只是这样说来,python和ruby这种东西的适用范围似乎就受到了相当的限制......


我倒认为使用什么语言和开发规模有什么关系,虽然静态类型可以在一定程度上保证团对开发的连续性,但是我们同样要指定架构,编码规范等等。所以我觉得应该从人的因素上约束项目而不是依赖语言机制。

关于python等的应用范围我们就不需要担心了,反正在很多国外的机构,比如航天,数学,动画等都有广泛的应用,redhat的很多界面也是用python写的,还有如今流行的gmail的部分功能,并且python的应用还在大规模的增多。
0 请登录后投票
   发表时间:2005-06-15  
fsword 写道
刚才拿python做了一下实验,发现确实是不考虑类型信息的:
t = s
t.tell()


你举的例子不是很恰当,任何弱类型的语言都会有这个问题,这个可以说是缺点,也可以说是优点,按就是类型的动态转换,而且你说的问题,完全可以靠自动测试,以及实现的编程规约来解决。我也来举例说明一下动态类型的好处,就以Burlap协议的实现来说明:

Java使用Burlap时的代码如下:
URL url = new URL("http://www.caucho.com/burlap/test/basic");;

BurlapProxyFactory factory = new BurlapProxyFactory();;
Basic basic = (Basic); factory.create(Basic.class, url);;


需要手动的将实现类转换为Basic类,也就是调用方,需要很明确的知道返回的方法在哪个类中,如果实现类发生改变,那么客户端调用代码也要做调整。

再说具体实现类:
public class BasicService extends BurlapServlet implements Basic


必须要继承一个BurlapServlet ,然后再去实现一个Basic接口,实现方法无法很方便的重用。

而Python的优点就在这里了,调用代码只需如下:
proxy = Burlap("http://localhost:8080/buffalo/Hello");
print proxy.hello("Breeze");


而实现部分的函数,就是一个普通函数即可
def hello(str);:
  return "Hello "+str


我认为:
调用方不应关心具体返回的类型是什么,他们只应知道返回了一个对象,然后我有哪些约定好的方法可用。
0 请登录后投票
   发表时间:2005-06-15  
动态语言的流行是一个(至少目前看来)趋势,我不质疑这一点,我只是想知道在具体的、大型的开发中,是怎么避免它由于弱类型带来的麻烦。
snowway 写道
虽然静态类型可以在一定程度上保证团对开发的连续性,但是我们同样要指定架构,编码规范等等。所以我觉得应该从人的因素上约束项目而不是依赖语言机制。

这算是回答了我的一部分问题,不过我更希望知道大家自己的开发中是怎么解决的,有很多问题道理很容易懂得,但是实际做起来就会发现真正的困难。
而且“从人的因素上约束项目”等于是增加了一条捆绑程序员手脚的绳子,而这本来是没有必要的(我不赞成什么东西都要程序员自己注意,例如编码规范,一般情况下,大家使用同样的IDE配置文件,程序员就不需要时刻关心编码规范,久而久之就习惯了)。
0 请登录后投票
   发表时间:2005-06-15  
清风 写道

你举的例子不是很恰当,任何弱类型的语言都会有这个问题,这个可以说是缺点,也可以说是优点,按就是类型的动态转换,而且你说的问题,完全可以靠自动测试,以及实现的编程规约来解决。

是呀,我讨论的就是这个问题,弱类型语言的优点我们都知道,但是缺点在大型开发中变得十分致命,你能否具体说说你们在开发中是怎么通过自动测试(在我刚才举的例子中,runtime也未必能发现错误的)和编程规约来解决的?
清风 写道
我也来举例说明一下动态类型的好处

你这个例子恰好说明了我的意思,强类型语言通过接口的概念严格控制着程序的逻辑,同时又具有很好的扩展性,而弱类型语言虽然写起来很顺手,可是你甚至不能肯定你那个proxy有hello方法可以调用,那是很危险的。
清风 写道
我认为:
调用方不应关心具体返回的类型是什么,他们只应知道返回了一个对象,然后我有哪些约定好的方法可用。

“有哪些约定好的方法可用”不就是对象的接口类型吗?如果你的type信息丢失了,又怎么知道有哪些可访问的方法呢?
0 请登录后投票
   发表时间:2005-06-15  
t = Teacher('Mrs. Shrividya', 400);
s = Student('John', 'S00001');

print # prints a blank line

t = s
t.tell();


这个我觉得不能算作错误,因为你已经手动将Teacher改变成为了Student,类型已经发生了改变,再调用t.tell方法,等于是调用Student的tell方法,任何弱类型语言都是这样的。

怎么说呢,我觉得强类型语言的编译期检查肯定是好的,但这是语言特点决定的,无法改变的,再说类型转换,强类型语言是比较严格,但是经常需要配置文件来指明其实现类,造成配置文件的泛滥。对于经常变化异常灵活的业务处理,我个人觉得弱类型语言更适合做这个工作。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics