NVelocity實現違反了LSP法則,使我的一個低級錯誤排查了一個下午。
最近我在做一個CMS系統,需要一個模板引擎,選擇了NVelocity,NVelocity是JAVA的開源模板引擎Velocity移植到了.NET平臺,這個不過多介紹。因為Velocity的模板語法很簡單我就選用了它作為我們CMS的模板引擎。NVelocity好像是Castle Project維護的,我在Castle Project的網站找到了入門文章,看上去是比較簡單的,很容易上手。然后我就照著他的例子編碼:
var props = new ExtendedProperties();
props.Add(RuntimeConstants.INPUT_ENCODING, "utf-8");
props.Add(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
props.Add(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, targetViewFolder);
velocityEngine.Init(props);
props.Add那三句在例子中是沒有的,是我自作聰明加上去的,因為如果不傳入配置的話會按照NVelocity的默認配置,但是這么寫是錯的,為什么是錯的稍后告訴大家。
這段代碼編譯過去了,然后運行到這里也沒有出問題,但是我在velocityEngine.GetTemplate的時候卻出了問題,報異常說找不到資源,經過斷點調試發現了詭異的地方
為什么我的配置沒有生效,反而還是默認的設置?然后我又在網上找了一些例子,由于“老眼昏花”,并沒有看出到底錯在哪里,最后沒辦法我覺得需要追蹤一下NVelocity的源代碼,我在Castle Project的網站上下載整套源碼,其中有NVelocity的代碼,但是項目缺少directive.properties和nvelocity.properties連個文件,我先項目中去掉了這個文件,發現雖然可以順利編譯,但是在使用NVelocity的時候連默認配置都沒有了,我只好在已經編譯好的NVelocity.dll中取得了這個兩個文件(以前還不知道怎么取DLL中的資源文件,又研究了N久),最后編譯成功,單步調適,跟著Init(props)方法進去看個究竟,果然發現了奇怪的地方:
p.Keys怎么可能一個元素都沒有?其實在監視props變量里面是有東東的,但是Keys里什么都沒有,然后我通過分析ExtendedProperties發現了原因:
1)ExtendedProperties是繼承Hashtable的
2)ExtendedProperties自己維護了Keys
{
get { return keysAsListed; }
}
所以,Add方法是Hashtable本身實現的,在使用Add方法增加元素的時候,ExtendedProperties.Keys并沒有增加,應該使用擴展出來的AddProperty方法,執行AddProperty才會順便去維護keysAsListed,我修改初始化的代碼后發現一切正常了。后來我回頭去看網上的例子,都是使用AddProperty的,汗死!!!最后貼出正確的初始化代碼
var props = new ExtendedProperties();
props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, targetViewFolder);
velocityEngine.Init(props);
不過這回老眼昏花也讓我理解了LSP法則,面向對象實踐中有一些法則,我往往是只知其然,不知其所以然,最后說說什么是LSP法則。:
LSP: The Liskov substitution principle
子類必須能夠替換基類。Subtypes must be substitutable for their base types.
ExtendedProperties繼承Hashtable,但是并不能夠代替基類,反而會導致行為不正常,讓我陷入歧途,一個低級的錯誤,一個下午的時間,不過總在下班前解決了。

浙公網安備 33010602011771號