如果客户要求您不要使用面向对象的编程,您将怎么办?


31

我正在编写一个程序来模拟网格中蚂蚁活动(PDF)。蚂蚁可以四处走动,捡东西和丢东西。

问题是,虽然可以通过类属性轻松地跟踪蚂蚁的动作和每个蚂蚁的位置(并且我们可以轻松地创建此类蚂蚁的许多实例),但我的客户说,由于他具有函数式编程的背景,因此他希望使用功能编程进行仿真。

需要明确的是,来自客户端的原始词语仅是“ no class”,而不是“ function programming”。因此,我认为他并不意味着函数式编程,我势在必行。另外,我没有函数编程的经验。

但是,我认为专注于这个问题,特别是关于功能性编程要求,而不只是简单地“必须执行”,这是有益的。

您将如何处理这种情况?您是否会说服客户使用面向对象的编程更清洁,尝试遵循他的要求并为他提供劣质的代码,或者做其他事情?


9
可能会改变主意的一件事是,这样做的代价是否更高(如果您比功能编程语言更精通OO语言)。
Holger

在Clojure中比较Rich Hickey的蚂蚁仿真代码(gist.github.com/1093917)可能会很有趣-尽管该仿真主要是为了演示STM的使用,但它基本上具有功能。
mikera 2011年

13
评论者:请不要在评论中留下答案。写下您自己的答案。评论不是讨论该问题的各种可能答案的场所:要么提出您的建议作为答案,要么先聊天以充实它。

6
只是想确保您了解N3dst4的观点,即“函数式编程”是一门特殊的编程学科。非面向对象的编程通常称为“过程编程”。
DJClayworth

1
您为什么认为面向对象的实现会“更清洁”?最有可能它会 比一个适当的实用的解决方案可读少。
SK-logic

Answers:


201

面向对象的代码从定义上讲不是更干净的,相反,非OO代码从定义上讲并不是很糟糕。尽管确实存在针对此特定问题的相当明显的面向对象映射,但我还是建议您尝试使用函数式编程方法。尽力而为,尝试以可以召集的最佳函数式编程风格解决问题,您可能只会学到意料之外的东西。


83
为“您可能只是学到了没想到的事情” +1!
肯尼思

2
而且,面向数据的编程确实具有出色的性能,因为它对缓存友好,并且可以在处理数据块的功能集中更好地实现。对于您正在解决的问题,这似乎很完美。我不知道它如何应用于函数式编程,但我猜想它的帮助远大于伤害。
克拉姆

8
+1表示“您可能只是学到了没想到的东西”!,但是:如果OP在函数式编程方面没有太多经验,并且客户期望好的和廉价的解决方案,那么投入到解决问题的新方法。
莫特

3
@mort-在这种情况下,客户想要一些特定的东西,听起来他们知道得足够多,可以实际知道他们想要什么,所以如果他们雇用的人不能做到这一点,那就是他们的问题。我想我想说的是事实,就是客户想要“便宜的东西”,并说他们雇用了错误的人,他不能提供这些东西,这是客户的错,不是作者的错,他不知道如何提供便宜的货。好的函数式编程解决方案可以解决此问题。由于没有技术理由不这样做,作者试图提供客户想要的内容是其中之一。
Ramhound

2
在任何问题中,OP都没有说“好与便宜”。需求可能是“快速和良好”(在三个中:快速,良好,便宜)。在“ OP”指导下,所有这些都是不相关的,因为“规范”表示“使用功能编程”。
WernerCD

68

您提到客户曾经使用功能性语言进行编程,也许他有一个理由要求他以功能性风格编写代码。你应该问他为什么

也许他打算保留代码并稍后自己维护。

而且,我认为这两种选择要么是面向对象的,要么是像您提到的那样编写糟糕的代码。确保在这样的示例中编写功能代码可能会比较困难,特别是如果您仅具有面向对象语言的经验,但是如果客户端愿意等待更长的时间让您快速熟悉功能样式,那么它将不会问他那个很伤心。

我会问他为什么他想要功能样式的代码,如果时间不是很多问题,我会要求额外的几天来加快功能编程的速度。(为获得学习报酬而欢呼!)

如果其他所有方法都失败,请说明以OO风格进行操作会花费更少的时间。


@downvoter您会提供一些反馈吗?
Thanos Papathanasiou

3
我了解到tl; dr标记值得贬低,对某些人而言
独立

1
FAQ或帮助页面中是否有任何内容建议使用“ tl; dr”?还是只是一些不喜欢它的流氓用户?在我看来,为答案添加简洁的摘要只会是一件好事,所以我无法想象为什么将其视为值得反对的理由。
本·李

1
@Bratch我认为tl; dr标记适用于试图读取我的答案的用户。这意味着即使您跳过所有其余内容,如果您只是阅读此内容,那么您将获得答案的要旨。你说的是什么意思?
Thanos Papathanasiou

1
我们老人家这样的人不知道tl; dr是什么意思(我确实查了一下,但是为什么有人会使用这种神秘的废话?)
HLGEM 2011年

55

您是否知道函数式编程不仅仅意味着“无类编程”?

有关完整的说明,请参阅Wikipedia文章,但总而言之...

在计算机科学中,函数式编程是一种编程范例,将计算视为对数学函数的评估,并避免了状态数据和可变数据。与强调状态变化的命令式编程风格相反,它强调函数的应用。

函数式编程是一种编程范例,就像OO是一种编程范例一样。

如果您的背景是面向对象的,那么我可以看到您希望所有蚂蚁如何成为对象。另一方面,如果您要模拟一个具有数百万只蚂蚁的蚂蚁场,则面向对象和消息传递可能会变得效率低下。

幸运的是,Python具有用于函数式编程的出色工具(最重要的一个是函数是一流的对象。)

Python函数式编程入门


+1以表明这一点。这个问题确实应该得到澄清。
Bratch

您是否知道可以使用面向对象和功能的语言?这是两个实际上彼此正交的组织原则。诚然,许多OO语言也是结构化命令式语言,但是没有强有力的结合这些语言的理论基础。
Donal Fellows

@DonalFellows绝对好,这两者并不互斥。Python(因为该问题最初被标记为Python)是强制性的,面向对象的和功能性的,具体取决于您所处的位置。在此页的其他地方,有人提到OCaml,它是OO,具有功能。
N3dst4

22

向您的客户说明,如果他要进行函数式编程,则应聘请专门从事此工作的人员。函数式编程与OOP有很大的不同,如果您认为可以轻松使用它并提供复杂的高质量解决方案,那么您会误会。


同意。这只是常识。
史密斯先生

1
问题是,从业务角度来看,向客户承认您缺乏知识并不总是那么容易(“您应该聘请熟悉功能编程的人”)。声称OOP更好是容易的,仅仅是因为您熟悉它。不太诚实,但比较容易。
Andres F.

@Andres F:处理一种新语言(和范式)根本不容易。客户端迟早必须重新考虑问题。早于晚。
史密斯先生

4
@史密斯先生:我完全同意你的看法。我只是说提供者(即程序员)的这种诚实并不总是即将到来。从本质上讲,您是在告诉客户雇用其他人,这在世界范围内都是有意义的,但是仍然很痛苦。
Andres F.

13

常见的误解是“ OO”与“功能”完全相反。这些事情可以很好地相辅相成。在您的示例中,我想“蚂蚁”可以很好地建模为抽象数据类型,可以使用类和对象直接实现。可以使用函数对“ Ant状态”之间的转换进行自然建模,只要“ Ant”类是不可变的类型,这将引导您使用函数方法。

并且要注意,“对象”可以通过闭包的功能概念互换,因为对象是穷人的闭包,穷人的对象是... ;-):

https://stackoverflow.com/questions/2497801/closures-are-poor-mans-objects-and-vice-versa-what-does-this-mean

https://stackoverflow.com/questions/501023/closures-and-objects


+1功能编程和OOP是正交的概念。查看OCaml,Scala,Clojure和python,了解可以同时处理这两种语言的语言。
rds

这两个链接值得单独投票……
Wayne Werner

8

与客户商谈之后,如果他仍然希望按自己的方式做,您要么做一份专业工作,要么做不到,要么就不承揽合同,要么就从合同中找点办法。

仅仅因为您不同意而产生“ cr脚的代码”是非常不专业的。


8
  1. 为什么我们都假设客户知道函数式和命令式编程之间的区别?很多人不了解非OO编程范例的名称或细节,并且会很容易地互换诸如“过程性”,“命令性”和“功能性”之类的术语。

  2. 除非您认为应该那样走,否则不要走别人告诉您走的路。因此,如果您认为函数式编程不合适,那么就不要让自己失败或半心半意地承担一个项目。

  3. 如果客户端写那么规范执行规范,否则你写的规范和实施规范。

  4. 影响客户决策的最佳策略是使不受欢迎的选择更加昂贵。它每次都能工作。

  5. 如果您是专家(相对于客户),那么您应该能够说服他们。

  6. 为了真正知道客户是否有正确的观点,您需要获得更多的函数式编程经验,以便您可以放心地接受它,或者意识到您对OO的偏见是由于您的经验不足。

  7. 为什么不两种方式都做,然后让客户看到两种实现并决定哪种方法更易于维护。只需将所有这些因素计入您的项目估算中,就可以在获得报酬的同时享受学习的乐趣。


为“为什么我们都假设客户知道功能编程和命令式编程之间的区别?” + 1。客户可能会说类似“我不希望它具有重复性,因此将所有内容分解为功能”之类的东西,这对开发人员来说是常识。客户可能不认为这是常识,所以他告诉您。
AlexWebr

1
+1,实际上客户不知道什么是函数式编程,要么是由最新的流行语驱动,要么是因为他们在20年前就这么做了,但仍然认为自己是技术性的。
匿名类型

5

在进一步困扰之前,我将确保您都在谈论同一件事。您可以问他什么时候软件是“面向对象的”。他正直地说,这不是他自己的主要专业知识,可能是他有一些偏颇的想法。

例如,许多人可以考虑

class C {
public:
  C();
  void f( int );
  void g();
};

成为经典的面向对象方法,但是

struct C;
void construct( C ** );
void f( C *obj, int arg);
void g( C *obj );

并非如此(即使就经典的“数据以及对其进行操作的功能”定义而言,两者都是同样面向对象的)。


2
为什么要争论OOP的确切含义?最好问一下为什么客户认为他的仿真更适合函数式编程。客户可能是正确的...我严重怀疑 “功能”是指您的第二个C示例,还是将“功能”与“命令性”混为一谈。
Andres F.

@Andres F .:我并不是说“功能性”是指我的第二个C示例。我只是指出有些人认为它是面向对象的,而其他人则认为不是。因此,在开始争论之前,最好避免任何误解。也许一开始就没有分歧。也许是老板,因为他说自己对OOP并不熟悉,所以假定OOP具有某些属性(就像OP显然假定函数式编程具有某些属性一样)。
Frerich Raabe 2011年

严格来说,我不会认为后者是OOP,因为方法调用/消息调度不是通过对象路由的。这是OOP的关键功能。
Donal Fellows

5

您是否会说服客户使用面向对象的编程更清洁?

我认为您需要对编程范例进行更多的自我教育。面向对象的编程代码不一定是更干净的,实际上,它并不是通用的。同样,优秀的面向对象的编码人员知道如何使用过程/模块(通过功能和声明式范式来完成出色的工作,这会有点困难,但是对于优秀的程序员而言,通过阅读和演绎,应该不会太困难) -可接受的FP /声明式解决方案。)

我再说一遍,如果没有对过程和模块化编程的充分了解,您几乎不可能完全了解何时以及如何使用对象定向。OO不仅仅是声明类和继承层次结构。

还是您会尝试遵循他的要求并给他糟糕的代码?

如果您不能在程序上编写好的代码,我怀疑您是否可以以面向对象的方式编写好的代码。期。我不是要在这里进行判断,但是必须断言。

面向对象是过程和模块化编程的扩展。面向对象只是为您提供了工具,这些工具在适当使用时可以为您提供更好的机制来处理封装,耦合,内聚和代码重用/可扩展性问题。

但是所有这些问题并不是面向对象的固有问题。它们存在于过程/模块代码中(以及与此相关的其他范式中。)这是复杂性问题的类型,其本质上与范式无关。如果没有OO胶就无法处理它们,那么您不太可能用OO胶处理它们。

=========

回到您最初的问题,即是否要说服您的客户。这取决于。正如海报的肖恩·麦克米兰(Sean McMillan)所说,如果客户只是试图对某个议程(阅读,办公室政治)的发展工作进行微观管理,那就走开。从事破坏活动的人会指责别人或推动特定的议程。您不想参与其中。

呵呵,这种要求可能还有其他原因。许多嵌入式商店,无论对还是错,都选择对可以使用C ++进行的操作施加很多限制(例如,没有虚拟方法,也没有例外。)有时,它以令人讨厌的方式完成。在其他时候,这样做有充分的技术理由。

因此,您需要了解为什么客户希望避免使用OO代码。而且,如果您可以推测没有政治议程(没有危险的信号),那么您应该做专业的事情,那就是简单地在程序上/模块化上完成代码,并做好它。

与编程范例无关,确实没有借口提供糟糕的代码。如果您无法使用一种范例来产生可接受的代码,那么您肯定会普遍无法产生可接受的代码。


3

您正在混淆数据结构和面向对象的程序设计(在这个面向对象的世界中,这是一个普遍的困惑)

如果您需要做的就是在数据结构中“跟踪数据属性”并对其进行修改,那么20世纪70年代以后生产的几乎所有语言都将为此提供良好的支持,无论是否面向对象。

在OO中更容易做的事情是fly

  • 基于类的继承(创建一个旧的类很容易创建一个新类)
  • 基于类的多态性(以后很容易在仿真中添加新种类的蚂蚁)

如果您没有紧迫的需求,那么基本上任何编程范例都可以解决此问题,而不会出现太多问题。


我要补充一点,任何支持多态性的函数式编程语言都应该使编写面向对象或伪对象的样式变得相当容易,从而使您可以轻松地添加新类型的ant。
Marcin

@Marcin:的确,现代FP语言非常强大。我只想指出数据结构/ ADT和OO之间的区别
hugomg

但是OO实际上只是ADT加对象控制的方法分派。其他一切都基于此。(好吧,对象对分发的唯一控制通常是对象的类型,但这是一种改进。)
Donal Fellows

3

我的客户说,由于他具有函数式编程的背景,因此他希望使用函数式编程进行仿真。

(这是社会问题被误认为技术/设计问题的另一个示例。)

这里有两种可能性:

  1. 您的客户期望能够在编写完代码后接受您编写的代码并自行修改或维护。如果是这样,您应该对“家庭风格”有更多了解-功能与面向对象只是冰山一角。您可能需要将自己局限于客户可以理解的编程风格,或者需要以自己喜欢的风格来教育客户。(曾经,有人要求我使用CGI来构建Web应用程序,而不使用模板或库,因为客户端可能要进行更改。)

  2. 您的客户由于某些议程而试图控制开发。这是一个充满疯狂的袋子,您什么都不想做。如果您真正提供的是“交钥匙”软件,那么只要它可靠地完成工作,客户就不必在意它是否由运行在轮子上的仓鼠制成。以这种方式对自己进行微管理只是在痛苦中求索。

由您决定自己所处的情况并采取相应措施。


3

嗯...我是这里唯一想“这显然是测试工作/任务”的人吗?

首先-作业本身本质上是一种“学术”(模拟蚂蚁行为的一个方面)。

其次-使用(或避免)可以读取代码并做出此类断言的“客户”的非常具体的编程范式来实现需求的请求。

如果是这种情况,那么您最好做一些您需要做的事情-这将是一个非常不错的学习经验,如果您可以做到,那么您将在此过程中学到很多东西...

如果不是这种情况,您确实应该向您自己和/或客户询问有关分配的理由。如果推理是可靠的,那就去做-您将学习,并且作为经验的程序员会更好。谁知道-您甚至可能会喜欢在OO上喜欢功能样式。

如果缺少解释,那么所有的选择都没有。.我不建议您做什么。

您可能想要尝试以功能语言/样式来实现要求,或者如果您觉得有些可疑,则可以礼貌地拒绝该提议。

最主要的是-一旦您了解了需求背后的动机,那么正确的行动就变得显而易见。

编辑:以对角线查看参考的PDF后,那里描述的算法肯定看起来很适合功能样式,而不是OO


2

他们对使用函数式编程的要求有几个方面:

  1. 你有一个客户,这总是一个好兆头
  2. 客户希望您做的很好。这就是为什么他们要求函数式编程。因此,您的销售组织做得很好,或者您要的服务价格很高。
  3. 客户组织中有些人知道函数式编程是一件好事,并且将来会变得很重要

但也有一些令人震惊的迹象:

  1. 您似乎不准备在函数式编程中实现它。您的技能已经有些过时,无法跟上变化。
  2. 或者客户期望您比实际的程序员更好。这意味着您可能需要降级他们的要求,直到可以正确执行。

-1表示FP优于OOP。
罗素·博罗戈夫

@ tp1 1)您假设客户端在技术上比程序员更聪明,但事实并非如此,因为客户端只是该客户端。2)FP比OOP还要老,尽管最近它受到很多关注,但是OOP没什么问题,您不必忘记使用FP 3)最糟糕的部分是假设FP更好并且使用FP使您成为更好的程序员,这只是在个别情况下是正确的,在这种情况下,这似乎是不正确的。
乔·泰曼

@乔·泰曼(Joe Tyman):嗯,必须假设人们并不愚蠢,否则客户很快就消失了。我并不是要说oop是坏是坏,而是在这种情况下假设功能可能是不合理的要求-也许客户不了解程序员的技能,或更糟糕的是,试图使程序员转换技术。
tp1

@Joe Tyman:另外,我想到的最坏的情况是客户确实需要可以执行某些高级功能编程(例如类别理论)的人员,并且他们正在尝试寻找一个可以做到这一点的团队-这就是为什么要求因为他们可能是不合理的。
tp1


1

您没有写任何关于编程语言的信息,这可能是那里最重要的事情。OOP和函数式编程之间的区别不仅在于代码的组织方式,还在于语言本身。在高并发的情况下,将使用功能语言Erlang,它比Java具有很高的优势(例如Facebook聊天使用)。OOP解决方案可能仅由于性能问题而失败。

这里的客户是大学,所以语言不仅是性能/配置问题,该代码还可以用于与学生进行教学工作或自己进行研究。因此,我认为“说服”客户选择其他范式在此并不适用。这是您可以执行任务还是不能执行任务(因此,您不应该执行该项目)。


0

客户说“跳”,你的答案是:__ _

对我来说,我会说服是否可行(新项目),但我还有一个拥有10年旧VB6应用的客户,我偶尔会对其进行升级...不会说服他们


从技术上讲,尽管VB6应用程序很好,但几乎是面向对象的,如果在当前的OS上运行良好,为什么要“升级”到.NET。除非您想利用新功能,否则这根本没有任何意义。
匿名类型

是的,但是您最近是否尝试使用vb6?这

对。我们将其大量用于维护尚未获得预算以进行Java或.net更新的现有应用程序。它很痛苦(与现代IDE相比),但也是相对的。像任何一种语言(包括脚本)一样,一旦您擅长于此,您对痛苦的定义就会变得更加主观。
匿名类型

0

稍微“交叉检查”您的客户(以非对抗方式):

客户实际上了解OOP和函数式编程之间的区别吗?客户的顾虑/要求是否合法?

如果“是”: 如果您有资格,请做他们想做的,然后拿走您的钱。如果您没有资格,请告诉他们,让他们决定要做什么。

否则: 拖尾在那里!


0
double dist(Point p1, Point p2) 
{
  //return distance
}

只要该函数不读/写该函数之外的任何内容,它就可以起作用。如果函数触摸了类变量,它将不再是“函数”。功能风格的优点是不再有来自更改或无效状态的错误。大量函数只是数学公式。简而言之,就是函数式编程。

顺便说一句,您可以在基于对象或面向对象的设计中组合功能样式。例如,两个“点”变量是具有状态的对象。并且该功能仍然有效!好极了!!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.