重复历史话题--GP

Jinhao 2008-06-22 01:50:54
现代程序开发最关注的一件事之一就是如何提高代码的可复用性。

OOP提供了抽象概念来构建一个统一的世界模型,具像的物理对象被实现在这个简单的抽象模型体系中,最终形成庞大的树型结构来覆盖由该抽象涉及到的方方面面,可复用性由此诞生。

GP提供了另类的复用方法,让算法与类型无关。

在大多数的开发中,GP的运用几乎为空白,其实这并不是坏现象,除了让部分代码变得稍微优雅,剩下的可以说在大部分情况下,GP都是画蛇添足。在开发中,我们努力用OO的知识和经验来创建类,让这些类对象相互协同工作来达到目的,一般情况下,我们是处在一个很小的问题域中着手解决具体的问题,不需要更多的思考,所以template关键字几乎可以不用出现在我们编写的代码当中。

在以往的观点中,GP和OOP就像两条平行线,一边是静态多态,一边是动态多态,这样的观点让很多人误解了GP,加上在实际工作中,几乎不写template关键字,从而加深了这种误解。

到底GP存在的意义在哪里?相信大多数C++程序员都会用到STL,正是GP造就了STL的应用如此广泛。GP是一种用来开发高效,高复用程序库的编程范式,所以在实际工作的大多数项目中,GP对我们来说可有可无。用GP来分析问题的三个步骤:
1,将抽象问题域分类成Concepts.
在STL中,迭代器按行为被分类成5类。Input/Output/Forward/Bidirectional/Random Access Iterator。

2,基于这些Concepts,设计泛型算法。
例如std::generate要求Forward Iterator,而std::next_perutation要求Bidirectional Iterator.

3, 创建Concepts的具体模型。
例如,std::vector的Iterator,std::map的Iterator。

其实GP的分析方式与OOP极其类似,都是由具体的事物寻找抽象,然后按抽象来设计,最后基于抽象实现具象。

那GP编写的泛型程序库到底好在哪里?
可复用性:
我们尝试用OO来实现vector
class oo_vector
{
public:
void push_back(vec_elem_t& r)
{
vec_elem_t * n = r.clone(*this);
//hold n ...
}
};

如果我们要使用oo_vector,那么存储的元素类型必须由vec_elem_t派生并实现clone方法。如果用C++ Templates来实现,复杂度自然降低。至少我们的元素类型不会出现派生自vec_elem_t, map_elem_t, list_elem_t等等这种庞大的多重继承的情况。

粘和性:
用上面的oo_vector来思考。如果有一个现成的类,要让oo_vector来操作,该怎么办?C++ Templates应用到这种情况下大大提高了粘和性和可复用性。

Templates把C++变得太“泛”了?
C++是强类型语言,继承确定了两个类的关系,这种关系可以某些方法作用于子类对象上,他们之间存在着一种限制。而对于一个泛型算法,它能接纳的模板参数T,从形式上,看不任何限制,但这会使你的代码编译失败。例如把std::list的iterator传递到std::find中,得到的编译错误是iterator缺少某某东西,在这种情况下,如果编译错误能提示list的iterator不能用在find里,这样就会友好很多。其实这不仅仅只是提示得友好,因为我们在设计这种泛型算法的时候就是依据上面提到的Concepts,这种 Concepts在目前的C++语言中,只是一个潜在限制,作为泛型库的使用者,很容易忽略掉这种限制。或许有人会认为,如果C++引入Concepts的限制来做类型的检查,那么它还会是GP吗?它仍然是GP,显而易见的,泛型库的设计是从Concepts出发的,这好比一个子类是从基类出发一样。

Concepts会是画蛇添足吗?
就算语言引入了Concepts,那么list的iterator仍然不能用到find中去,这和没有Concepts的情况完全一样。Concepts描述了一组抽象的行为,我们可以提供一个算法函数来处理具有这种行为的类型,它的引入会把人们的关注目光从围绕T上转移到Concept上,这能更好地表达每个抽象的核心思想。按Concepts来特化算法,比按类型来特化算法,是更好GP。在解决list::iterator应用到find的问题上,只需要特化一个符合list::iterator Concept的find即可。

现在看来GP和OOP似乎很相似了,从分析的角度来说,他们的方向是一样,只是方法不同。这两个范式的区别不像OOP和面向过程那样,立竿见影。或许说,GP和OOP都应该是一种“泛型”,GP是基于行为抽象,OOP则是基于事物抽象。在OO的设计中,我们仍然会考虑到行为这一问题,只不过从OO的角度来说,这太隐晦,而GP在这方面则表达得更好,更抽象。
...全文
373 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
laomai 2008-09-26
  • 打赏
  • 举报
回复
做个记号,以后慢慢看。
太乙 2008-06-23
  • 打赏
  • 举报
回复
mark~~~~~~~~
gogovista 2008-06-23
  • 打赏
  • 举报
回复
另,木有concept是不行滴
给源码结构加上一点点的抽象,就指望他了..........
gogovista 2008-06-23
  • 打赏
  • 举报
回复

真奇怪
明明是很互补的两东东
人们咋就喜欢搞成两端说捏??

OO代表紧绑定的语义、有二进制复用能力、有利于发现抽象
GP是松耦合、强检查类型、源代码级别的结构复用

俺觉得他两个是天生一对、地造一双......不然java c#也不会火烧火燎滴要加入泛型支持

多范型是个趋势.........
lily604 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用楼主 Jinhao 的帖子:]

GP是基于行为抽象,OOP则是基于事物抽象
[/Quote]
说的很好 觉得很有道理
fallening 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cunsh 的回复:]
想起一个帖子: 为什么GP更自然
http://groups.google.com/group/pongba/browse_frm/thread/e553a21476ba2ebd


[/Quote]

关注
femalelover 2008-06-22
  • 打赏
  • 举报
回复
前两期的<程序员>还说GP是反人类反自然反OOP的.
cunsh 2008-06-22
  • 打赏
  • 举报
回复
想起一个帖子: 为什么GP更自然
http://groups.google.com/group/pongba/browse_frm/thread/e553a21476ba2ebd

johnelf 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 cunsh 的回复:]
mark .
[/Quote]
cunsh 2008-06-22
  • 打赏
  • 举报
回复
mark .
femalelover 2008-06-22
  • 打赏
  • 举报
回复
感觉代码中要不要用GP, 能不能用到GP, 或者何时用OOP, 何时用GP, 是跟工作的具体内容相关的.

处理大量相似而不相同的对象, 用OOP, 处理大量相似而不机的任务, 用GP.
bellbird 2008-06-22
  • 打赏
  • 举报
回复
学习了 `
yuewei1231 2008-06-22
  • 打赏
  • 举报
回复
留着以后看!留着以后看!

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧