一位同事因为设计的几个类搞了几十个public的成员,被经理指责得一无是处,大家评评理!(0分)

  • 主题发起人 主题发起人 cpj7406
  • 开始时间 开始时间
个人觉得应该先看框架合理性,再看功能是否完善,最后看代码质量。如果仅仅因为代码
编写不是十分的“规范”(更要命的是,这个“规范”从来没有被强调过)而得出“一无是
处”的结论,似乎有些过分了。
作为经理,既然有自己的标准,那就应当写几页“规范”(当然,其中要解释不规范的害
处),然后让新人带着“规范”的概念看VCL之类的高手编写的代码并写点Demo,等基本上
上路了,再派发实际的任务。希望新手完全通过自己的阅读高手们的代码来提炼出正确的编
码规范——这对多数人来说非常不切实际。
 
对代码优劣的评判是个很困难的事情,creation-zy 点到的评判方法应该比较通行。

在这个帖子里提到的问题,实际上是一个基础概念问题,我觉得需要指出来告诉大家,这个问题就是:数据成员在类中扮演什
么角色?我曾经听 soul 谈起过这样一个事实,在 Delphi 的源代码中,数据成员连在 protected 段都不会出现。为什么要
这么严格地看待这个问题呢?因为,数据成员在面向对象中,仅仅只是类内为了类自己正常开展逻辑而存在,它是类私有的。而
一个类,不论它是处理一种行为,还是处理一个算法,在外在表现上它只表达外显行为。这就如同一个人体,心脏或者大脑是该人体
私有的,人本身以行为来表达自己。

那为什么我们会看到我们需要去操纵类内数据这样的行为呢?这是因为类的行为表现为类内数据的变化,对类内数据的控制,可以由类
表现为外在行为的改变,比如一个容器我们需要改变它的尺寸,我们就可以设置这个容器的高和宽,但需要明白,设置高和宽不是我们
真正需要的,真正需要的是我们需要改变容器的外在的尺寸表现,也就是说,任何可以改变容器尺寸的方法都可以用,只要它最终导致
了容器的尺寸按预期变化就行了。(比如我们可以执行一个“压扁”的方法,传入的参数也根本不是宽和高,而是牛顿值)

基于这样的观点,类的数据成员就不应该出现在 protected 段,当然更不应该出现在 public 段了。

而把数据成员直接暴露在 public 段,不仅表明是对类构成上存在认识问题,还表明类的架构、逻辑存在分离和布置上的问题(也可能
是偷懒和粗糙),这与通常生活中那句“我想把心掏出来给你看”遇到的情况是一样的,也就是这个类的设计已经变得不被其他类理
解了。(偷懒和粗糙是人品问题,涉及人文,不能归入技术讨论)

所以,强调不要把数据成员放到 public 段里,就如同强调不要把脑壳打开后出去吹风一样认真,而一个把数据成员放到 public 的类,
就如同先天性体外心脏一样,是一个重度残疾的病人。

有了这样一个明确的概念后,我想,一个认真认为自己是 coder 的人,打死也不会再把数据成员放到 public 去的,这根本不需要说教。
 
请说明是public域……浪费表情。如果是直接读写的域还真是不如直接放public。什么所谓软件工程都是搞毛的。
 
所有数据成员放在private域里是不容质疑的,但DELPHI的窗体设计,把所有控件放在published域就感觉不太好了,难道就为了个RTTI?
 
针对楼主的帖子,我觉得代码质量如何只是问题的一个表面现象,程序员在一年半的
时间里没有提高才是主要问题。
 
看了半天,技术上有待提高没错,可能也就一个入门的水平,不过让这个同事来设计类,这样的工作安排可能不是很恰当,让一个3岁小孩来舞大刀,不砍死自己就算不错了。
偶们单位搞1年半Delphi的可能也就这种水平,真正喜欢编程,热爱编程的新人现在是越来越少了,无奈啊...
 
nicai_wgl,招我去吧:)

public
FName: string;

private
FName: string;
public
property Name: string read FName write FName;
有什么区别吗?

既然没有区别为什么要把简单的一句换成复杂的两句?属性在这种情况下还有意义吗?

既然要对外公布,如果不需要对这个公布的属性做之前或者之后的检查,那么写在public里面又有什么不可?
在这种情况下所谓的属性就完全是教条主义。

我注意到在Java中并没有属性这个语法,数据成员全部都是私有的,对外公布的全部都用Setter或者Getter形式,代码可读性更强,造成的误解更小。

property,我认为已经成了Delphi的鸡肋
 
这样的经理随便发脾气,而且还当着其它同事的面[:(]
 
delphi是有属性的,可是像java那样没有属性怎么办?如果设计类要考虑到以后扩展和维护,就不应该让一个生手去设计类,其实我感觉delphi中的property属性只是对自身RTTI有用的,对编程不一定有用的,像Get和Set就可以控制了。
 
面对批评,习惯了就好,或者说麻木了就好。
 
To: muhx 好久不见啊,单位现在加工资了,你如果呆到现在应该有6-8K,不过也快到头了,老曹走私被抓了。
 
To: muhx:
我也有这种感觉:既然要对外公布,如果不需要对这个公布的属性做之前或者之后的检查,那么写在public里面又有什么不可?

要是我只是简单的赋值,写在public里有什么弊端呢????
感觉与get,set取接口一样,但属性似乎更直观
Test.SetSysTime(5)
Test.SysTime:=5;
感觉后者一看就知道是什么意思
当然如果前后有其他动作的另论
 
我觉得上面有很多人都不知道尊重他人
顺便问个问题,请高手指点下:
我编系统的时候也没听说public里不许有数据成员的啊。
也许是我看的东西少把,头次听说。
有什么书推荐下,好好看看
 
我好多时候public里也有变量的
 
Borland 的源代码确实是很高质量的,值得学习。
Delphi语法上没有禁止在public中申明数据成员,但是并不等于说在public中申明数据成员是好的。
如果申明为属性,那我们可以控制该属性是只读的或者可写的等等,并且可以防止通过指针引用,从而实现更好地封装,防止不该发生的或者不符合设计者要求的对象引用。
比如下面这个类
TTest = class(TObject)
private
FVarA: string;
public
VarB: integer;
property VarA: string read FVarA write SetVarA;
end;
...
对于属性VarA我们只能取值和赋值,其它的操作都在编译时被认为是非法的,并且,赋值的动作也可以由SetVarA过程进行控制

而对于VarB,我们除了可以随意修改它的值以外,还可以引用它的地址,就象这样:
var
mytest: TTest;
myvarb: integer;
begin
mytest:=TTest.Create;
myvarb:=@mytest.VarB;
myvarb^:=1231231;
ShowMessage(IntToStr(mytest.VarB));
mytest.free;
... ...
ShowMessage(IntToStr(myvarb^))
// 可能引发异常
end;
而这样的不正常引用不会被编译器发现,出错的时候也很难发现,当然,在这个例子里面很容易。

当年我第一次知道有属性这个概念的时候,真是Happy得不得了,不知道现在还有人会抗拒使用属性啊。。。
 
另外,Java的大多数语法是从C++继承而来的,它对属性的操作也是从C++那儿来的,Getter和Setter都要写代码。而在Delphi里申明一个属性,如果你不想写Getter或者Setter,那只要直接引用变量本身就好了,再加上数组属性和默认属性的设置,把程序的编写变得更简单。
 
属性很好,它有助于封装

public
FName: string;

private
FName: string;
public
property Name: string read FName write FName;

虽然在效果上没什么区别,甚至编译都产生一样的指令,但是如果哪天需要在给Name赋值时需要执行一些检查,那只好去找所有引用FName的代码,因为FName在public,可能不仅是你,而且有其它开发人员引用了.你怎么办?

设计一个类的接口是相当严肃的,直接把数据成员写在public,我也用过,不过,那只限于我自己使用的类, 或者是用来代替record的.即使以后不得不改变设计,也不会影响太大.一旦某个类或单元要公开给别人使用,接口必须是经过规划的.

大家可以看一看ASTA3.0的代码,ASTA功能固然强大,但是它的代码质量我可不敢苟同,直接把数据成员写在public段随处可见,当然,这不是主要的问题.主要的问题出在它的类接口的规划, 让人觉得是一大堆水平不一的人往里面随意地塞代码. 造成的问题是代码很难维护.
 
什么叫好,什么叫不好!
 
其实我上面的话并不是排斥property,只是反对太过于教条主义。
property最大的好处在于它的可阅读性和可维护性
理解面向对象比会使用Property更重要

我看了我的同事的一些代码,如果他的Public部分的property全是直接对数据成员(Field)的引用,那么我判断他对面向对象未必了解的十分清楚,只是人云亦云。

面向对象推荐对接口编程而不是对具体的类编程
Delphi也有自己的接口机制interface
在Delphi的接口语法中也可以声明property
我们知道接口中所有的成员都是Public的
也就是说你的property无法直接访问私有的数据成员,设计接口只能通过public的Setter或者Getter来实现
比如
property Name: string read GetName write SetName;
用户即能通过Name := 'muhx';赋值也能通过SetName('muhx');赋值
在这种情况下实际上这个Name就是冗余的设计了
完全可以去掉

结论:
如果使用Delphi来做RAD,那么在不影响可读性的前提下,使用属性没有坏处
如果要用Delphi来做系统级的设计,要考虑可维护、可阅读、易扩展等目标,使用面向对象来设计和开发,针对接口来编程而不是针对类来编程,那么就不要使用属性了,这会画蛇添足
 
To: aikede
"Test.SetSysTime(5) 方法一
Test.SysTime:=5
方法二
感觉后者一看就知道是什么意思
"

以前我也有这种感觉,方法二更直观
深入学习面向对象,觉得面向对象是对现实世界的抽象
实际上对系统的性能提高没有好处,好处在于让程序员更好更容易对问题理解。

回到上面说的问题,直观上来看方法二似乎更容易理解
但是从现实来看,方法一更接近现实社会。
举例来说我的身高是1米82
要改变成2米22该怎么办?
采用方法二
muhx.Height := 2.22;
但是现实中身高是我的固有属性,怎么能直接赋值呢?
采用方法一
muhx.SetHeight(2.22);理解起来是把我的身高变成2.22米,那怎么变的呢?在SetHeight里加个40厘米高跷好了。

说这么细致很容易引起我在抠细节,不实用的感觉,我其实只是想说面向对象是对现实的抽象。
用这种方法有什么好处呢?
在一个团队中看到赋值知道这是私有的,看到Setter和Getter知道这是属性,使得团队更好的阅读彼此的代码。

最后,推荐
《代码大全》第二版
《重构》
《Head First设计模式》中文版(也被翻译成《深入浅出设计模式》)

谢谢aikede对我跟帖的关注
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部