论坛首页 海阔天空论坛

今天老板的一个问题让我很无语

浏览 8424 次
精华帖 (0) :: 良好帖 (0) :: 灌水帖 (6) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-12-16  
早上老板看我的代码,其中一个方法我传了三个参数进来,老板告诉我要有面向对象编程的思想,不应该使用三个参数,应该把这三个参数弄成一个对象传进来。 我问老板,那我们是不是要把所有的代码都改一遍,把凡是有参数的都合并到一个对象传进来?老板说等我们有时间就这么重构一次。
   发表时间:2011-12-16  
就是咯,如果你那些参数都是一样的,而且都同类。那你以后改动你要把所有的都改一次。
用一个类,你就改一个地方。你说哪个安全呢?
0 请登录后投票
   发表时间:2011-12-16  
追求全对象会导致类太多。
0 请登录后投票
   发表时间:2011-12-16  
完全瞎扯淡。一个接口的定义应该这个接口所要表达的语义相吻合。

public boolean login(String name, String password);



public boolean login(User user);


这两端代码到底谁能够表达更好的语义?非常显然是前者。

User这个对象把一个login动作的实际需求屏蔽了!这在一个复杂的系统中是一个非常危险的事情。比如说,你这个系统中的login方法,未来要被其他的上层接口或者其他系统调用。当别人拿到login(User user)的时候就傻眼了,因为User这个对象中一定包含有其他的字段,对方在调用的时候怎么知道如何去populate这个user对象,你这个系统才能正确处理呢?如果没有注释的帮助,估计接口调用者会骂死你。

所以我认为你们老板的面向对象学真该好好补补课了。
2 请登录后投票
   发表时间:2011-12-16  
downpour 写道
完全瞎扯淡。一个接口的定义应该这个接口所要表达的语义相吻合。

public boolean login(String name, String password);



public boolean login(User user);


这两端代码到底谁能够表达更好的语义?非常显然是前者。

User这个对象把一个login动作的实际需求屏蔽了!这在一个复杂的系统中是一个非常危险的事情。比如说,你这个系统中的login方法,未来要被其他的上层接口或者其他系统调用。当别人拿到login(User user)的时候就傻眼了,因为User这个对象中一定包含有其他的字段,对方在调用的时候怎么知道如何去populate这个user对象,你这个系统才能正确处理呢?如果没有注释的帮助,估计接口调用者会骂死你。

所以我认为你们老板的面向对象学真该好好补补课了。


明显他们老板的意思是
public boolean login(LoginableUser user);

然后LoginableUser里只有String name, String password
0 请登录后投票
   发表时间:2011-12-16  
gtssgtss 写道

明显他们老板的意思是
public boolean login(LoginableUser user);

然后LoginableUser里只有String name, String password


要是他们老板连DTO是一个反模式都不能理解,那就没什么好说的了。
0 请登录后投票
   发表时间:2011-12-16  
downpour 写道
gtssgtss 写道

明显他们老板的意思是
public boolean login(LoginableUser user);

然后LoginableUser里只有String name, String password


要是他们老板连DTO是一个反模式都不能理解,那就没什么好说的了。

要我说javabean就已经是反模式了
0 请登录后投票
   发表时间:2011-12-16  
downpour 写道
完全瞎扯淡。一个接口的定义应该这个接口所要表达的语义相吻合。

public boolean login(String name, String password);



public boolean login(User user);


这两端代码到底谁能够表达更好的语义?非常显然是前者。

User这个对象把一个login动作的实际需求屏蔽了!这在一个复杂的系统中是一个非常危险的事情。比如说,你这个系统中的login方法,未来要被其他的上层接口或者其他系统调用。当别人拿到login(User user)的时候就傻眼了,因为User这个对象中一定包含有其他的字段,对方在调用的时候怎么知道如何去populate这个user对象,你这个系统才能正确处理呢?如果没有注释的帮助,估计接口调用者会骂死你。

所以我认为你们老板的面向对象学真该好好补补课了。


同意downpour的说法。函数定义接口应该暴露所有需要的参数上下文。
如果一定要用User复合结构,应该引入类似于这样的表达样式。login(user = { name, password} )。
关于这个问题,我恰好有些想法。函数定义时,参数应该清晰地展开。不过,在函数调用时,有些情况下(如参数个数较多,并且需要分在不同的过程中获取的时候),复合结构就有优势了。比如,这样的场景。

user = getUser(); // 获取所需要参数。user包含name和password两个字段。
login( user) 和 login( user.name, user.password) 这两种调用方式,那种更加方便呢?在我看来,login(user)比较方便。那么,能否两全呢?我恰好写了点东西。

《编程机制探析》第六章 面向对象
http://www.iteye.com/topic/1114088

这个帖子中的一个回复。

buaawhl 写道

说到了继承,借机再谈一下一些不成熟的想法。
继承虽然有一些弊端,但不可否认,继承有一个切实的好处——直接引入另一个类的上下文,即,子类可以直接使用父类的成员属性和方法。这实际上是通过方法表(我只关注虚方法表,这里指的也只是虚方法表)复制来实现的,子类直接获得了父类的公共接口。不过,这不是什么了不得的特性。一个类完全可以通过暴露内部类接口的方式直接提供其他类的接口。
继承值得一提的好处就是,子类调用父类方法,如同调用本类方法一样方便。比如,getName()。但是,调用内部对象的方法,就不那么方便了,必须每次都带上内部对象的引用。比如,o.getName()。
这种功能虽然很方便,但是,可能会引入各种问题。比如,我们熟知的override、overload、covariance问题、多重继承问题。Python和Ruby引入的mixin语法,更加轻便的实现了多重继承(引入多个方法表)的效果,但是,并没有避免多重继承的问题,比如,同名方法问题(同名后来者覆盖前者)。
以上是在类级别直接引入上下文(context)的功能。另外,在模块级别也存在类似功能。
一个模块引入另一个模块的功能,通常需要import之类的关键字。这方面,C++、C#的using namespace做得很好,比import做得好。Import进来的功能,必须带着外部模块的引用。比如,o.getName()。Using space既可以达到import的效果,也可以进一步达到直接引入的效果。可以直接调用getName。
Pascal有一个with语法,可以展开任何复合结构,在本作用域内直接调用复合结构中的成员,就好像调用本作用域内定义的局部变量一样。这种语法是我所知道的最为灵活的直接引入上下文的语法。值得借鉴。
我设想的faramita语法是这样:函数参数即上下文。
这种语法和curry语法结合在一起,就可以实现非常灵活强大的直接引入上下文功能。
假设一个函数:f (x, y, z) = x + y + z
那么,f(x = 1) (y = 2) (z = 3, x = 4),这个函数调用看起来只是一种curry形式,但是,实际上确是参数上下文的叠加复制。最终结果相当于f (x = 4, y = 2, z = 4) 的调用结果。这和curry的形式是一样的。
如果有一个tuple。t = (x = 2, y = 4, z = 6)
那么,f(t)的结果就是f(x = 2, y = 4, z = 6)的结果。
如果t1 = (z = 10) 。那么,f(t)(t1)的结果就是f(x = 2, y = 4, z = 10)的结果。
这种参数上下文的叠加复制,其实就相当于多层继承、多重继承中的方法表的叠加复制,因此,也完全能够达到同样的效果,而且,语义上更加清晰。


如果有了这样的语法,在函数定义的时候,可以清晰地声明所有参数,在函数调用的时候,可以直接使用复合结构。

3 请登录后投票
   发表时间:2011-12-16   最后修改:2011-12-16
buaawhl 写道
downpour 写道
完全瞎扯淡。一个接口的定义应该这个接口所要表达的语义相吻合。

public boolean login(String name, String password);



public boolean login(User user);


这两端代码到底谁能够表达更好的语义?非常显然是前者。

User这个对象把一个login动作的实际需求屏蔽了!这在一个复杂的系统中是一个非常危险的事情。比如说,你这个系统中的login方法,未来要被其他的上层接口或者其他系统调用。当别人拿到login(User user)的时候就傻眼了,因为User这个对象中一定包含有其他的字段,对方在调用的时候怎么知道如何去populate这个user对象,你这个系统才能正确处理呢?如果没有注释的帮助,估计接口调用者会骂死你。

所以我认为你们老板的面向对象学真该好好补补课了。


同意downpour的说法。函数定义接口应该暴露所有需要的参数上下文。
如果一定要用User复合结构,应该引入类似于这样的表达样式。login(user = { name, password} )。
关于这个问题,我恰好有些想法。函数定义时,参数应该清晰地展开。不过,在函数调用时,有些情况下(如参数个数较多,并且需要分在不同的过程中获取的时候),复合结构就有优势了。比如,这样的场景。

user = getUser(); // 获取所需要参数。user包含name和password两个字段。
login( user) 和 login( user.name, user.password) 这两种调用方式,那种更加方便呢?在我看来,login(user)比较方便。那么,能否两全呢?我恰好写了点东西。

《编程机制探析》第六章 面向对象
http://www.iteye.com/topic/1114088

这个帖子中的一个回复。

buaawhl 写道

说到了继承,借机再谈一下一些不成熟的想法。
继承虽然有一些弊端,但不可否认,继承有一个切实的好处——直接引入另一个类的上下文,即,子类可以直接使用父类的成员属性和方法。这实际上是通过方法表(我只关注虚方法表,这里指的也只是虚方法表)复制来实现的,子类直接获得了父类的公共接口。不过,这不是什么了不得的特性。一个类完全可以通过暴露内部类接口的方式直接提供其他类的接口。
继承值得一提的好处就是,子类调用父类方法,如同调用本类方法一样方便。比如,getName()。但是,调用内部对象的方法,就不那么方便了,必须每次都带上内部对象的引用。比如,o.getName()。
这种功能虽然很方便,但是,可能会引入各种问题。比如,我们熟知的override、overload、covariance问题、多重继承问题。Python和Ruby引入的mixin语法,更加轻便的实现了多重继承(引入多个方法表)的效果,但是,并没有避免多重继承的问题,比如,同名方法问题(同名后来者覆盖前者)。
以上是在类级别直接引入上下文(context)的功能。另外,在模块级别也存在类似功能。
一个模块引入另一个模块的功能,通常需要import之类的关键字。这方面,C++、C#的using namespace做得很好,比import做得好。Import进来的功能,必须带着外部模块的引用。比如,o.getName()。Using space既可以达到import的效果,也可以进一步达到直接引入的效果。可以直接调用getName。
Pascal有一个with语法,可以展开任何复合结构,在本作用域内直接调用复合结构中的成员,就好像调用本作用域内定义的局部变量一样。这种语法是我所知道的最为灵活的直接引入上下文的语法。值得借鉴。
我设想的faramita语法是这样:函数参数即上下文。
这种语法和curry语法结合在一起,就可以实现非常灵活强大的直接引入上下文功能。
假设一个函数:f (x, y, z) = x + y + z
那么,f(x = 1) (y = 2) (z = 3, x = 4),这个函数调用看起来只是一种curry形式,但是,实际上确是参数上下文的叠加复制。最终结果相当于f (x = 4, y = 2, z = 4) 的调用结果。这和curry的形式是一样的。
如果有一个tuple。t = (x = 2, y = 4, z = 6)
那么,f(t)的结果就是f(x = 2, y = 4, z = 6)的结果。
如果t1 = (z = 10) 。那么,f(t)(t1)的结果就是f(x = 2, y = 4, z = 10)的结果。
这种参数上下文的叠加复制,其实就相当于多层继承、多重继承中的方法表的叠加复制,因此,也完全能够达到同样的效果,而且,语义上更加清晰。


如果有了这样的语法,在函数定义的时候,可以清晰地声明所有参数,在函数调用的时候,可以直接使用复合结构。


user.login才是面向对象啊
我觉得数据库和业务是典型的桥接关系
0 请登录后投票
   发表时间:2011-12-17  
downpour 写道
gtssgtss 写道

明显他们老板的意思是
public boolean login(LoginableUser user);

然后LoginableUser里只有String name, String password


要是他们老板连DTO是一个反模式都不能理解,那就没什么好说的了。

如果从OO的角度上说,LoginableUser这样的接口肯定是对的方案,但是老实说,我从来没这么写过。因为这个LoginableUser看不到被复用的场景,或者复用的场景太少了(即使被复用,一般只能在重构时体现,除非是在写一个security框架,否则很难预见)
DTO不是反模式,问题是创建很多只用一次的interface。
0 请登录后投票
论坛首页 海阔天空版

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