ICE的slice檔案定義注意事項
一、原始檔規則
1、副檔名必須為.ice
2、在使用#include來包含其他的ice定義檔案時,只能使用<>,不能使用""。在使用路徑包含時,使用linux風格的斜線,不能使用windows風格的反斜線
3、每個slice定義檔案中最好加上#ifndef的巨集定義,防止檔案的雙重包含
4、檔案必須是utf-8編碼的
二、詞法規則
1、slice檔案支援c++的單行和多行註釋
2、slice定義中的關鍵字均為小寫
3、slice檔案中關鍵字不能以下劃線開始和結尾,當然這一規則也是可以打破的,在編譯slice檔案的時候使用“--underscore”的編譯選項
4、slice的關鍵字雖然是大小寫敏感的,但是為了保證ice能夠對映到非大小寫敏感的系統,因此最好不要採用不同的大小寫拼寫規則來區分兩個關鍵字,即你可以認為是非大小寫敏感的。
5、雖然說部分語言關鍵字不是slice的關鍵字,但是最好不要使用,因為slice的編譯器會對這些語言相關的關鍵字進行特殊處理,從而帶來程式碼可讀性的降低
6、如果以前定義的slice檔案中標示符與新的ice版本規則衝突,可以使用反斜線"\"來表示關鍵字為一個普通的標示符
7、slice定義檔案中禁止標示符以“ice”開頭。當然這一規則也是可以打破的,在編譯slice檔案的時候使用“--ice”的編譯選項
8、slice定義檔案中禁止標示符以"Helper"、“Holder”、“Prx”、“Ptr”結尾。
三、名字空間
1、在全域性的名字空間中只允許出現名字空間的定義,即slice檔案定義的最頂層必須是名字空間定義Moudle XXX
2、可以再不同的檔案中使用相同的名字空間,就像多個c++檔案中定義名字空間的不同型別一樣
四、資料型別
1、slice提供的基本資料型別包括:bool、byte、short、int、long、float、double、string。擴充套件資料型別包括:enum、struct、sequence、dictionary。
2、特別注意slice不提供所謂的無符號型別,因為在某些程式設計語言中,就不提供native的unsigned型別,因此slice無法做無符號型別的語言對映
3、slice的string字串必須使用unicode字符集,同時不能包含0的。如果需要使用包含其他字符集或者0的串,可以考慮使用byte結構來儲存
4、布林值bool的取值只能是flase或者true
5、byte型別在slice的語言對映中會始終保證是8位元組的,同時在網路傳輸過程中也不會受網路和本地位元組序的影響
6、slice的enum型別是不允許使用者來制定列舉成員的取值的,但是slice能夠確保列舉型別中後面的成員取值大於前面的成員取值,因此列舉成員是可以做大小比較的。slice不允許定義空的列舉型別,即列舉型別中必須有成員定義
7、slice中struct不支援型別的巢狀定義,即不允許在一個struct資料型別中再次定義一個struct的資料型別
8、結構中的基本資料型別和列舉型別支援在定義的時候指定預設值
9、需要使用變長的資料集合時,可以使用sequence來定義。sequence的一種特殊用法是用來標示可選值,因為sequence資料成員可以是空的資料集合。為了表示一個空的資料集合,我們一般這樣來定義:sequence<XXX> TypeOpt; TypeOpt Parameter; Opt的字尾一般迎來標示該序列集合是允許為空的可選集合或者引數
10、需要使用類似map的型別對映結構時,可以使用dictionary來定義。但是dictionary的key欄位是有約束的,只能是如下型別:byte、short、int、long、bool、string、enum、資料成員為整形或者字串的結構。
11、slice常量定義允許的型別:整形、浮點、字串、列舉。注意整型常量的取值不能帶長度標示(l、L、u、U);浮點和字串常量的語法定義基本同c++;常量取值時需要設定允許範圍內的值,否則slice編譯時會提示錯誤;常量定義取值時是可以引用其他常量的,只要確保其取值範圍是合法的。
五、介面定義
1、介面操作必須包含如下資訊:返回值、介面名稱、輸入引數型別和名稱(如果存在)、輸出引數型別和名稱(如果存在)。
2、介面操作在引數排版上要求輸出引數必須在輸入引數的後面,並且不支援輸入輸出引數,即引數的資料傳遞方向是單一的。不支援預設值引數
3、同一個介面內部不允許操作重名的。即不支援介面操作的過載
4、如果某一個操作不會改變其介面物件的狀態,請將其表示為nonmutating。即類似c++的常量函式(函式名後加const)。這樣標示的好處是ice的執行環境能夠在函式呼叫過程發生底層的一些錯誤情況下更積極的重新嘗試,保證系統有更好的容錯效能。
5、如果一個操作在一個介面物件上連續執行兩次與一次的效果是一樣的,那麼為了能夠讓系統有更好的容錯效能,請將介面表示為idempotent。從這個角度去理解,那麼nonmutating操作也是idempotent的。
6、介面可以傳遞代理型別,即類似如c++的指標型別。這樣做的一個好處是客戶端能夠傳遞一個帶操作的資料結構給伺服器端,這樣客戶端和伺服器端能夠傳遞除了資料之外的操作實現。需要做的事情僅僅是在slice中定義一個介面的指標,注意是“介面”。
7、介面是可以繼承的,當然包含多重繼承。但是需要注意的一點是,多重繼承的多個基類中不能包含相同名稱的操作。
8、始終的有一個觀念就是,所有介面都共有同一個基類Object,但是你不能顯示的從Object繼承,這是slice隱私為大家實現的。注意Object的O大寫了。這是關鍵字中的一個特例
六、異常處理
1、異常的定義有點類似結構,可以在其定義任何資料型別。但是和結構不同的是異常可以不包含任何資料成員
2、異常定義時也支援和常量一樣的預設值定義語法規則。即基本資料型別支援在定義的時候制定預設值
3、可以設定某一個介面操作會丟擲特定型別的異常,當然在該介面操作實現過程中也只能丟擲申明的異常,否則ice的會報執行時錯誤
4、為了能夠更好的保證系統的向下相容性,最好在系統初始定義時就設定好操作的異常(即使初始實現時是沒有異常丟擲的)。
5、異常是支援繼承的。即可以向下擴充套件異常的資訊。但是不支援多重繼承。可以再申明丟擲基類異常的操作中丟擲子類異常
6、伺服器拋送給客戶端的異常有如下幾種情況:使用者異常、ObjectNotExistException、FacetNotExistException、OperationNotExistException、UnknownUserException(操作的實現丟擲了一個未宣告的異常)、UnknownLocalException(系統未捕獲操作申明的異常)、UnknownException(語言系統的異常)
七、類
1、類在資料成員定義上與結構相同、在操作定義上與介面類似。他是一個兩中型別的混合物。類相比結構支援繼承擴充套件、支援多型、支援自引用,相比介面有具備資料屬性
2、為了能夠具備更好的效能,如果struct就能夠完成的事情,不要大費周章的來弄個class來搞
3、一定要區分類的自引用和介面的自引用的差異化。類的自引用時確實的值存在,但是介面的自引用時指標存在,即不是值域空間。因此在一些操作中,需要從時間和空間的角度來考慮是採用值引用還是指標引用。
4、在介面或者類的操作中如果引數是一個類,那麼一定要注意,在客戶端和伺服器端的互動中僅僅傳遞了傳送方的類成員,其操作的行為並沒有進行傳遞,因此不能確保其操作的行為在客戶端和伺服器端的解釋是一樣的。為了能夠在客戶端和伺服器端傳遞操作,最保險的做法是使用介面來代替類進行操作傳遞。當然如果你能保證客戶端和伺服器端的操作行為完全一致,用類來做不失為一種好的做法,因為在操作的執行上由於是在本地地址空間,而不會產生類似介面代理的RPC呼叫產生更重的呼叫開銷。
5、類可是實現一個或多個介面,在這種場景下,一個類例項的介面呼叫,一定要區分該操作時從介面繼承下來的,還是類擴充套件的。這樣才知道其呼叫實現時遠端的還是本地的。
6、類和介面一樣,不能過載操作。在繼承基類或者實現介面時,不能擴充套件和基類、實現介面相同的成員變數或者操作名稱
7、一定要注意,如果使用類來代替介面傳遞代理(即指標)給接收方,那麼僅僅是傳遞了一個代理,你只能理解是一個介面,而無法通過代理訪問類的資料成員。
8、在相互引用的類和介面定義中,前置宣告就成為了一種不得不用的手段。
八、其他
1、每個擴充套件的類和介面都有一個型別ID,一般而言,型別ID 起頭是全域性作用域(::),然後在後面附加包含該型別的各巢狀模組的名字,最後再以該型別自身的名字結束
2、Object類提供了一些一些基本的操作:ice_ping、ice_isA、ice_id、ice_ids
九、編譯
1、slice2cpp [-h] [-v] [-DName] [-DName=Value] [-UName] [-IDir] [-E] [--output-dir Dir] [-d] [--ice] [--underscore] file
2、slice2html
原文連結:http://blog.csdn.net/followshake/article/details/7366286