主頁 > 後端開發 > 關于清潔代碼的規范性疑問

關于清潔代碼的規范性疑問

2020-10-28 05:59:23 後端開發

看過一些關于代碼封裝的規范的書,不乏一些國外大牛的書,我印象比較深的比如:一個函式的代碼不應該超過20行。
我是從來沒有遵循這個規則,也不太能理解為什么要這樣做的原因。我自己始終覺得“業務完整性”的表述更重要。比如一個“業務”實作的代碼,如果要通過多個函式,甚至于多個逐層呼叫的函式來完成,這種業務代碼在我來看,是很難閱讀的(需要不斷的進入/跳出函式,這很打斷思路),所以我自己的習慣始終是,一個“業務”的代碼,順序讀下來,代碼間分段明確,注釋足夠,閱讀效果是最好的,幾百行代碼讀起來完全不費勁。

當然,我以前不太寫c代碼,我寫的是c#這種代碼,使用的是VS這種高級IDE,是不是這種高級語言和高級IDE下,代碼規范如我這樣寫更好?我也只是猜測。

最近在看一個歷史專案的c代碼,把我這個疑問又勾起來了,我把它作為案例,拿出來問問大家。
它是這樣的,在一個實作中,封裝了七八層函式,這些函式都只被呼叫過一次,也就是函式封裝起來只是被一個地方呼叫。那我就奇怪了,這樣的話封裝起來干嘛?封裝起來不應該是為了“復用”嗎?

這些函式,依次被呼叫,且僅呼叫一次:
parseVarBind()
parseSequence()
parseSequenceOf()
parseRequest()
parseCommunity()
parseVersion()
parseSNMPMessage()
SnmpXDaemon()

代碼類似:

SnmpXDaemon()
{
//一些代碼
parseSNMPMessage()
{
//一些代碼
parseVersion()
{
//一些代碼
parseCommunity()
{
//一些代碼
parseRequest()
{
//一些代碼
parseSequenceOf()
{
//一些代碼
parseSequence()
{
//一些代碼
parseVarBind()
{

}
//一些代碼
}
//一些代碼
}
//一些代碼
}
//一些代碼
}
//一些代碼
}
//一些代碼
}
//一些代碼
}


請問:
這種封裝方式,每個函式的代碼量是不多,每個函式不超過50行,但
1、這種封裝方式合理嗎?
2、如果合理,為什么合理?

uj5u.com熱心網友回復:

請牢記:源代碼本身的書寫是否結構化或面向物件或符合設計模式或敏捷…并不重要,重要的是你是否使用結構化或面向物件或符合設計模式或敏捷…的方法命名識別符號、閱讀、修改、檢查、測驗源代碼。

意思是你程式結構看上去再合理,再簡潔,也不一定比看上去一團亂麻的程式結構在運行或修改時更不易出錯,更方便修改,出錯了更容易找到哪里出錯和具體出錯的原因,更容易改正錯誤。

試對比
圖書館(對圖書的分類夠結構化了吧)

搜索引擎(可看作是扁平化任何結構資料,僅支持全文檢索)
哪個處理資訊更方便、更高效。

所以
與其費勁去重構代碼讓其看上去更簡潔、更合理
不如費勁學習grep、sed、awk、……這類全文搜索和批處理編輯的工具。

結構越復雜,越難修改,越難除錯。
有時(甚至大多數時候),看上去越合理、越簡潔的代碼,運行起來性能越差,出錯時查找原因越難,找到出錯原因后改正越費勁。

程式員要做的不是盡力避免錯誤,而是聚焦在快速發現并改正錯誤。真正以快速方式輕易解決錯誤,“快速的失敗”遠勝過“預防錯誤”。Fred George

前微軟C#編輯器的開發主管Jay Bazuzi列出的一些有助于找到正確方向的問題;他覺得前同事們應該用這些問題來問自己;實際上不管在哪里作業的開發者們都應該經常問問自己這些問題:
◆“要保證這個問題不會再出現,我該怎么做?”
◆“要想少出些Bug,我該怎么做?”
◆“要保證Bug容易被修復,我該怎么做?”
◆“要保持對變化的快速回應,我該怎么做?”
◆“要保證我的軟體的運行速度,我該怎么做?”
如果大多數團隊都能不時問一下自己,必定會從中得益,因為這些都是真正強而有力的問題。

uj5u.com熱心網友回復:

復用只是封裝的作用之一
還有其他作用 比如擴展 比如修改
比如說 業務變更 之前只需要考慮 <label 開頭的標簽
現在需要多處理一個 <edit 開頭的標簽
你沒做封裝 那么你可能需要在一個幾百行的函式內部逐行確認才能找到什么地方添加這個功能
你做了封裝 定位到對應函式 可能就十幾行代碼的事情
雖然這個函式你只呼叫1次 但是你修改起來定位代碼非常方便 


或者說這樣
parseVarBind()
parseSequence()
parseSequenceOf()
parseRequest()
parseCommunity()
parseVersion()
parseSNMPMessage()
SnmpXDaemon()
假設這里面parseVersion()是暫時不需要 我想屏蔽
不管是在這里直接注釋函式呼叫
還是到parseVersion()函式里面直接在第一行寫return 
都能非常簡單的完成

如果你的代碼不是這個結構
而是一個幾百行的代碼
你需要從里面找出幾十行代碼 然后再做注釋
多注釋了一行 或者少注釋一行 就可能導致bug

等等等等

uj5u.com熱心網友回復:

我個人代碼一個函式差不多50行左右,最多不會超過80行,超過的話就會拆。我很擁護這個規則的,原因有兩個方面:
1、可讀性
首先把功能單一的代碼拆成小函式有利于代碼閱讀,代碼寫出來是給人讀的嘛

SnmpXDaemon()
{
       // 幾百行代碼
}

看起來肯定沒有

SnmpXDaemon()
{
      parseVarBind()
      parseSequence()
      parseSequenceOf()
      parseRequest()
      parseCommunity()
      parseVersion()
      parseSNMPMessage();
}

這種邏輯清晰,易讀性強。對于代碼的第一個作者而言,一個函式幾百行代碼沒什么問題,但是對于后續維護人員來講,很痛苦,后來維護的人基本不會閱讀所有的代碼,都是看主干,看思路,看自己關心的那一段,所以函式、變數名字一定要取好,對于上面那個SnmpXDaemon()函式來說,如果采用第一種寫法,我不得不把幾百行代碼都看完,但是對于第二種,我可能就看那么幾行,因為一看到parseVarBind()這種我就知道這個函式在做什么,大體也知道它怎么實作的,如果我對這個函式很關心或者不知道它的實作,那我可能就會去看parseVarBind()它的實作,但是不會去看parseVersion()的實作,當然最重要的是邏輯思路,如果一個函式幾百行,如果你不把注釋寫好,我去理解你的思路是很花時間的,因為大家的思維方式可能不一樣,比如我這種吃香蕉從香蕉屁股那端剝的人在看到同事吃香蕉從香蕉蒂那端剝的時候我就震驚了,就算你代碼注釋非常好,但是你也很難保證后續的維護者跟你一樣把代碼注釋寫好,而且人家改動代碼的時候還要去維護你的注釋,但是第二種寫法思路就很清晰,都不用寫注釋,一看就知道先做什么再做什么最后做什么(前提是函式、變數名一定要取好!)。
再說樓主貼的那段代碼,如下:
SnmpXDaemon()
{
    //一些代碼
    parseSNMPMessage()
    {
        //一些代碼
        parseVersion()
        {
            //一些代碼
            parseCommunity()
            {
                //一些代碼
                parseRequest()
                {
                    //一些代碼
                    parseSequenceOf()
                    {
                        //一些代碼
                        parseSequence()
                        {
                            //一些代碼
                            parseVarBind()
                            {
 
                            }
                            //一些代碼
                        }
                        //一些代碼
                    }
                    //一些代碼
                }
                //一些代碼
            }
            //一些代碼
        }
        //一些代碼
    }
    //一些代碼
}

這個代碼就很難看,為什么不這樣呢:
SnmpXDaemon()
{
    //一些代碼
    parseSNMPMessage();
    //一些代碼
}

然后parseSNMPMessage()函式里面如SnmpXDaemon()一樣,這樣的話兩個好處,首先如同我上面說的,其次就是減少了橫向的縮進,閱讀代碼的時候還要用滑鼠拉代碼編輯器的橫向滾動條我覺得也是個比較糟糕的體驗。
2、復用性
多用小函陣列合的第二個好處我覺得就是復用性,如果一個邏輯功能被多處使用,封裝成小函式以提高靈活性,相信是寫過代碼的人共識,樓主的疑惑在于拆出來的函式只用了一次,沒有被別的地方使用,所以感覺沒有拆的必要。但是以我的經驗,這個是很必要的,因為你寫的時候確實可能只有一處呼叫,但是你后來維護的人,可能因為業務的發展變遷,功能擴展什么的,你那個函式就有可能會被多處呼叫,試想一下某天你擴展個功能,突然發現你需要的功能別人已經實作了,你只需要傳個引數呼叫一下,是多么讓人激動的事兒!
把代碼拆分成小函式間接呼叫會影響性能,這個不可否認,但是按照80-20法則,影響性能的只是那20%的代碼而已,所以在寫代碼的時候,優先保證結構性,可讀性(當然很明顯的問題,比如100w個資料你非得用個冒泡排序那種就不說了哈),等寫完除錯的時候,發現確實有性能上的問題,再來有針對性的優化,而且你要因為多了幾層間接呼叫影響性能了來優化代碼,優化到這個份上,我還從未見過...

uj5u.com熱心網友回復:

如果一個業務太龐大太復雜了,寫完整個流程需要5萬行,你是不是準備一個函式整5萬行?

uj5u.com熱心網友回復:

參考 1 樓 趙4老師 的回復:
請牢記:源代碼本身的書寫是否結構化或面向物件或符合設計模式或敏捷…并不重要,重要的是你是否使用結構化或面向物件或符合設計模式或敏捷…的方法命名識別符號、閱讀、修改、檢查、測驗源代碼。

意思是你程式結構看上去再合理,再簡潔,也不一定比看上去一團亂麻的程式結構在運行或修改時更不易出錯,更方便修改,出錯了更容易找到哪里出錯和具體出錯的原因,更容易改正錯誤。

試對比
圖書館(對圖書的分類夠結構化了吧)

搜索引擎(可看作是扁平化任何結構資料,僅支持全文檢索)
哪個處理資訊更方便、更高效。

所以
與其費勁去重構代碼讓其看上去更簡潔、更合理
不如費勁學習grep、sed、awk、……這類全文搜索和批處理編輯的工具。

結構越復雜,越難修改,越難除錯。
有時(甚至大多數時候),看上去越合理、越簡潔的代碼,運行起來性能越差,出錯時查找原因越難,找到出錯原因后改正越費勁。

程式員要做的不是盡力避免錯誤,而是聚焦在快速發現并改正錯誤。真正以快速方式輕易解決錯誤,“快速的失敗”遠勝過“預防錯誤”。Fred George

前微軟C#編輯器的開發主管Jay Bazuzi列出的一些有助于找到正確方向的問題;他覺得前同事們應該用這些問題來問自己;實際上不管在哪里作業的開發者們都應該經常問問自己這些問題:
◆“要保證這個問題不會再出現,我該怎么做?”
◆“要想少出些Bug,我該怎么做?”
◆“要保證Bug容易被修復,我該怎么做?”
◆“要保持對變化的快速回應,我該怎么做?”
◆“要保證我的軟體的運行速度,我該怎么做?”
如果大多數團隊都能不時問一下自己,必定會從中得益,因為這些都是真正強而有力的問題。

趙4老師是跳出問題回答問題了吧。新的問題可能是:對于最后的問題,不同的人和團隊,回答可能是不一樣的。

uj5u.com熱心網友回復:

現在沒有復用、修改不代表以后也不會。所以,作為一個好習慣,就是總為復用、修改留下余地。
你這個有點類似:現在馬路上又沒車,你為啥不闖下紅燈。對錯、好壞自己判斷。

uj5u.com熱心網友回復:

參考 2 樓 lin5161678 的回復:
復用只是封裝的作用之一
還有其他作用 比如擴展 比如修改
比如說 業務變更 之前只需要考慮 <label 開頭的標簽
現在需要多處理一個 <edit 開頭的標簽
你沒做封裝 那么你可能需要在一個幾百行的函式內部逐行確認才能找到什么地方添加這個功能
你做了封裝 定位到對應函式 可能就十幾行代碼的事情
雖然這個函式你只呼叫1次 但是你修改起來定位代碼非常方便 


或者說這樣
parseVarBind()
parseSequence()
parseSequenceOf()
parseRequest()
parseCommunity()
parseVersion()
parseSNMPMessage()
SnmpXDaemon()
假設這里面parseVersion()是暫時不需要 我想屏蔽
不管是在這里直接注釋函式呼叫
還是到parseVersion()函式里面直接在第一行寫return 
都能非常簡單的完成

如果你的代碼不是這個結構
而是一個幾百行的代碼
你需要從里面找出幾十行代碼 然后再做注釋
多注釋了一行 或者少注釋一行 就可能導致bug

等等等等

是,這是一種可能性,不過按照我的經驗,
1、寫代碼的人自己修改,那封裝和不封裝,差別很小,這只是個人習慣差別
2、對于修改他人的代碼,對于我來說,我不敢不去看封裝方法里邊的代碼,那相當于蒙眼狂奔。我的習慣都是,看明白了才能改。
3、多數情況下,閱讀代碼的時間大大多于修改代碼,所以閱讀代碼的方便性應該提升。

題外話,對于我舉的這個案例,它的七八個封裝函式,都沒有函式注釋,不除錯很難明確這些函式的功能。而且這些函式分別的反復操作一些全域變數,看起來封裝度也差。如果真的對代碼clean理解深入的人,不應該搞出這么分裂的現象。所以總體上,我覺得至少這個案例,七八個函式都是唯一呼叫,應該是封裝過度了。

uj5u.com熱心網友回復:

參考 6 樓 taodm 的回復:
現在沒有復用、修改不代表以后也不會。所以,作為一個好習慣,就是總為復用、修改留下余地。
你這個有點類似:現在馬路上又沒車,你為啥不闖下紅燈。對錯、好壞自己判斷。

我的看法,是剛好相反的。這是我做產品時總結的:簡潔的設計,不要過度設計產品,讓產品生長,而不是設計。我個人認為代碼也應該如此,代碼的封裝不要過度設計,以為未來會如何如何復用,其實往往最后就沒有復用。這個案例就是如此,產品定型了,也沒有復用。
我認為好代碼也應該是,根據需求迭代出來的,那才是最簡潔的代碼。不要怕未來改代碼,未來在迭代時有復用需求了再復用。

uj5u.com熱心網友回復:

參考 6 樓 taodm 的回復:
現在沒有復用、修改不代表以后也不會。所以,作為一個好習慣,就是總為復用、修改留下余地。
你這個有點類似:現在馬路上又沒車,你為啥不闖下紅燈。對錯、好壞自己判斷。

我這么說的意思,也不是說我自己想闖紅燈,其實我對代碼整潔也是有追求的,我只是覺得有些時候不應該過度設計。不是說要在路口闖紅燈,而是比如50年前,大家都在用手推車的時候,十字路口不需要設定紅燈。

uj5u.com熱心網友回復:

既然如此你不應該有疑問
你的體驗就是都寫在一起方便你就都寫在一起
相信自己 

uj5u.com熱心網友回復:

反正我的體驗是封裝了更方便 大家敬而遠之

uj5u.com熱心網友回復:

覺得不用死守著超過50行就要拆,有的如果真的沒必要拆,就留著吧
但是如果一個函式動不動就幾百行,這個肯定是不好維護的

uj5u.com熱心網友回復:

你認為已經過度了,大師們還嫌不夠。你認為以后可以重構/重用,大師們認為以后根本不會給你這個時間、機會。
所以,這樣多討論是沒有結果的。
自己理解,自己成長,走自己的路。

uj5u.com熱心網友回復:

除了代碼重用,擴展,還有一個作用,就是方便單體測驗
如果只改動了某個函式,單體測驗之要測驗該函式就可以了,寫在一起就要整體測驗(相當于結合測驗了)
當然,至于怎么劃分模塊合理,那就具體問題具體分析了。

uj5u.com熱心網友回復:

參考 13 樓 taodm 的回復:
你認為已經過度了,大師們還嫌不夠。你認為以后可以重構/重用,大師們認為以后根本不會給你這個時間、機會。
所以,這樣多討論是沒有結果的。
自己理解,自己成長,走自己的路。

是的,路還是要自己走出來的。

uj5u.com熱心網友回復:

參考 14 樓 qybao 的回復:
除了代碼重用,擴展,還有一個作用,就是方便單體測驗
如果只改動了某個函式,單體測驗之要測驗該函式就可以了,寫在一起就要整體測驗(相當于結合測驗了)
當然,至于怎么劃分模塊合理,那就具體問題具體分析了。

單元測驗,這點,不可否認。幾百行的代碼,確實對單元測驗來說是很糟糕的。如果有一票否決,那么這個理由比較充分。不過同時,做好單元測驗的程式員少之又少,及其優秀的專案,可能才會考慮到單元測驗這么完善。

uj5u.com熱心網友回復:

總結起來說,我也不是說就是不認可大師們的觀點,大師們這么做應該有他們的道理,只不過我從自己的經歷來說,不能體會到這樣做有那么多的好處,反而缺點挺多。而我也想想明白了再干,不想盲從。
我能想到的幾點,需要短函式的原因是:
1、單元測驗:測驗單元越短越好。
2、低級語言:比如c/c++這種稍低級的語言,涉及到比較多的運算,代碼相對的不那么容易看懂,封裝有利于功能的模塊化和理解。而我使用c#等高級語言多了,這些高級語言表達力強,即使寫上100行,其閱讀性也還是非常強。所以相應的對短函式的要求降低了。

以后會嘗試寫短一些的函式和方法,更深入的體會一下短函式的優缺點。

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/194742.html

標籤:模式及實現

上一篇:求斐波那契數列N項,求助!

下一篇:求大佬看看,

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more