歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

編程基本功觸類旁通

Spark 是用scala寫的,storm是clojure開發的,docker采用了go, 各種編程語言層出不窮,但其實都是馬甲,作為一個程序員,我們需要理解那些相通的本質,做到觸類旁通.
 
程序中的基本邏輯控制——跳轉,在匯編語言中早就有滿足條件後跳轉的命令了。所謂跳轉,就是告訴機器到那去干活. 就像過去的接線員那樣,因而C語言中有個goto語句,它是跳轉的最直接的解釋.
 
如果程序中goto多了,恐怕沒誰能看懂了. 為了避免goto語句的不便理解,C語言中的if...else語句就變得更讓人歡迎了。滿足條件時反復執行某區間的代碼,goto語句都能做到,而while和break語句所作的事情不是增加了新功能,而是提高了程序的易讀性和易寫性。for 語句只是讓數值漸增的while語句更簡潔而已,而foreach語句是為了方便編寫對某對象內的所有元素進行某種處理的代碼。

函數是為了程序的便於理解和重復使用,把代碼的一部分視作有機的整體,然後切分出來並為之命名,這是一種程序設計機制。函數催生了return語句,能夠使函數調用後回到程序執行的原來內存地址,使用函數給操作命名的辦法來表示操作開始時內存的位置。棧是一個存儲有多個值的數據結構,實現後進先出,是管理函數操作的有力工具。了解棧,就可以解釋運行時的函數行為了。

遞歸調用是函數使用的一種方式,是指函數內部再次調用當前函數的過程。當多重嵌套的數據結構無法用for語句實現時,就需要使用遞歸調用了。

一個程序中尤其在一個函數中,錯誤處理的傳達方法主要有兩種:
1)通過函數的返回值來傳達出錯的信息,調用者通過返回值來判斷進行相應的錯誤處理
2)預先設定好錯誤處理的代碼,錯誤發生時能跳轉到相應的錯誤處理代碼。
方法一存在兩個問題,分別是錯誤遺漏和錯誤處理導致代碼的可讀性下降;對於方法二中可追加錯誤類型和可自主出發出錯,這兩種功能被現代的異常處理機制所繼承。

異常處理逐漸成為了錯誤處理的主要傳達機制. try 是一個為了方便理解的修飾符,觸發異常的表述為拋出異常,異常處理在except中,出錯也要執行的關鍵字為finally。而c++采用了資源獲取即初始化技術,通過自動調用析構函數來實現類似的機制。一般地,函數調用參數不足時,數組越界等情況,都要拋出異常。Fail First,即異常處理優先, 但是,檢查型異常是比較麻煩的.

關於變量,整個程序共用一個參照表,即全局變量的使用范圍,作用域是指名字的有效范圍。動態作用域是把變量原來的值事先保存在函數入口處,在出口處寫回變量中的方式,靜態作用域按函數區分各自的對照表,避免全局污染的原因就在於此。一般地,一個程序都會有整體對照表(內置),一張文件級對照表(全局),和一張函數級的對照表(局部)。

千萬別輕易認為自己了解了數據類型,類型是個復雜的概念.類型是人們給數據附加的一種追加數據,最初是為了加入數值的類型信息,告訴編譯器如何處理,而後,用戶自定義類型和面向對象同樣是類型,從而產生了作為功能的類型,進而發展為接口,出現了泛型和模板等。把類型的信息和數值看做整體的方式叫做動態類型,在內存上使用了同等類型對待的設計方法,支持類型推斷。例如python,都是PyObject。 從內存和何時使用的角度來看待類型會更清晰。

從存儲的形式看變量, 存放多個元素的東西可以理解為容器,容器中的數據存在內存中,存儲的方式不同容器的體現也不同。數組是順序存放的,鏈表同時存放了相對地址,因而對元素多插入頻繁的情況,鏈表更適合。為了簡潔地表達計算時間和數據量之間的關系,一般采用O表示法。O(n)是n的數量級,O(1)是常數數量級,樹(平衡)中元素的讀取時間為O(log n)。

字符串博大精深,是非常重要的元素. 北郵門口的摩爾斯碼,到後來各種的字符集編碼,程序中多用注釋來指明編碼方式,unicode帶來了統一。一般語言的字符串都帶有自身的長度,c中的字符串不知道自身的長度,是最為原始的字符串,NUL即\0是表示字符串終止的特殊字符。Unicode是16bit還是32bit是在編譯時通過選項指定的。

並行處理越來越被關注, 單cpu的並行處理實際上是分時交替處理,交替方式有:
1)協作式多任務——在合適的節點交替,基於信任,所有處理都會在適當的間隔後交替處理
2)搶占式多任務——一定時間後交替,不需要終止程序的協助就可以單方面終止它
搶占式多任務存在競態條件(race condition),或者稱為線程安全,競態條件成立的三個條件:
1)兩個處理共享變量
2)至少一個處理會對變量進行修改
3)一個處理未完成前另一個處理會介入進來
只要三個條件有一個不具備,就可以寫線程安全的程序了。
規避一,沒有共享內存,就不存在競態條件了,例如利用獨立進程和actor模型。
規避二,比如C++中的const,scala中的val,Java中的immutable
規避三,不介入,使用協調模式的線程如coroutine等,也可以使用表示不便介入的標識——鎖、mutex、semaphore,實際上是使用中的狀態牌。鎖的使用問題包括死鎖和無法組合,只能寄托於事務內存來奢望解決了。

關於面向對象的解釋, 至少有兩種截然不同的含義:
1)class是一種創建用戶自定義類型的功能,面向對象是使用用戶自定義類型和繼承的程序設計
2)通過不同狀態的對象互相傳送消息來通信的程序設計就是面向對象
歸集變量和函數建立模型的方法有:
1)模塊,將相互關聯的函數集中在一起,將初始化處理也放入包中即構造函數,例如perl
2)將函數和變量放入散列中,例如javascript
3)閉包,通過命名空間來歸集,是創建具有對象性質的的事務的一種技術。一個包含了自由變量的開發表達式,和該自由變量的約束環境組合在一起後,實現了一種封閉的狀態。

對象是現實世界的模型,類在不同語言裡的意義不同,沒有一個通用的解釋,除了Java外,類不是不可或缺的。
類的存在只是為了更方便書寫程序而約定的一種規則,無他。class最初有分類的含義,還表示類型,還有功能說明的作用,概念復雜。C++和Java的類主要有以下作用:
1 ) 整體的生成器
2)可行操作的功能說明
3)代碼再利用的單位

類繼承的三種實現策略:
1)一般化與專門化:子類是父類的專門化
2)共享部分提取:在多個類中提取共享部分作為父類
3)差異實現:把繼承作為實現再利用的途徑
為了保證理解的簡易性,要防止繼承樹的層級過多。一般采用裡氏置換法則:對於類T的對象一定成立的條件,對於類T的子類S的對象也必須成立。

多繼承問題的解決方案主要有:
1)Java語言中禁止了多重繼承,取而代之的是委托和接口
2)按順序搜索,例如python中使用了C3線性化
3)混入式處理
4)trait認為類同時具有的作為再利用代碼單元和實例生成器,這兩種作用是相反的,把再利用單元的作用特別化,設定一些更小的結構(特性=方法組合)。

Copyright © Linux教程網 All Rights Reserved