面向對象編程為什麼沒有在科學計算領域獲得普及?

像計算化學,材料模擬領域的gaussian,gamess,vasp,castep這些流行的計算軟體毫無例外的面向過程。

像分子動力學領域的gromacs,lammps用c++,但沒有見到他們著重宣傳oop的概念。

科學領域計算也是可以抽想成類和對象的概念啊。


在等離子體領域:

流體代碼大都一隻腳跨入了OOP的大門, 因為有CFD打前哨

但是另一種主流的,Particle-in-Cell模擬方法貌似大家都還沒有特別尊重OOP的設計模式, 因為這玩意想要設計一套封裝的比較徹底的類系統真心困難, 演算法裡面很多東西都是攪在一起的, 尤其是在必須保障計算效率的前提下,目前我們組的Fortran程序都是所有數據混成幾坨,完全沒有抽象和封裝的影子在裡面。能設計幾個通用的函數(手動斜眼)實現代碼共用也就到極限了。曾經打算先用函數來封裝一些基礎數組訪問, 但是性能一下子掉了50倍, 瞬間不敢在動了。

個人總結原因有幾點:

  1. 大老闆不重視, 一般做物理的更重視有什麼new physics, 沒什麼人重視代碼好不好看。 代碼寫的再好看沒有有力的結果還是發不了好文章。
  2. 開發的人吃力不討好, 一切以new physics為導向, 導致學生沒什麼動力去改善代碼的結構, 有那點時間還不如去多看兩篇文章,多推點公式, 多看點數學。
  3. 改動成本太大, 有些代碼寫出來之後是沒有辦法確定其正確性的, 你不知道算出來的東西是bug還是new physics, 只有通過不同實現手段的不同代碼之間進行cross benchmark, 這兩年我們組有一個老外一下子燒掉了1200萬cpu/小時來驗證代碼正確性, 這要調出來的代碼再用oo重構一遍, 沒人願意再花幾年/上千萬機時來測試正確性。

當然, 代碼復用是必須的, 可以降低代碼的上手難度, 更好保證正確性,可以保證一個代碼在用OO重構之後十幾年之內造福後來的學生。 但是必須要大領導有這個意識,拍板指定一兩個學生犧牲掉自己的幾年的時間來做這個事, 或者拍板拿出一筆錢找有興趣的學生來做 (但是這個學生在學術上可能發展就不太好了, 所以要用錢來補償), 這是我目前想到的唯一可行的一種解決方案。

我們組嘗試過找計算機學院的人來做, 效果不好, 因為要先給他們普及一年左右的相關知識, 然後他們才能聽懂我們這邊的需求究竟是什麼。


謝邀~~

我用過五套領域內的程序:

  • 兩套面向對象的,其中一套是我們自己寫的。抽象程度很高,用起來改起來都很爽。

  • 兩套面向過程的,其中之一是一套很老的 C 程序,另一套是一個面向對象不怎麼完整的 c++ + cuda, 姑且算面向過程了。抽象程度很高,用起來改起來都很爽。

  • 一套 Scheme 寫的函數式的,抽象程度很高,用起來改起來都很爽。

結論:

  • 至少在我的領域內,面向對象應該算是普及了。

  • 只要寫得好,主流範式都可以寫出高效易用且擴展性強的程序。

  • 兩套程序給你選,一套面向過程的 4k 核並行無壓力,一套面向對象的 200 核性能就開始掉,難道你會選後者?


謝邀。

有一個重要的原因,就是很多計算化學軟體的核心代碼都是上古年代用FORTRAN寫的,比如Gaussian,而那些核心代碼雖然可能經過了修改/優化,但還都沿用到了現在的版本里。


我想首先應該明確一點,題目中「計算科學「換為「科學計算(Scientific Computing)」可能更加合適一些。

兩方面原因,其一在於絕大部分科學計算領域中的演算法的是直接以面向過程來描述的,這很顯然,因為演算法就是對數據進行處理以得到所需要結果的過程。這一套邏輯是該領域研究人員所熟悉的,因此就算他們選擇了C/C++來進行編程,也很自然的就採用了面向過程的範式。其二在於科學計算領域的研究人員所受到的編程方面的訓練並不足以使他們足夠強地掌握面向對象的編程方法。當水平不足的時候,使用面向對象的方法寫出來的程序運行效率可能很差,這不滿足科學計算對於效率的高要求。

但是這並不絕對,比如在元胞自動機領域,可能多數程序都是面向對象的,因為該方法的描述與面向對象的方法是十分契合的,也因為這一領域最近才迅速發展,領域中已經有足夠多的研究人員具備使用C++進行面向對象開發的能力。

此外,尤其需要注意的是,進入新世紀之後,越來越多的人開始採用C/C++甚至最近的Python進行科學計算了,但是這並不表明面向對象在他們的程序架構中佔有優勢地位,多數科學計算的C/C++程序仍然是面向過程的,或者本質上是面向過程,只是基於對象在頂層上做了一些封裝。我注意到題目的標籤中加了Fortran項,我想大家須要將面向過程/面向對象這種編程範式與具體的語言(Fortran/C/ C++/Python)區分出來 。我自己比較熟悉的Python/C++都是支持面向過程/面向對象多種編程範式的。況且Fortran語言的運行效率並不比C/C++高,兩方陣營表現幾乎一致(知乎用戶:Fortran 目前仍然是科學計算領域使用的主要語言嗎?)。

最後,就我個人而言,我現在使用得更多的是以泛型編程技術為核心的多種范型並存的編程風格。前述已經給出定義「演算法就是對數據進行處理以得到所需要結果的過程」,因此泛型這種將數據類型與操作過程相分離,最大程度上提高代碼復用程度並且基本不損失運行效率的範式,在我看來,十分契合數值計算的需求。但是科學計算領域的研究人員中少有人具備熟練掌握並最大程度上利用該範式的能力。


現在很多「商用」計算化學軟體代碼量都還是比較大的,但是「沒有見到他們著重宣傳oop的概念」

我覺得是因為對於一般計算化學的用戶來說他們並不關心程序是用面向過程還是面向對象的語言編寫的,兩者的區別還主要在軟體代碼的維護上,而用戶接觸到的只有程序封裝好的少量命令。可能普通用戶更關心的是分析工具的多寡、並行效率的高低、結果的正確性這些問題,計算化學軟體可能還是」不管黑貓白貓,只要能以最快的速度抓住想要的老鼠就是好貓「。

目前,很多計算化學軟體代碼都是面向過程的確實如 @陳浩源所說,是歷史的原因。很多軟體的基本功能是在oop尚未普及的年代寫成的,代碼的升級確實是個問題,而很多情況下fortran作為數值計算和並行編程的教學藍本也讓其生命力得到了延續,比如大氣、海洋模擬的很多程序仍然在用fortran寫。

不過很多比較新的計算化學軟體也逐漸使用面向對象的語言,比如VMD是用C++寫的,用戶可以用TCL/TK或者Python寫腳本處理數據。


因為真正的面向對象指的是消息、委託那套,最適合的是複雜GUI業務邏輯,和高性能計算沒有半毛關係。


題主應該是不大了解軟體工程的相關知識,所以對面向對象缺乏概念。那麼,我大概首先介紹一下面向對象是什麼,然後說為什麼不面向對象。

簡單的來說,就是演算法問題不適用於面向對象

首先要排除一個錯誤想法:面向對象是萬能的,一定有好處的。編程領域沒有銀彈,面向對象有種種缺點,很多程序不能用面向對象寫,很多流行的語言不重視對象。現在還「著重宣傳oop的概念」的,一定是大忽悠。

所有語言和設計模式,都有一個共同的目標:抽象。抽象解決一個問題,就是代碼的複雜度。抽象程度高的語言,代碼簡潔,復用程度高,解耦容易,總之就是節約程序員的時間。

那麼再看計算軟體,第一條就可以把面向對象斃了:簡單。寫個幾千行的東西,就沒什麼複雜性,還面向對象,不是給自己找抽嗎?當然某些語言的存在就是一種傷害,不討論。

好吧,這些軟體還是很複雜的,因為它們裡面包含的演算法很厲害。但是演算法明顯不屬於面向對象適合去解決的問題,演算法的抽象方式跟日常生活中面對的實體完全不同。演算法是沒有副作用的,沒有解耦的問題,而對象和方法充斥著副作用,解耦是個值得研究的問題。高性能演算法用過程式,高度複雜的演算法用函數式,就是沒對象什麼事。

好吧,計算軟體也是有GUI的,這個總要面向對象了吧。這個應該是面向對象的,一般沒人拿過程式去寫。不過,你看著那些界面,然後隨便拉一個桌面程序比一比,你覺得他們好意思拿著強調自己面向對象了嗎……

我認為,計算程序在面向對象之外,其實有很多地方可以優化。至少我見過的多數計算程序都是在傻寫,不懂得應用各種技巧。最應該學習的是函數式編程,包括lambda和macro,能極大降低演算法中的復用程度和代碼量。如果真的是理科學生,數學好沒碰過編程,要做科學計算領域,最適合的入門教材是SICP,理解了SICP里講的演算法和編程思想之後受用無窮。


1、面向對象編程在計算科學領域已經得到了普及。

拿計算化學來說,火爆的量化軟體orca和皇族血統的Qchem都用上了c++。分子模擬面向對象已經是完全的主流,gromacs,lammps,NAMD都是c++

2、為什麼這些軟體沒有宣傳oop?這些軟體吃飽了撐的才會去宣傳oop。一款軟體要宣傳的是功能,是速度,用面向對象還是面向過程亦或者是函數式編程那是作者關心的事情,向用戶宣傳這個幹啥?幾時見到office宣傳自己是oop了?


本人科學計算和遊戲開發都做過,對此有一定的認識。面向對象在遊戲開發領域普及,或者說必不可少,而在科學計算領域不流行,是有它內在的原因的。

對於大型遊戲,遊戲過程複雜,涉及到人、物、環境之間的大量交涉,用面向對象去解決問題變得完全不可行。如果你指的俄羅斯方塊之類的小遊戲,那當我沒說。

對於大型科學計算,計算過程同樣很複雜,但都是有客觀規律可尋的,要不怎麼說叫科學呢。不外乎各種公式、方程等計算、迭代。這時可以用面向過程也可以用面向對象去解決,但面向對象的計算時間比面向過程的時間多N個數量級。科學工作者關心的是計算速度、計算精度和結果的可靠性。

軟體的開發,要從軟體的編寫、應用和維護升級等方面去考慮。

對於遊戲開發,

編寫:面向對象,1年;面向過程,50年。

應用:玩家在遊戲中發出一條指令,比如使用火球術。 面向對象的計算時間 5ms ;面向過程計算時間0.1ms ,但是玩家玩了幾分鐘,由於未知原因導致遊戲崩潰 。

遊戲的維護升級: 面向對象,1個月 ;面向過程,80年。

試想這樣的場景:1990年, 某老闆不知從哪裡忽悠來了千萬資金,雇了若干開發人員,開發一款名為俄羅斯方塊的全民掌游,準備大賺一筆。到了2040年,開發人員興奮地向老闆報告,我們精心研發50年的精品掌游通過測試,終於可以上線了。老闆撓著白花花的頭髮說,幼稚,現在大家都在玩的是開心消消樂!

對於大型科學計算,

編寫:面向對象,3個月;面向過程,6個月。

應用:模擬導彈在大氣中的飛行軌跡。面向對象的計算時間 50年;面向過程計算時間 6小時 。

維護升級: 面向對象,20天 ;面向過程,30天。

試想這樣的場景:2000年2月29日,中央氣象局準備對第二天的天氣進行預測,他們使用的計算程序是用面向對象編寫的。在2050年2月29日,得到了計算結果,當天的天氣預報中進行播報:各位觀眾,根據中央氣象局剛剛發來的消息,2000年2月30日的天氣是。。。。。。

當然,現在的科學計算都越來越集成化,系統化了,很多計算具有相似性,這樣可用面向對象去抽象出他們的共性。軟體和用戶交互的界面、數據輸入輸出,計算模型構建等可以用面向對象,但核心的計算部分仍然需要使用面向過程。


作為一個非計算機專業的人,的確不太懂什麼叫做面向對象編程,我這樣算得上面向對象編程了嗎?

(1)我寫計算程序的時候用用stl里的容器存儲數據,調用智能指針防止內存被吃光,寫寫輸出文件進行結果保存,用正則表達式判斷輸入文件名進行結果調用,用Eigen第三方庫或者調用matlab生成dll庫完成矩陣計算,當然也可以自己寫,不過基本想用的庫網上早有人造了輪子,也輪不到我費心;計算的時候為了同時計算幾個算例寫幾個多線程同時算,當然也可以多線程各自計算一個算例的幾個小方程,用互斥鎖實現控制,用log進行調試;為了出圖,再搞搞gdi,流行點搞搞opengl,或者懶點用matlab做個dll進行後處理。看了兩天c++14,再整兩行匿名函數在程序里趕趕時髦,挺好用的(感覺matlab里的函數句柄和stl里的仿函數好像)。為了理清上面這一堆東西的關係,畫一張UML圖放在論文里,我這樣算得上面向對象編程了嗎?

(2)除了有限元數值計算(偏微分方程數值解),還有哪些計算領域的編碼量級也很大呢?

(3)封裝、繼承、多態怎麼在科學計算領域應用呢?各位大佬舉個例子說,不講例子作為行外人,很難明白為什麼要這麼那麼做。


面向對象是一種程序設計思想,要理解這種思想並不十分容易,搞科學計算沒有用到,可能有兩個原因,一是不掌握這種方法,二是抽象不夠,搞高斯程序的哪些人,如果果放在現在,還會不使用面向對象方法嗎,不可能,並且可能不使用fortran,使用java.


因為大牛都很調皮,動不動上彙編搞性能,你說說這該怎麼面向對象


面向對象編程,不是必須的,樓主對面向對象編程還不是很理解,1)一些純計算的程序,不適合面向對象,比如計算你們家的水費之類,還有物理過程的程序,比如操作系統的程序,也不宜用面向對象寫,以前在網上,看到一個人問 linux發明者,為什麼不用C++,覺得也是一個外行問的問題。簡單地說,面向對象,適合大程序,而且是面嚮應用,而不是一個客觀的物理過程。面嚮應用的程序,往往需要總結成一些抽象概念,比如界面程序,數據處理程序,等等,按人的思維,如果你覺得需要把程序規整成幾個主觀概念時, 那就可以用到面向對象了。


推薦閱讀:

學 C 語言時,有沒有遇到過讓你「痛不欲生」、「揪心」或「不得要領」的術語?現在又是怎麼理解它的?
寫程序需要編譯器,編譯器是程序,輸入輸出也需要驅動,驅動也是程序,那麼第一個在電子計算機運行的程序是怎麼產生的?
Scheme語言的優勢?
Mathematica 能否成為取代 Python 乃至其他編程語言的程序設計語言?
新入職的軟體開發公司,看不懂代碼怎麼辦?

TAG:編程 | Fortran | 科學計算 | 計算化學 | 計算物理學 |