內(nèi)含C語(yǔ)言、java、數(shù)據(jù)庫(kù)新手錯(cuò)誤集錦
還記得你剛學(xué)C語(yǔ)言的情形嗎?當(dāng)初看上他,可能是因?yàn)槿腴T學(xué)的,可能是因?yàn)樗葟?qiáng)大,又靈活;不管因?yàn)槭裁丛?,你都入了C語(yǔ)言這個(gè)坑,現(xiàn)在回想起來(lái),剛?cè)肟幽菚?huì),是不是也犯過(guò)一些初級(jí)的錯(cuò)誤呢?比如說(shuō):
1、標(biāo)識(shí)符不區(qū)分大小寫
C語(yǔ)言習(xí)慣上,符號(hào)常量名用大寫,變量名用小寫表示,以增加可讀性;
2、忽略了變量的類型,進(jìn)行了不合法的運(yùn)算
%是求余運(yùn)算,得到a/b的整余數(shù)。整型變量a和b可以進(jìn)行求余運(yùn)算,而實(shí)型變量則不允許進(jìn)行“求余”運(yùn)算。
3、將字符常量與字符串常量混淆
char c;
c='a';
在這里就混淆了字符常量與字符串常量,字符常量是由一對(duì)單引號(hào)括起來(lái)的單個(gè)字符,字符串常量是一對(duì)雙引號(hào)括起來(lái)的字符序列。C規(guī)定以“\”作字符串結(jié)束標(biāo)志,它是由系統(tǒng)自動(dòng)加上的,所以字符串“a”實(shí)際上包含兩個(gè)字符:‘a(chǎn)'和‘\',而把它賦給一個(gè)字符變量是不行的。
4、忽略了“=”與“==”的區(qū)別。
在許多高級(jí)語(yǔ)言中,用“=”符號(hào)作為關(guān)系運(yùn)算符“等于”。如在BASIC程序中可以寫
if (a=3) then …
但C語(yǔ)言中,“=”是賦值運(yùn)算符,“==”是關(guān)系運(yùn)算符。如:
if (a==3) a=b;
前者是進(jìn)行比較,a是否和3相等,后者表示如果a和3相等,把b值賦給a。由于習(xí)慣問(wèn)題,初學(xué)者往往會(huì)犯這樣的錯(cuò)誤。
5、該加分號(hào)的時(shí)候忘記加,不該加的時(shí)候又加上了
少加分號(hào)的情況:
多加分號(hào)的情況:
最重要的是,在編輯器報(bào)錯(cuò)時(shí),你卻查不到錯(cuò)誤,最后發(fā)現(xiàn)把;寫成了;
同比,雖然java和C是不一樣的語(yǔ)言,但是我們可以看到,新手期犯的錯(cuò)還都差不多,比如說(shuō):
1、不區(qū)分大小寫的情況
變量money和Money,雖然是一個(gè)單詞,但是不一樣的,一定要記得;
2、將數(shù)組轉(zhuǎn)化為列表
將數(shù)組轉(zhuǎn)化為一個(gè)列表時(shí),程序員們經(jīng)常這樣做:
3、判斷一個(gè)數(shù)組是否包含一個(gè)值
程序員們經(jīng)常這樣做:
4、一個(gè)等號(hào)和兩個(gè)等號(hào)的不同
在Java程序中,一個(gè)等號(hào)是賦值操作符,而兩個(gè)等號(hào)則是比較操作符。在java新手的程序中經(jīng)常出現(xiàn)這樣的代碼:
5、空引用的錯(cuò)誤
這類錯(cuò)誤也是最令人頭疼的,屬于邏輯性錯(cuò)誤,編譯器可以正常編譯,但是在某種情況下執(zhí)行出錯(cuò),出錯(cuò)信息是java.lang.NullPointerException。
這是由于在對(duì)象的引用沒(méi)有被初始化的情況下而調(diào)用這個(gè)對(duì)象的屬性或者方法而造成的,比如下面的例子:
說(shuō)完語(yǔ)言,我們?cè)賮?lái)看看數(shù)據(jù)庫(kù)新手們,都常犯什么錯(cuò)誤:
1、Storing images儲(chǔ)存圖片
數(shù)據(jù)庫(kù)里不應(yīng)該放圖片。你可以做的事情并不代表你就應(yīng)該去做。圖片會(huì)占用數(shù)據(jù)庫(kù)里相當(dāng)大的空間,吃掉不必要的IO資源從而拖慢應(yīng)用。這個(gè)錯(cuò)誤最常出現(xiàn)的情況,就是新人將圖片用base64編碼,然后將其儲(chǔ)存在很大的text/blob字段當(dāng)中。
2、Limit/Offset
分頁(yè)在很多應(yīng)用中都非常常見(jiàn)。從你開(kāi)始學(xué)習(xí)SQL,(你就該知道)最直接的分頁(yè)方法就是先用ORDER BY對(duì)數(shù)據(jù)庫(kù)的一些列進(jìn)行排序,然后LIMIT返回的結(jié)果數(shù),對(duì)除第一頁(yè)外的每一頁(yè)使用OFFSET。這看起來(lái)很符合邏輯,直到你處理中等規(guī)模應(yīng)用時(shí)才意識(shí)到:
它對(duì)數(shù)據(jù)庫(kù)施加的負(fù)載是非常痛苦的。
它具有不確定性,記錄應(yīng)該隨著用戶翻頁(yè)而改變。
3、用整數(shù)做primary key
在創(chuàng)建primary key的時(shí)候,幾乎所有的ORM(Object Relational Mapping對(duì)象關(guān)系映射)的默認(rèn)做法都是創(chuàng)建一個(gè)串行字段,它是按順序自動(dòng)生成的,然后你就可以用它(這些自動(dòng)生成的數(shù)字)作為你的primary key。在管理員看來(lái),這是非常直觀的,因?yàn)榭梢杂捎脩?到用戶2這樣依次查看。對(duì)大多數(shù)的應(yīng)用來(lái)說(shuō),這種做法通常是不錯(cuò)的。但是隨著這些整數(shù)primary key不斷變大,你很快就會(huì)意識(shí)到處理他們會(huì)讓人筋疲力盡。對(duì)于大規(guī)模系統(tǒng),這是很不理想的處理方法。此外,你還會(huì)依賴生成這些key的那個(gè)系統(tǒng),在你必須要擴(kuò)大規(guī)模的時(shí)候,會(huì)非常痛苦。更好的解決辦法是從一開(kāi)始就利用好UUID(Universally Unique Identifier通用唯一識(shí)別碼)的優(yōu)勢(shì)。
4、新列中的默認(rèn)值
無(wú)論你做這個(gè)工作有多久,都不會(huì)一次就創(chuàng)建出一個(gè)完美的schema。最好是將數(shù)據(jù)庫(kù)schema視為一個(gè)持續(xù)演化的文檔。不幸的是:向數(shù)據(jù)庫(kù)中添加一列是件很容易的事,這也就意味著在添加列的時(shí)候把工作搞砸同樣很容易。默認(rèn)情況下,如果你新添加了一列,通常是允許有NULL值的。這個(gè)操作速度很快,但大多數(shù)應(yīng)用實(shí)際上不太想讓他們的數(shù)據(jù)里有null值,他們會(huì)想要設(shè)置默認(rèn)值。
如果你在表里添加設(shè)置了默認(rèn)值的新列,會(huì)對(duì)這張表觸發(fā)一次完全的重寫。注意:這對(duì)應(yīng)用中的任何(數(shù)據(jù)量)很大的表都非常不利。(正確的方法)恰恰相反,最好是先允許null值存在,這樣操作就是即時(shí)的,接下來(lái)再設(shè)置默認(rèn)值,再用后臺(tái)進(jìn)程去回溯更新數(shù)據(jù)。
5、過(guò)度標(biāo)準(zhǔn)化
開(kāi)始學(xué)習(xí)數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)化的時(shí)候,(標(biāo)準(zhǔn)化)感覺(jué)就像是很正確的事。你創(chuàng)建了一個(gè)posts的表,里面包含authors,每篇文章(post)都屬于一個(gè)條目(category),所以你又創(chuàng)建了一個(gè)categories的表,然后再創(chuàng)建一個(gè)把它們倆join在一起的表,post_categories。從根本上來(lái)說(shuō),這樣做標(biāo)準(zhǔn)化也沒(méi)什么原則上的錯(cuò)誤,但是某種程度上,標(biāo)準(zhǔn)化的收益正在遞減。
在上述實(shí)例中,categories可以簡(jiǎn)單地作為post里的一個(gè)varchar字段。標(biāo)準(zhǔn)化是件很有意義的工作,但是每次處理包含多對(duì)多關(guān)系的表時(shí)都要深思熟慮,想想你是不是真的需要在關(guān)系的兩邊都各用一個(gè)單獨(dú)的表。
歡迎各位看官們補(bǔ)充~
吃瓜觀眾可點(diǎn)一波關(guān)注壓壓驚(還好我繞過(guò)了這些坑)
恒生開(kāi)發(fā)者社區(qū)-恒生電子面向所有開(kāi)發(fā)者提供的服務(wù)分享、技術(shù)交流和互聯(lián)共通等一站式服務(wù)平臺(tái)。
聯(lián)系客服