V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
raycake
V2EX  ›  程序员

近期与同事讨论,函数式(FP)正在缓慢取代面向对象(OOP)?

  •  
  •   raycake · 29 天前 · 8787 次点击
    请关注问题,别抨击提题问题的人和问题本身(狗头保命)。
    90 条回复    2024-11-16 09:13:22 +08:00
    SimonOne
        1
    SimonOne  
       29 天前   ❤️ 3

    只会写面向过程的人无所畏惧。
    ohoh
        2
    ohoh  
       29 天前   ❤️ 3
    FP 是一等公民,意思其他都是牛马。说得也对,毕竟这么多年了,一等公民还是一等公民,牛马还是牛马。还是牛马好使
    chendy
        3
    chendy  
       29 天前   ❤️ 1
    个人感觉正好相反
    早年隔三差五就能看 Haskell 和 Clojure 相关的东西
    现在…很久没见过了
    COW
        4
    COW  
       29 天前 via Android
    额,有句话怎么说来着,小学生才做选择题
    NessajCN
        5
    NessajCN  
       29 天前   ❤️ 13
    我不想对 oop 本身做过多评价
    我只想说我极为厌恶「继承」
    kkkwar
        6
    kkkwar  
       29 天前
    勾起回忆了,用二郎都是十年前的事了
    ZZ74
        7
    ZZ74  
       29 天前   ❤️ 1
    我不想对这个有任何评价,因为不管哪种原因,开发效率的提升 ,只是让老板快速获得它想要的。 你还是得加班。
    redbule
        8
    redbule  
       29 天前   ❤️ 20
    我感觉这是十年前最流行的话题了,现在基本没啥人提了。
    其原因大概是老人已经对 fp 祛魅了,新人接触到的新语言如 js ,go ,rust 等等,不再是传统的 oop 模式,连“面向对象”这个词都显得老旧和过时了。
    事实上过于强调 oop 也确实落后了,现在是 fp 和 oop 融合的时代,大家都互相的长处放入语言特性。编程语言的生产力也获得了解放。
    fredweili
        9
    fredweili  
       29 天前
    函数式当然爽,它的相对面是面向过程,像小学老师
    luyinge
        10
    luyinge  
       29 天前
    @redbule 是的,现在语法都是你抄我我抄你,哪还有什么严格的 OOP 跟 FP 的界限,啥好用用啥
    sampeng
        11
    sampeng  
       29 天前
    因为现代语言总算没有"继承"这个毒瘤了.
    mightybruce
        12
    mightybruce  
       29 天前
    因为出了几个极端的面向对象的语言和函数式设计语言都死了,现在语言都是相互吸取和借鉴,
    面向对象对于现实的模拟说实在比函数式编程更差

    面向对象基于的软件建模的那一套都没有严格的论证,而不像函数式编程还是建立在数学论证的基础上,流行的语言都是借用一些函数式编程的方法和思维,但还不是函数式编程。
    mahaoqu
        13
    mahaoqu  
       29 天前
    写 CRUD 真的只需要面向过程。

    写 React 倒是需要函数式,不过设计的确实有点蹩脚。
    xz410236056
        14
    xz410236056  
       29 天前
    @NessajCN 所以 apple 搞了面向协议编程
    wu67
        15
    wu67  
       29 天前   ❤️ 1
    拿 ts 举例, 类型和类型断言就是一个非常典型的 oop 特征, 但是实际上写起来一堆 any script...
    所以写起来简单易读就好了, 根本没必要强行局限于只使用什么模式.
    就像之前我还接触过一个项目, 各种 index component 目录疯狂套娃, debug 时随缘挑一个文件, 找到它展开的目录深度在 7 以上....很明显就是之前的人不知道从哪看了什么什么项目圣经之列的...
    purringpal
        16
    purringpal  
       29 天前 via iPhone
    小孩才做选择
    jorneyr
        17
    jorneyr  
       29 天前
    C 语言时代,10 万行以上的代码命令都是一个很困难的问题。
    后来发展面向对象要主要解决大项目里的代码管理,只要能解决代码管理问题,函数式编程或者面向对象都没关系,例如 Golang 支持包管理、即面向过程、也面向对象,使用合适项目的方式才是核心。
    lvlongxiang199
        18
    lvlongxiang199  
       29 天前
    能列一下你的论据吗 ?
    crysislinux
        19
    crysislinux  
       29 天前 via Android
    就算不用 class ,不还是到处是 object 里塞属性塞方法么。
    bluearc
        20
    bluearc  
       29 天前
    可能是最近的热门语言都同时有二者的特性让你有这种感觉,或者说现在大部分都已经是多范式编程语言了,至于纯函数式编程语言,比如 Haskell ,我觉得是少数大佬的玩具
    DOLLOR
        21
    DOLLOR  
       29 天前   ❤️ 21
    取代者不是函数式,而是“函数是一等公民”的概念越来越深入人心了。函数应该是能独立存在的东西,能作为变量、参数、返回值,不应该只作为类的附属品。

    被取代的也不是面向对象,而是 为了面向对象而面向对象。
    8355
        22
    8355  
       29 天前
    fp 的应用在于 serverless 函数计算的发展,取代我觉得并不会。
    zsj1029
        23
    zsj1029  
       29 天前
    一个 ts 函数式导出,你去打印这个导入,实际还是个对象,所以。。。没有所以
    tubinorg
        24
    tubinorg  
       29 天前
    在 oop 中加点 lambda 而已
    RightHand
        25
    RightHand  
       29 天前 via Android
    函数也是对象,爆杀一切
    Chingim
        26
    Chingim  
       29 天前
    只能说不再是传统的 OOP.

    但也不是纯粹的 FP, FP 处理副作用还是有点蛋疼的
    windcode
        27
    windcode  
       29 天前
    极端的面向对象思想已经过时了,现代语言更多是取长补短,取一个工程上的“均衡点”
    shily
        28
    shily  
       29 天前
    @NessajCN 是不是因为你没有东西继承?要是有一个小目标继承,就不会了。🐶
    Leviathann
        29
    Leviathann  
       29 天前
    @xz410236056 protocal 不过就是 typeclass 换个马甲而已
    Rorysky
        30
    Rorysky  
       29 天前   ❤️ 2
    大多数 oop 都是脱裤子放屁,话糙理不糙
    PTLin
        31
    PTLin  
       29 天前
    是面向组合替代了面向对象,fp 不是只有一等公民的函数和 map filter reduce 那些东西。
    mogutouer
        32
    mogutouer  
       29 天前
    python 写多了吧😂
    frandy
        33
    frandy  
       29 天前
    早前流行 FP,现在是 OOP+FP,怎么好维护怎么来,因为现实业务没有纯函数,而且 FP 里面好多概念无法理解,比如函子(Functor)、适用函子(Applicative)、单子(Monad),一听名词就觉得好高大上,哈哈哈哈哈
    kyuuseiryuu
        34
    kyuuseiryuu  
       29 天前
    先有业务,后要数字化 —— OOP 好用。
    先要产物快速迭代 —— FP 好用。

    项目复杂度上去了迟早要迁移到 OOP 。
    业务没跑起来就上 OOP 提前设计,利润不一定有一开始就用 FP 来的多。
    kuanat
        35
    kuanat  
       29 天前   ❤️ 6
    稍微偏个题。

    编程这件事的本质是什么?我个人有个粗糙的定义,就是用语言对某种事物、行为或过程做出无歧异的抽象描述。用自然语言给人指路、教人下棋或者介绍产品都是编程,只是这种程序的执行者不是自动化的机器。

    从计算理论上说,图灵完备的编程语言之间不存在表达能力的差别。语言特性和编程范式百花齐放,表面上是工具特化的结果,深层次是反映编程者对于现实的认知逻辑和思维方式。

    FP 是数学上优美的,非常适合解决真空中球形鸡的问题,现实大多数问题仍旧需要传统经验公式和手段来应对。OOP 是有效解构对世界认知的哲学,但实现 OOP 的方式却不一定。组合( composition )替代继承( inheritance )就是认知层面的进步。

    从过去二十年编程语言的发展来看,语言特性 FP/OOP 的进步演化一直在发生,但几乎不存在相互替代的基础。作为工具的编程语言,以当下的视角来看,能够成为主流的一定是具有工程化能力基础的,只有解决问题的范畴和效率提升才会带来工具的替代。
    kw8023cn
        36
    kw8023cn  
       29 天前
    @kyuuseiryuu 有趣的观点,学习了
    zefpe2
        37
    zefpe2  
       29 天前
    FP 早就是润物细无声了,新一点的语言和框架全都带着 FP 的概念。常见的 Option 、Result 、Either ,还有前端各种 State 、异步的处理,全都是用 FP 的概念,我不信现在还有人没见过任何一个。大部分人不需要专门学习 FP 就已经用上 FP 技术了,你每天都在用 Monad 却不需要了解任何 Monad 的知识
    xiangbohua
        38
    xiangbohua  
       29 天前   ❤️ 1
    说句实话,我觉得平时很多人写业务的时候框架一套就开始写逻辑,没多少人的用到了 oop 的特性的。。。框架用的 oop 语言然后只是被迫 new 对象而已。对于一般人而言只要框架好用,是不是 oop 无所畏惧。
    XIVN1987
        39
    XIVN1987  
       29 天前
    流行语言都是混合语言,,纯 OOP 或纯 FP 的语言都半死不活。。
    XIVN1987
        40
    XIVN1987  
       29 天前
    C 语言除外,,它既没有 OOP ,也没有 FP ,,纯粹的高级、通用汇编语言。。
    archxm
        41
    archxm  
       29 天前
    工作个三五年,都会有这感觉的。
    zhangkui
        42
    zhangkui  
       29 天前
    @sampeng js?你在说谁?
    locochen
        43
    locochen  
       29 天前   ❤️ 1
    需要无状态,用 fp 。
    需要保持状态, 用 oo
    jaycezhang7890
        44
    jaycezhang7890  
       29 天前
    前端是这样的
    Donaldo
        45
    Donaldo  
       29 天前
    @DOLLOR #21 从 C 或者更底层的角度看,函数一直是这样吧
    SenLief
        46
    SenLief  
       29 天前   ❤️ 2
    @NessajCN 我感觉 oop 没那么直观,尤其是继承,还有人继承好几代,都得画个家谱。
    weiwenhao
        47
    weiwenhao  
       29 天前
    组合优于继承。实际写代码也确实这样
    open9527
        48
    open9527  
       29 天前
    最近用 java stream 用多了感觉编程思想会变
    wxm1997
        49
    wxm1997  
       29 天前   ❤️ 1
    @RightHand #25 你是不是在说 python
    wanguorui123
        50
    wanguorui123  
       29 天前
    怎么快怎么来,纠结这些干嘛
    ychost
        51
    ychost  
       29 天前   ❤️ 1
    现代语言比如 Kotlin 、C#、JS 都是混合用的,纯 FP 只会让项目难以维护
    james122333
        52
    james122333  
       29 天前 via Android   ❤️ 1
    OOP 限制多 不灵活 框架如果使用就很难绕过
    只能用反射绕过去才能实现各种符合需求的花式操作
    FP 有闭包个人觉得更好 可组装灵活性高 也更适合元编程
    OOP 和一些框架已经是生产力的敌人了
    我爱用 shell 因为元编程不错用 没有做茧自缚带来的烦恼 也不用在限制下解决问题带来的虚假的成就感而感到沾沾自喜 限制生产力同样也是限制学习
    james122333
        53
    james122333  
       29 天前 via Android
    可以说这件事情本身就是个阴谋
    jry
        54
    jry  
       29 天前
    我感觉 Vue 组合式 API 就是把 OOP 回退到 FP 了。
    cheng6563
        55
    cheng6563  
       29 天前
    早些年前还经常看到讨论 Haskell 和 Scale 啥的,近几年好像是真没看到了啊...
    james122333
        56
    james122333  
       29 天前 via Android
    为什么中国人那么多 自始自今没有个地位等同 linux 的跑出来 还有一堆商用软件
    道理在此阿 都在瞎打滚了
    jeesk
        57
    jeesk  
       28 天前
    @james122333 产品能够产生受益才行呀, 无论你使用什么高大上的技术,没钱都拉倒。
    thtznet
        58
    thtznet  
       28 天前   ❤️ 4
    OOP 的本质是为了让软件承载的业务在代码的世界中有个映射能更好的让程序员理解业务,只从技术角度看待程序的话,当然程序就是函数就可以了,引入 OOP 不是为了技术迭代或者被迭代,是一种业务理解的哲学过程。其本质一种“设计模式”,只是某些语言被特意地设计成更适合 OOP 的设计模式,例如 C#,但是 C#并不是不能写函数式,完全可以以其他方式组织代码结构。很多最近几年入行的程序员总是感觉 OOP 不流行了,那是多种情况,1 种情况是楼上几位提到的各种范式在融合,另外一种原因是因为很多程序员已经接触不到需要完全面向业务的 OOP 式编程,因为现在有太多的框架和模板或者库将以前需要深入理解 OOP 才可以实现的代码被无形中处理掉了。并不是 OOP 少了,而是很多非关键组件开发的程序员接触不到了,现代软件工程的组织模式导致了很多程序员只会接触到整个软件平台中极其细小的一部分组件,而这部分组件实现的功能极其专业和细微,让人无法感知到需要以 OOP 的设计思想才可以写出来。当程序员的段位上升整体架构的时候,一定会体会到无处不在的 OOP ,虽然最终落实到编码层面不一定以 OOP 的写法去实现。跑个题:新时代的驾驶员开不到手动换挡的车不代表车子没有了挡位,它只是被自动化处理掉了。感知不到传统系统并不代表齿轮少了,它只是在底层默默地工作。
    shui14
        59
    shui14  
       28 天前
    框架打螺丝,当下 FP 热门,即便是 OO 阵营,也不再是 csharp 那种严谨意义上的面向对象,现在流行组合替代继承
    如果是自己开发 sdk ,就算是 js 包,面向对象还是有一席之地,而且 react 如日中天要搞开放式的架构,比如整合地图引擎或者要把 three 这些三方库之类的做模块化,面向对象还是很能打,类似 ddd ,这两年流行的 react 库,架构是老 class ,写业务就 hook 。其实就是拿它当 ng 用,但是 ng 今天太重了,毕竟库开发是少数,绝大多数是打螺丝
    Lockroach
        60
    Lockroach  
       28 天前
    不管是 fp 还是 oop ,都得看架构设计和使用者,滥用继承和函数都会让代码可读性下降
    kaedea
        61
    kaedea  
       28 天前 via Android
    谁也取代不了谁,所以谁也别看不起谁,反正不久都会被 prompt 式编程取代。
    voya
        62
    voya  
       28 天前
    不存在谁取代谁,仅仅是手边工具,怎么方便怎么来,有问题的是刻意追求模中模式最后本末倒置,函数式就像积木,面向对象像工厂的模具,都有优势场景
    dawn009
        63
    dawn009  
       28 天前
    函数式和面向对象不冲突。面向对象仅仅是一种数据封装方式。
    inframe
        64
    inframe  
       28 天前
    锤子、扳手、锯子,哪个好用用哪个,一起用也可以
    james122333
        65
    james122333  
       28 天前
    @jeesk

    我说了那么多不就是为了好开发...
    xFrye
        66
    xFrye  
       28 天前
    这两者不应该是对立关系而是互补,根据实际需要来选择解决方案
    yikyo
        67
    yikyo  
       28 天前 via iPhone
    看到讲 oop 的,请问现实公司有用 ddd (领域驱动开发)的吗?实际意义大不大,当年看了很多遍,还是没理解核心思想
    mocococ
        68
    mocococ  
       28 天前
    还是面向对象好用;函数式的话,写太多函数,需要时来调用不同的函数,增加心智负担。

    New 一个对象让他来帮你实现功能不是更好么,交给它处理就好了,不同的功能用不同的对象。最好是接口,一眼便看清该接口的所有功能,还可以根据情况实现不同的细节。

    接口的实现,才来调用函数式,这样最好理解和管理,两者结合使用最好了。
    jojobo
        69
    jojobo  
       28 天前
    之前面试的时候被问到过,回答的不好
    charlie21
        70
    charlie21  
       28 天前   ❤️ 1
    OOP 擅长的是责任划分, 它是一种完全符合 SOLID 原则里的 S: Single responsibility principle 单一职责原则 的应对策略

    函数式 擅长的是 清除副作用,用纯函数来清除副作用

    这是两个层面的 互不干扰也无法互相替换。

    在大型架构里 (即使不用 OOP )也要有明确的职责划分方法,否则不够大型。

    在时尚界,函数式代表了时尚,尽管它能做到的东西 用别的方法也能做到,但函数式可以给出十分简明清晰的 API (因为它在清除副作用,它往往十分适合 “状态管理类” 的任务。 典型的状态管理类的任务是:
    erlang: 状态变化是万恶之源 https://zhuanlan.zhihu.com/p/27341488 了不起的 Erlang
    redux: 前端状态管理器
    ngrx: 前端状态管理器 https://zcating.github.io/2019/12/10/ckaum9y7o001zejl325a2852f/ 为什么要用 ngrx 它解决了什么问题
    // 只有在这些任务面前,再开始聊函数式,才是合适的 因为函数式编程恰如其分解决了这类问题 (也就是 其它问题呢 想用函数式也没用) 。否则真的就是赶时髦的了


    总之:
    1 看中 明确的职责划分方法 ,的 结果是, 让复杂的事情变得可管理
    2 对于某类任务,函数式编程可以降低复杂度 , 尤其是数据状态变化(数据状态跟踪)的复杂度
    jchnxu
        71
    jchnxu  
       28 天前
    @NessajCN 我也是这样的。。。继承是一种到处泄露的封装方式,尤其代码复杂了之后,心智负担很大
    kapaseker
        72
    kapaseker  
       28 天前
    @NessajCN 但是继承只是一个可选项,不是必选项
    acorngyl
        73
    acorngyl  
       28 天前
    @thtznet #58 谢谢啊
    这个帖子点进来给我看懵了,以为我到外星球了。直到看到你这层,才知道自己还在地球。

    看了半天,没搞明白大家在说什么?现代很多语言都是纯面向对象的啊,搞不明白怎么还出来个面向过程。举例说,python 。python 里所有的变量都是对象啊,就算是“a = 5”这种 int 类型,翻译成 java 或者 c++,就是 int a = new int ; a=5. 面向过程或者半面向对象的语言,int 这种基本数据类型不会使用内存指针,是直接开辟内存地址,后续是内存值操作。纯面向对象的,哪怕是基本数据类型,也是先创建指针,指针指向 int 内存,之后都是指针传递。只不过现在很多语言,编译器或者解释器把指针隐藏了,不开放给开发者使用。还有 map 的各种操作,map.set 、map.get ,这个“ . ”点出来的,不都是类方法吗?
    看还有吐槽继承的。顺便吐槽一下 spring 的实现类,极大多少情况,一个接口对应一个实现类,的确违背接口设计的初衷了。接口类是为了多态服务的。比如 list 接口的各种实行,数组列表、链表、双端链表,它们都是 list 的实现类,list 在用的时候接可以灵活使用各种实现类的功能,扩展实现的时候直接加实现类就行,不用动 list 和所有已有的对 list 的使用。

    就是说下我对这个话题的理解。如果我理解的和大家讨论的不是一回事。请无视。
    InkStone
        74
    InkStone  
       28 天前
    现代语言比古代语言更 OOP

    现代语言同时也比古代语言更 FP
    woodfizky
        75
    woodfizky  
       28 天前
    你可以用 FP ,你也可以用 OOP ,你还可以一起用,主要看用在什么场景。
    用的好不好就开发者写的好不好,不存在说谁取代谁。
    Felldeadbird
        76
    Felldeadbird  
       28 天前
    不应该先拿一个语言为例嘛。FP 和 OOP 不是看语言选择风格的嘛?不可能说 java 去写 FP 呀,那失去了优化。
    jonsmith
        77
    jonsmith  
       28 天前 via Android
    技术思想在发展,oop 也在改良,比如组合远替代继承、函数一等公民、对接口的灵活运用。
    TophTab
        78
    TophTab  
       28 天前
    函数类,对象类
    SergeGao
        79
    SergeGao  
       28 天前
    @locochen fp 也可以用闭包实现有状态,react 的 hooks 就是
    uni
        80
    uni  
       28 天前
    哈哈哈前两周还在尝试在 python 里面搞 monad (是用来改进实际的业务代码哦),然后发现纯 monad 还是要配合语言的其它特性,比如说循环要用递归的方式来写,这样才能发挥 monad 的力量,但是比如说一个几千上万次的循环在 python 里面改成递归,在 python 里面也太扭曲了而且可能有性能问题,还是决定放弃了

    但是 fp 是真的香!
    Azone
        81
    Azone  
       28 天前
    现在的语言不都是多范式的吗,为啥要纠结这个,而且现在新兴的还有 POP
    songray
        82
    songray  
       28 天前
    恰恰相反,业界已经几乎没有纯 fp 或纯 oop ,大多数情况下,最佳实践都是某种比例的糅杂。
    lxdlam
        83
    lxdlam  
       28 天前
    先问是不是再问为什么。

    FP 跟 “OOP” 本来就是正交的概念,与 FP 相对的是 Imperitive Programming ,而 FP 可以看作一种 Declartive Programming 。在 1994 年确定的 ANSI Common Lisp 标准中,Common Lisp Object System ( CLOS )已经被完整定义,这是一个完整的对象系统,而被广泛实现的 Meta Object Protocol ,更是后面 Java AOP 的真正前驱。同样,1996 年 OCaml 继承 Caml 衣钵,在 StandardML 基础上发展出了完整的 Object 系统,这也是一个完整的 OOP 系统。而 Scala 跟 Clonjure 这种本身就诞生于 JVM 的语言,更是天生就具有 OOP 能力。
    charlie21
        84
    charlie21  
       28 天前
    在 存在一个极为明显的继承关系 的时候
    继承是有用的

    - 比如本站名帖: 继承 nannanziyu site:v2ex.com /t/761625
    - 比如在尝试基于第三方库制作自己项目用到的一些极为基础的类的时候 ,此时 第一件事情就是 创建新 class 继承原有的类,然后稍加修改
    charlie21
        85
    charlie21  
       28 天前
    基础库里经常看到类的拓展 例如
    https://afterlogic.com/aurora-files-api/index.html
    https://afterlogic.com/aurora-files-api/Aurora.Modules.Core.Models.Tenant.html

    如果现在你想要使用这个第三方库作为自己的项目的基础类 你也会先创建类并 extends 某个 class

    也就是说,如果在极为表面的 app 层工作的人,那么很有可能是几乎用不到类继承的! 他们不用,不代表别人不用
    charlie21
        86
    charlie21  
       28 天前
    这是一个项目的继承关系树

    https://afterlogic.com/aurora-files-api/tree.html

    比如 Aurora\Modules\Core\Models\User 继承了 Aurora\System\Classes\Model ,而后者继承了 laravel 的 Illuminate\Database\Eloquent\Model 。也就说 这个项目基于 laravel 框架定制了自己的一套基础类,自定义的基础类是业务模型类的基类 。

    换作是别的后端项目 大概是也类似的 ... 吧
    locochen
        87
    locochen  
       28 天前
    @SergeGao 后端用的不多
    tyzandhr
        88
    tyzandhr  
       28 天前 via Android
    ocaml 式的 fp 远比 haskell 更受人欢迎。

    事实上无论什么语言都能写纯函数。只要把项目分成可变的外部世界和不可变的数学世界两部分就算是函数式编程。
    headwindx
        89
    headwindx  
       27 天前 via iPhone
    存在即合理,现实世界需要多元化,不要局限在一个坑里,探出头看看其他坑,找到最适合你的
    xfun
        90
    xfun  
       27 天前
    试试 Rust 的组合,各个部分只是资源
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2456 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:48 · PVG 19:48 · LAX 03:48 · JFK 06:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.