The two most important days in your life are the day you were born and the day you find out why. -Mark Twain

#6 資料結構 - Stack - part 2

承接上一篇的內容,我們要用什麼方式來做 Stack 的 "容器" 呢? 我們前面提過 Array 和 List,你覺得那一個用來做為 Stack 的容器比較適當?

我們在前面談過 Array 和 List,兩者最大的差異在於物件位於記憶體上的位置是緊連在一起還是允許分散的.如果緊連在一起,則讀取速度快,如果是分散的,則讀取速度慢.光是這一點,我想 Array 就足夠成為我們做為 Stack 容器的人選了.接下來我們用一個簡單的模型來談如何用 Array 做 Stack 的容器.



上圖是一個 Array,這裡頭一開始宣告了 5 個空間,所以可以放 5 個物件,然後有一個變數用來記錄目前最新儲存物件的位置,在上圖用箭頭來表示它,所以一開始並不會有箭頭出現,因為一開始 Array 都是空的.當使用者呼叫 Stack 的 push() 時,就會寫入一個物件,此時箭頭沒有出現,所以這個物件就被放在編號 0 的位置,同時箭號也會出現在這個位置上.接著更多的物件會再進來,於是就往 Array 空的位置上放,但要照順序放,也就是編號 0 放完,就換到編號 1,同時箭頭也更新到編號 1 的位置.

如果使用者呼叫了 Stack 的 pop(),則 Stack 只要將箭頭所在位置的物件回傳出去,然後箭頭往左邊移動就行了,也無需刪除該物件,若有新物件再進來時,那位置上的舊物件就會被覆寫.

透過這樣的方式,你就可以簡單地實做了一個 Stack,透過一個容器和一個箭頭就能達成讓先進來的物件最後才被讀出.

接下來你可能會問一個問題,如果 Array 滿了怎麼處理? 你可以有兩個選擇,第一是丟出錯誤訊息說容器滿了,裝不下新東西了,第二個選擇是再建立更大的容器好應付更多的物件.第二點就和之前談過的 ArrayList 蠻相近的,當 Array 滿的時候,就要建立更大的 Array 或是更多新的 Array,然後再把新進來的物件放到新Array中.

由於宣告一個新的且更大的 Array 並且再把舊 Array 上的元素搬到新的 Array 上,這其實算是個蠻費力的工作,所以我們總不希望這樣的事情常常發生,因此,一開始的 Array 或許不會太大,但我們再建立新的 Array 時,我們可以建大一點.比如說,一開始 Array 長度像上圖一樣是 5,當這個 Array 滿了需要建立新的 Array 時,我們可以建立長度 15 的 Array,如果再滿了,則可以建立長度 45 的 Array.所以你可以看到要建立新的 Array 時,新的長度一定要比原長度還要再多 2 倍以上.因為我們也不知道使用者最後到底要多大的 Stack 來裝他的物件,因此這種循序漸進的變大方式對電腦效能的衝擊會小一點.

所以,當你有機會需要做類似 "undo" 功能的時候,記得用 Stack,比較方便也比較好懂,對後面維護的人來說也易於了解.

Share:

#5 資料結構 - Stack - part 1

還記得以前工作時曾有個一個經驗.有一天,我到同事的辦公室閒聊,聊著聊著他就跟我說他正在做一個新功能,當時我們正在做 Windows desktop應用程式,在這個程式裡面有一個編輯功能的頁面,讓使用者可以輸入產品的許多資料,而我同事正在做的就是為每個編輯動作留下記錄,好讓他可以做出 "undo" 的功能,而且要能一直 "undo" 下去.接著,他展現給我看他的成果,一切都運作的蠻好.接著,我就很好奇問他程式碼是怎麼寫的,接著他就展示相關的程式碼給我,他用了一個 .Net 的 DataTable,然後在這個 DataTable 裡建立了相關的欄位,如動作的序號,資料名稱,資料內容.因此,只要使用者一變動了某一個資料後,這個 DataTable 裡就會多了一筆資料,當使用者執行 "undo" 時,就會從這個 DataTable 裡尋找最大的序號,讀出該序號的資料並且更新 UI,然後將這筆資料從 DataTable 中刪除.如果這是你要做的功能,你會怎樣做呢?

聽完他的解釋之後,我滿臉的疑問馬上問他,你做了這麼多東西,你不覺得累嗎? 你為什麼不用 Stack 呢? 你知道什麼是 Stack 吧! (因為他是數學系畢業的,我怕他不知道什麼是 Stack) 其實,我倒也不怎麼在乎他如何去實做這功能,只是想到未來有一天我和他都會離開這份工作,總有一天這些程式碼都會交給後面的人繼續開發和維護,我常在想如何未來的工程師們看到這樣的實作方式,不知道他們容不容易懂.

其實,像這樣的功能很常遇到,用 Stack 就對了.人們常說 "凡走過必留下痕跡",而在軟體世界裡,用 Stack 來留下痕跡就相對地輕鬆.為什麼比較輕鬆呢? 原因很簡單,抽象上來說 Stack 只提供兩種方法,一個是 push (放物件進去),另一個 pop (把物件拿出來),而最後放進去的物件將會是第一個被拿出來的.以上述我那位同事的例子來說,如果他用 Stack,那麼他根本不用去管理序號,也不用在 DataTable 裡去尋找最大的序號,也不用做讀出來的資料在 DataTable 裡刪除,因為 Stack 都幫他做了這些工作.

如果你的工作是程式設計相關,我相信你一定知道什麼是 Stack,這一個基本的資料結構在各大平台與作業系統中都會提供,當然在 java 和 .net 平台也有.接下來,我們討論一下 Stack 是什麼做的? 如果你沒看過 Stack 的實做,先思考一下,如果今天你的工作是寫出一個 Stack,你打算怎麼做呢? Stack 最基本的要求就是可以寫入物件,也可以讀出物件,但是物件的寫入讀取順序一定要按照先進後出,也就是後進先出的方式來進行.因此,我們首先可以想像的是 Stack 一定像是一個容器一樣,因為它要可以容納物件,同時還要有一個管理的機制,好讓先寫入的物件在讀取出會被優先讀出去.如果你能想到這樣,就差不多完成了一半的思考.

待續...

Share:

#4 自己設計的 database schema 是不是好的呢 ?

 前面的幾篇文章都講了些較基礎也較偏向課本的內容,在這篇裡面我們來談談比較實務的題目,那就是你怎麼知道你設計的 database schema 是不是好的?

如果你的工作是軟體專案的成員,這題目一定早就會在你心裡了.市面上的軟體專案有很大的部份都需要資料庫,用來儲存企業內所需的資料,而幾乎大部份市面上的專案所需要的資料庫都是關聯式資料模型 (Relational Database),因此 database schema 的設計便是整個專案內容的設計中其中一個項目,也就是你要了解什麼是 ERM (Entity Relationship Model).也許你之前念過一些課本的內容或是上過一些課,但若沒有真正自己參與設計的話,有時你心裡一定會覺得我這樣的設計是不是好的呢?

這篇文章的內容不是要教你如何設計 database schema,其實你只要遵循著課本裡面所教你的原則來設計,設計出來的結果就不會有太意外的錯誤.比如,你知道什麼是 Entity 和 Relationship,相信你一定知道如何把 Entity 轉成資料庫中的表格以及如何用表格和欄位來實現 Relationship.我的看法是只要你正確地遵守了這些原則並且嚴格確保了正規化 (Normalization) 的存在 (一般業界的軟體專案所做的正規化至少要到 3rd normal form),設計出來的 database schema 應該都可以有八十分.以上是從資料庫的角度來看 schema 的設計,而接下來的二十分,我們就要從程式與效能的角度來思考.

在專案一開始的時候,很有可能資料庫的設計已經完成了,但是程式架構尚未完成,所以 database schema 的設計是否適當,這很難決定,畢竟存取資料的不是人,而是工程師們寫的程式,而資料存取會不會快,那就要看工程師們是怎麼寫程式了.所以你會發現,一個好的 database schema 很難在一開始就完成,除非那是個很簡單又單純的專案.

通常來說,你所設計的 database schema 能不能是個很好的設計,最大的影響是程式讀取的快慢,我們暫不考慮產品與硬體的影響,通常來說,當你的 schema 裡有很多的表格,程式在讀取資料時常常需要 join 很多的表格,這將會大大影響效能,因為 table join 雖然在關聯式資料庫中是一個很平常的事情,但也是一項成本高的運算.因此,你可以思考改進的第一個方向就是如何在不違背 ERM 和 Normalization 的原則之下將會被做 table join 的資料庫表格的數量降到最低.未來的內容,我們再來討論為何 table join 是一個成本高的運算.

第二個可以參考的方向是 Index,不論是做 table join 還是單純在一個表格上尋找資料,如果事先做好了 Index ,它將會幫助資料庫引擎能夠更快速的找到資料,因此就能更快速地完成 table join 或其他的資料存取動作.我們也會在未來的內容裡來說明 Index 如何幫上忙.

最後還有一點 De-normalization (反正規化).相信大家在課本上或實務上都會聽過這個名詞,據說它的做法能夠提升效能,但在電腦的世界裡是沒有白吃的午餐.以我個人的經驗而言,其實我不是很喜歡這東西,重點不是簡不簡單或難不難,而是它會改變了一些基本的思考而造成系統後續維護的問題. 我舉一個很簡單的例子,比如你有一個資料庫系統,裡面有一個表格,這個表格很簡單,只有兩個欄位,一個是 user id,另一個是 function id,如下所示:

User IDFunction ID
User AFunc A
User AFunc B
User BFunc A

想像這是一個很長的表格,它記錄了那些使用者可以使用那些功能.現在的情況是大部份的使用者都可以使用所有的功能,所以你可以想像使用者多功能多時,這表格有很多的筆數.你的老闆說這表格實在太長了,管理起來真麻煩,於是他想要弄一個東西,也就是如果某個使用者可以使用全部的功能的話,那麼就用 * 來代表所有的功能.

User IDFunction ID
User AFunc A
User AFunc B
User BFunc A
User C*

如上面表格所示,這代表 User C 可以使用所有的功能,這就是一種 De-normalization 的結果,如果你經驗不多,可能會一時覺得好像很方便,因為表格的資料筆數可以減少,同時要讀取 User C 的功能數量時也很變快,因為只有一筆資料.但你想想,你願意配合做這樣的改變嗎 ? 如果你是軟體工程師,你可能會不太高興,因為你會發現必須要寫一些 "特別" 的程式碼來處理 *.更慘的是,如果這些都是前人的工作,沒人告訴你什麼是 *,你可能要花點時間才能搞懂它的目的.

我在這裡要說的重點是並非所有的 De-normalization 都是好的,這樣的做法的確對資料庫引擎是有益的,因為資料讀取的成本變少了,但卻在程式邏輯上增加了更多的程式碼來處理.這樣一來一回的情況下很難評估是不是真的有好處.以整個系統的角度來看,除非你真的感受到很多的好處,不然就無需 De-normalization 了.

Share:

#3 我需要懂資料結構嗎 ?

如果你的工作是系統管理或是網路工程領域,那麼資料結構可能對你不會有太大的影響,如果你的工作是程式設計或資料庫方面的領域,那麼資料結構對你將會是很重要的主題.若你的工作是程式設計類或資料庫類,即便你沒念過書本上的內容,我相信你對資料結構也有基本的認識.資料結構可以說是整個電腦科學裡相當基礎的知識,如果你把電腦科學用國中國小數學來比喻的話,則資料結構就像小學的四則運算一樣的基礎,必須要了解它才能通往更高級的方程式.

以目前的電腦架構來看,你可以把CPU視為一個做運算的單位,比如做加法運算或除法運算等等,而記憶體和硬碟的空間就像是一條有限長度的磁帶,你可以將資料寫在這條磁帶上,而記憶體這條磁帶比較短,但它讀取寫入速度較快,硬碟這條磁帶比較長,它讀取寫入速度較慢,所以當 CPU 運算時所需要的資料都是在記憶體和硬碟這兩條磁碟裡.接下來,當 CPU在運行時,要透過什麼規則來讀取寫入以及運算資料,那就會因為不同的程式應用而不同,所以在電腦科學裡就會因為不同的應用而定義出適合的資料結構.因此,簡單的來說,資料結構就是定義資料該如何儲存,該如何讀取,以及如何運算.

不論是那一種電腦系統,運行在該電腦上的作業系統一定都會提供一些基本的資料結構,例如 Array, Stack, Queue, List等等,而每個資料結構都有個自的特色以及運用的時機和技巧.比如,Array 的特色就是它的元素在記憶體空間中需要連在一起,也就是只要找到了 Array 的開始位置後,找第一個元素和找最後一個元素所需的時間都是一樣的,因為 Array 裡面的元素都是同一種 data type,所以每個元素在記憶體所佔的大小也都相同,因此很簡單就可以算的出來.List 跟 Array 在這方面剛好就有點不同,List 裡面的每個元素也都是一樣,但它並不需要把每個元素把放在記憶體中連續的空間,List 的元素可以東放一個,西放一個,在儲存位置的選擇上比較有彈性空間,也正是因為這樣的彈性空間,所以每個元素裡面需要有一個特別的位置 (我們稱它為pointer),用來記錄下一個元素的位置在那裡,透過 pointer,我們才能從第一個元素一直走到最後一個元素,所以當你要存取 List 裡面某一個元素時,它的位置就不能像 Array 是用算出來,而必須從第一個元素開始走,一直走到你要的元素為止,所以每個元素的尋找時間是不一樣的.

接下來你可能會問,Array 和 List 看起來有點像,其實又不太一樣,我們該怎麼知道什麼情況下要用那一種呢? 這是一個很好的問題,有時很難給出很好的答案,但基本上我能給的答案是,如果你知道你所需要的元素個數,那麼你就用 Array,因為 Array 一開始必須要宣告它裡面能裝幾個元素,若情況剛好相反,你不確定你要裝多少個元素,而且存取元素的時間也不是你所在意的,那麼用 List 就提供了一些彈性.

如果你曾用過 java 或 .net 平台提供的 ArrayList,你可能曾想過這到底是 Array 還是 List 呢? 簡單地說,它是長的像 List 的 Array,本質上它還是 Array,但也提供了一些 List 的存取方式讓你來寫入或讀取裡面的元素.同時,它加上了改變 Array 長度的功能,也就是說你一直新增元素進去的話,那勢必會塞滿原有的 Array,所以若要再裝進更多的元素,則需要改變 Array 的長度.但是 Array 一旦宣告了之後就不能改變長度,所以有兩個可能的解決方法.
第一,宣告一個更長 Array,然後把原有 Array 的元素放到新的 Array 上,此時新的 Array 就有更多空間可以裝新的元素,然後把原有的 Array 從記憶體中釋放.
第二,宣告另一個一樣長度的 Array 來裝新的元素.此時就要做一些管理的動作,這樣 ArrayList 來讀取寫入資料時,才知道那一個 Array 是第一個,那一個 Array 是第二個.
可能還會有其他的方法,總之都是在做類似 Array 管理的動作,主要就是解決 Array 長度的問題.

未來文章再機會來談談這些基本的資料結構.

Share:

#2 BIG O - 有關程式執行的快慢 - Optimization

從上一次寫的文章中可以看到如何辦別一個程式執行的好壞,那些都是相當基本而簡單的例子,但在工作中時,我們需要利用這技巧嗎? 答案當然是 YES,但在一般業界中 BIG O 的評估,有時並不是那麼單純,因為我們都習慣用了其他公司寫好的 framework 來進行我們的程式撰寫,比如用 Java platform 或 .Net platform ,所以一個 API 內部會如何執行,我們看不到原始碼就不太能準確知道,所以這一部份只能靠著多使用這些 framework 所得的經驗來知道那一個 API 比較好.

比如,前一篇文章曾講到 string1.Contains(string2),要寫 Contains() 可以很簡單,你可以把 string 看成是一個 array,在這個 array 裡的元素就是字串裡的每個字母,而今天你要在這字串裡面尋找是否包含另一個子字串時,最簡單的方法就是寫 2 個 loops,外面的 loop 是用來記錄目前比對的位置,裡面的 loop 是用來比較 string1 從記錄點開始有沒有跟 string2 一樣的字元.以 Contains() 的角度來看,我們在評估 BIG O 時只看輸入參數的影響,所以我們不會去管 string1 的長短,在 string1 一樣的情況下,去看 string2 從很短到很長時對執行步驟的變化.這個是最簡單的寫法,難道你認為你用的 framework 就一定這樣寫嗎? 那可不一定. 這些產品工程師們總是有可能想到更好的寫法,所以有時候若有機會去看看這些 framework 的原始碼時,相信會對於你寫程式的功力將大有幫助.

BIG O 談的是輸入參數變化量對程式本身影響的一個趨勢,在業界中,當然會利用這個技巧來討論,除此之外,在業界中還更需要做一些 optimization. 什麼是 optimization 呢? 簡單的說,就是去掉一些沒有用的執行. 讓我們來看上一篇 FindSum4() 的例子.

bool FindSum4(int[] ary, int target) {
    for (int i = 0; i < ary.length ; i++) {
        for ( int j = 0 ; j < ary.length ; j++) {
            if ( i != j ) 
            {
                int sum = ary[i] + ary[j];
                if ( sum == target ) {
                    return true;
                }
            }
        }
    }
    return false;
}

你看看上面寫的例子還有沒有可以改進的地方呢? 可以改進的地方就是有些運算其實是重覆了.其實重覆的地方很多,比如 i = 0 , j = 1 和 j = 0 , i = 1 的運算是一樣的,因為都是抓 ary 的第一個元素和第二個元素來做加法運算. 所以你可以看到 loop 的次數其實可以不用跑那麼多次的,我們只要改一下

bool FindSum4(int[] ary, int target) {
    for (int i = 0; i < ary.length ; i++) {
        for ( int j = i + 1 ; j < ary.length ; j++) {
            if ( i != j ) 
            {
                int sum = ary[i] + ary[j];
                if ( sum == target ) {
                    return true;
                }
            }
        }
    }
    return false;
}

把第二個 loop 的 j = 0 改成 j = i + 1,這樣就大大減少了 loop 內容執行的次數了,而且 if ( i != j ) 還是多餘的.雖然這不一定是最完美的 optimization,但相信你抓住我所要講的重點,那就是去除掉一些重覆的執行動作,雖然以上的兩個程式的 BIG O 都是一樣的,但在工作時,我們還是會要求工程師要做優良的 optimization. 畢竟你輸入的 ary 不可能是無窮大,電腦記憶體是有限的,所以做優良的 optimization 的確是可以幫助你讓程式別重覆做同樣的動作.

話說回來,那像 FindSum4() 是不是還有更好的寫法呢? 答案是有的,以後在適當的內容時會再說明.

Share:

#1 BIG O - 有關程式執行的快慢

如果前面的文章所提,在十多年前時我還沒有電腦科學的基礎知識,在當時很難辦別自己寫的程式是不是好的,後來念書了之後才知道原來在課本裡有一些理論的方法來讓你做評估,而這篇文章的主題就是要來談這項評估.  評估的方法不只一種,而且還有一些數學推論,不過我將會儘量跳過數學推論的部份,而且只談論業界中最流行的一種評估方法,它叫做 O (我們將它念成 big O).

O 的數學基礎是你的程式所需執行的時間會因為輸入參數的不同而有所變化,比如你有一個程式要算1+2+3+4+5的答案,若你懂基本的程式,你就知道輸入參數是5,然後寫一個 loop 來做 5 次的加法就可以得到最後的答案. 一旦你的輸入參數是 10,那麼你寫的那個 loop 的內容就會執行十次.

int answer=0;
for (int i = 1; i <= n ; i++ ) {
     answer += i;
}

所以以上的程式就可以用一個數學的多項式來表達所需要執行的步驟. 以此例子來說是 f(n) = n ,所以 n = 5 時,程式要做 5 次加法, n=10 時,程式要做 10次加法. 如果以 n為x軸,以加法次數為y軸時,你就可以為這程式畫出一條線. O 的方法就是找一個比你的程式 f(n) 還要高一點的g(n),所謂高一點就是從 x,y軸的位置來看,所以我們稱g(n)為f(n)的上限,講白話一點就是不會超過g(n),所以g(n)可以視為程式在執行時最費時的情況,不會再比它更慘了,所以才叫做上限. 然後當輸入參數漸漸變大,就會發現g(n)和f(n)會越來越接近.

因此,O就是找出上述的 g(n).

所以,我們在評估程式時很難去用執行時間來評估,因為不同的電腦架構和程式語言都會影響,我們也不會用程式寫了幾行來評估,而是用上述的方法來評估.

在課本上,我們稱它為時間複雜度 (Time Complexity),在業界中最常用 O 來表達,所以當你使用一些業界的 SDK 時,有時你會看到某個 API 是多少的 O,比如O(n), O(n2)等等.

以上是比較偏向用數學的角度來解釋,接下來我們用更簡單的方法來說明找出一個程式的 O.

int FindSum2(int n) {
    int answer = 0;
    int n = n + 1;
    for( int i = 1; i <= n ; i++) {
        answer = answer + i;
    }
    return answer;
}

上面這一個 FindSum2() 跟上面的程式幾乎一樣,只是有一個小小的變化,在 for 之前多了一個 n = n +1; 所以你可以看到當你輸入 n = 0 時,會執行一次的加法, n=1時,會執行二次加法,以此類推,當 n 越來越大時,加法執行的次數就是 n+1. 所以這個程式就是 O(n+1),通常我們會忽略掉一些舉無輕重的執行次數,因為當你的 n 變的很大很大的時候,後面那一個 +1 似乎就變的相當不起眼,因此我們會直接說 O(n).

寫程式有趣的地方就是在這裡,因為當程式的輸入參數很小時,程式都能表現的很好,但程式寫的好不好就看它在輸入參數很大時的表現了. 相信大家在業界工作時,在許多項目都會有這樣的感覺,就像網路上只有十台電腦時,網路速度還蠻快的,但變成一百台電腦時,事情就不一樣了.

另外,我們再來看一個例子

int FindSum3(int n) {
    int answer = 0;
    for( int i = 0 ; i < 10 ; i++ ) {
        answer = answer + 2;
    }
    for( int i = 1; i <= n ; i++) {
        answer = answer + i;
    }
    return answer;
}

上面的 FindSum3() 和 FindSum2() 相差了一個 for loop. 我們可以用上述的觀念做找出 FindSum3() 的 O. 你認為是多少呢?

是的,他們兩個是一樣的! 也許你會說這兩個明明是不一樣的,執行的加法次數也不一樣,沒錯,他們執行的加法次數的確不一樣,誠如之前所說,一旦 n 變的很大時,其實也可以說是一樣的,比如執行十億次的加法和執行十億又十次的加法所需的時間,你覺得你會在乎那十次嗎? 我想你比較在乎十億次才對. 所以,到這裡你就可以知道 O 所要表達的並不是一個精確數字的情況,它所要表達的是一個趨勢.

我們再來看看另外一個例子.

bool FindSum4(int[] ary, int target) {
    for (int i = 0; i < ary.length ; i++) {
        for ( int j = 0 ; j < ary.length ; j++) {
            if ( i != j ) 
            {
                int sum = ary[i] + ary[j];
                if ( sum == target ) {
                    return true;
                }
            }
        }
    }
    return false;
}
FindSum4() 輸入參數是一個陣列 ary 和一個數字 target,要來找出陣列裡是否有兩個元素的和等於 target. 猜猜,FindSum4() 的 O 是多少?  記得,在 FindSum4() 中,那一個參數會影響它的執行時間? 沒錯,就是陣列,陣列如果很短,程式執行時間也短,陣列如果很長,執行時間也較長,你看到有兩個 for loop, 而 loop 裡面的內容要執行幾次完全是由陣列的長度所決定 (ary.length),所以你可以把陣列的長度來做當 n,而 FindSum4() 的 O 是 n2. 答對了嗎 ? 所以,如果你可以想到另一種程式寫法只要 O(n),那麼你的程式在時間複雜度上就打敗了我寫的 FindSum4(),也因為如此,我們才能說你想到的那個程式執行的比我的 FindSum4() 還要快.

以上是我們用加法執行的次數為例子來說明 O,簡單的運算用來表達執行次數是很單純的,所以千萬別以為所有的程式都可以這樣分析,因為你還要確定你所呼叫的每個 API 是不是都像加法那樣單純. 因為現在許多高階的程式語言,像java, C#等,都包裝的很好,有時你並不會看到內部的運作機制,比如 string.Contains() 不像加法那麼單純,其實 Contains() 裡面很可能就會有一個 loop,而且這個 loop 執行的次數會取決於 string 的長短.

希望透過以上這些簡單的例子能讓你了解怎麼以時間複雜度的角度來看程式執行的好壞,同時也了解基本的 O,以及推論出 O 的函數值.

Share:

#0 寫在最前面 - 網誌的內容與目的

我還記得很多年前在台北工作的時候,台灣的資訊業界和電子產業比起來算是較小的,但儘管如此,仍是會有許多機會遇到許多非電腦科系畢業的朋友在資訊業界中工作,比如,我曾遇過財經科系畢業的朋友從事網路工程的工作,或是其他理工科系的朋友從事程式撰寫的工作,甚至包括我自己也是. 我大學是念機械系,但進入社會後卻從沒有做過機械業的工作,而我所從事的全部都是資訊業中的工作.

因為有著不同的背景,後來才又跑回學校重拾課本,把許多該有的基本知識學了起來,能像我這樣做的朋友畢竟算是少數,所以這個網誌的目的就是把我過往的經驗寫下來,專門寫給非電腦科系畢業而在資訊業界中工作的朋友們. 電腦領域裡有許多的科目,我也不是全部都懂,所以往後的內容只著重在資訊業界中比較常會遇到情況,而這些情況的確是需要有念過課本裡所提供的知識才能清楚明白的. 這是什麼意思呢 ? 來舉一個例子,相信許多人都用過資料庫的產品,不論是那一種資料庫產品,它們一定都會提供一個功能,叫Index search,也就是說當你所設計的 table 針對某些資料欄位建立起 Index 之後,這會幫助你所下的 search query 可以更快的找到資料. 我相信若你有過一些資料庫的經驗的話,你一定知道這件事情,但是對於非電腦科系畢業的朋友們來說,我們可能就不知道為什麼可以讓資料尋找變快了,因為這是一般的產品文件裡不會提到的概念. 而在這個網誌的內容裡就會以簡單的描述來說明資料庫是如何達成的.

所以,當你看到這裡之後,你就比較能夠明白這網誌的目的了. 接下來,可能有人會問為什麼要寫這些內容呢? 就如同一開始說過的,在我過往的經驗發現在資訊業工作的非主修電腦系的朋友還不算少數,包括我自己也是其中一個,由於我自己的個性是屬於好奇寶寶型,所以喜歡知道許多背後的原因,這也是我後來決定再回去學校重拾課本的原因,也是因為這樣的際遇,所以才打算把這些背後的原因能記錄下來,希望這些能對其他有興趣的朋友提供幫助與參考.

我預計寫的內容將會是一般在資訊業界中常遇到的情況,大致上會包含的範圍有作業系統,程式寫作,資料庫,與分散式系統等相關的內容. 我相信這些內容也符合大多數非電腦科系在資訊業工作中朋友們的領域.

Share: