辛巴學院-Unity-劍英陪你零基礎學c#系列(四)函式和封裝

瘋光無線發表於2015-10-14

辛巴學院:正大光明的不務正業。

國慶長假結束了,我的心情是這樣的:

你總是起不早,起不早
獨自一個人沉睡到天亮
你無怨無悔的夢著那副本
我知道你根本就不想上班
你總是起不早,起不早
放假總是短暫,上班太難
請個病假,再睡上一天

今天我們聊c#的函式和封裝

這個話題其實你有無數的資料,每個寫過程式碼,沒寫過程式碼的人,都知道這些玩意。
我也沒有太多新奇的角度,先記住這一點

這不是數學,這不是數學,這不是數學。

我接觸最早的語言是basic,那個時候函式還沒有那麼深入人心,不是visual basic,dos時代接觸的。有一些系統函式可以呼叫,自己寫小程式卻鮮少定義函式,或許是不能定義,反正我學那會完全不知道。

講basic幹什麼?這不是關於c#的文章麼?只是告訴你,曾經存在不那麼依賴函式和封裝的語言,函式不是必須的。但c#,或者說c系語言,都是以函式和封裝作為基礎。那麼你可能會思考,一個不用函式和封裝的程式碼該怎麼寫?過去的basic 有行號,可以goto 到一行接著執行。我們就依靠這個goto,將程式碼劃分為幾塊,跳來跳去。

這實質上就是一個沒有語法保障的封裝,實質上就是函式。在c系語言,你也可以用goto,實際上編譯成機器語言以後,本來就是goto來goto去。

把一塊功能組織在一起,就叫做封裝。專門將一塊功能標記為一段子程式的語法,這就是函式。

每一行程式碼都是你的寶貴財產,比如衣服,兩三件的時候,隨便放在那裡就行了。幾十件的時候,不分類整理一下就有點麻煩了。幾百件的時候,可能還要先分房間再分衣架。

這種需求就是封裝的需求,它是隨著系統複雜度的提升,自然而然會出現的需求。

如果你一時還完全體會不到這種需求,那先不要去考慮研究函式,研究封裝,先去用一個函式寫完整個程式,一直如此,一直如此。如果最終你也無法感受到封裝的需求,那你也可以成為一個獨特的程式設計師。

C#的函式語法是這樣的    【修飾符】型別 函式名(【引數1】,【引數2】,…){…}

這玩意說不說也都差不太多,大家都知道。

怎麼設計函式?

最關鍵是你能體會那種看到一個500行的函式,有一種好想好想把他重新整理成好幾個函式的強烈衝動麼?

這種衝動是學習函式設計方法,也就是學習封裝的關鍵所在。

你也許已經發現很多優秀的程式設計師,他們卻說不出什麼,他們明明能寫出優秀的程式碼,卻不能解釋為何要如此寫,應用了何種方法或原則。

這一類程式設計師就是【本能型】,他們學會了基本的語法之後,跟著那種整理的衝動,一步步走向優秀。我認為本能型是最輕鬆的一種型別,愛和悟性,正是你最大的助力。

然而,世事總不如人意,總有些人需要一點幫助才能找到自己的切入點。

所以我們還是來探討一下,函式怎麼封裝?

從命名開始,再寫呼叫,至於實現,再說吧。

所有好的函式設計都是從命名開始的,然後編寫呼叫程式碼,至於實現,呵呵,愛誰寫誰寫,如果你沒有助手,那就是你寫。現在你可能對這個講法有著深深的懷疑,沒關係。我們先談命名。

你可能聽過幾種命名法,比如著名的匈牙利命名法。我們聊的是命名法的使命。命名法的使命是讓一個名字清晰,準確,易識別。就.這.麼.簡.單。

  1. 用英文。我不抵制拼音,我說的是用英文字母,別用中文或火星文,輸入起來太煩心,26個英文字母不借助任何輸入法可以用鍵盤敲出來,這是天然的優勢。無論你是怎麼樣的一個熱愛自己民族文化的人,我相信你也不願意抵抗這個優勢,你可以造一個5000個按鍵的鍵盤,每個鍵對應一個常用中文字,我十分懷疑你要花多久才能熟練使用這樣的一個鍵盤。至於用拼音,那只是一個low的問題,只是讓你看起來像是一個土撥鼠,話說回來,隨便查字典得來的英文要慎重,別隨便亂用,要查就查個徹底,搞清楚語境用法,否則也還是一隻土撥鼠。

 

  1. 無論哪種命名法,他都由單詞和分隔符兩個部分構成,有兩種世界通用分隔符,下劃線和駝峰法。舉例m_Gold DoSth別發明你自己的特別分隔方法。單詞沒關係,用簡寫一定要用約定俗成的,簡寫取幾個字元是不能亂來的,你自己定的規矩,別人怎麼可能懂,比如inte 你知道是個what? 用Integer 或者int。cha 你知道是個what?用character 或者 char。

 

  1. 函式名字是動賓短語,變數名字、型別名是定語修飾從句。好吧,先給語文老師上柱香,我也不確定我說的對不對。

    Void 打() 這就不是個好命名,因為沒賓語,根據上下文也推斷不出來打誰。Void 打豆豆()就好些了

    Void 轉圈() 這就問題不大,可以很容易推斷出是自己轉圈。此處用中文只是為了說明,別挑我理哦。

    Int 金幣 int 豆豆的金幣 根據上下文,他們都是語文,你要從語文的角度考慮話說清楚了沒。命名,本來就是文字的事兒。

命名說完了。

讓我們回到先寫呼叫還是先寫實現的問題上。這個問題有個有趣的現象,大部分新手程式設計師都認為應該先寫實現,當他們成為老手之後,就統一認為應該先寫呼叫。

我們來思考這樣一個問題?程式沒跑起來之前,程式設計師是否知道程式的執行順序。答案是知道。

我們再來思考這樣一個問題?一個不知道其細節實現的函式,程式設計師是否能使用,答案是能。

我們再來思考這樣一個問題?我們觀察程式結構是看什麼,看到我們欲觀察的結構的末端時?我們需要看其函式實現麼?答案是不需要。

程式設計就是程式沒跑以前先規劃好他怎麼跑,規劃程式怎麼跑就要設計程式的結構,就是設計誰呼叫誰,不知道實現細節的函式不影響我們設計程式

所以

永遠先寫呼叫,再寫實現,是程式設計的鐵則

我想說這就聊完了,不過還是要照顧一下悟性不高的同學。

還是不免俗的來幾條函式設計原則:

函式不要太長,100行以上就值得再思考一下了,空行不算。

所有的設計原則基本上都是經驗原則,100 80 200 你也可能會聽到各種版本,沒關係,都一樣,都是個經驗數字。這個原則的出發點是別寫太長,不容易看懂

函式命名就已經決定了函式做什麼事,聚焦在這件事上,無論引數、返回值實現都要忠於這件事,否則,去另一個函式。

    在閱讀時好的函式是不需要看其實現就能理解其作用的,一個與命名不符的函式就是一個坑,雖然每個程式都是在坑人與被坑之中成長的,但是提前記得這個原則,會給你提供一定的幫助。

函式的一致性,就是函式的輸入一致,輸出就應該一致。

函式別增加和他無關的狀態,這一條理解起來比較困難,所以我們分開講

隨機數函式表面看起來每次的輸入都是空,返回都不同,其實並不是如此,隨機數函式有個隱形輸入,隨機種子。隨機種子一樣,隨機數函式返回就一樣。

所有的函式都是這樣的,計算機中不存在不確定的狀態,所有的狀態都確定,只有像隨機種子、時間這類程式碼閱讀者不易察覺的隱形狀態。

這一條就是說要慎重設計函式的隱形狀態,保持其從外部易於觀察。

比如你寫了一個函式 addrandhp(10),然後其行為是加 5 到 15點血,在10 加正負5範圍。這就有個隱藏狀態正負5之間的隨機。

Addrandhp(5,15)用這樣的設計方式就從外部容易理解其行為。

函式應儘早報告錯誤,比如先檢查下輸入是否合法。

    在執行中函式出錯,應該給予正常的異常反饋,用throw xxx,這也是有爭論的,有不同的方法論。但是微軟的類庫裡都是儘量早丟擲異常的,我們跟隨微軟的風格。

 

不知不覺可能把零基礎系列做的比較複雜了,可能我就適合寫這種裝逼效果的文字,反省反省。

再會,哈庫拉瑪塔塔

相關文章