WebObjects/Web 應用程式/開發/通用最佳實踐
困擾新 WebObjects 開發人員的一個更嚴重的問題源於在 appendToResponse 中建立和傳送一個 WOComponent,然後在隨後的 takeValuesFromRequest 和 invokeAction 方法在該頁面上完成之前更改該元件的結構。
這樣做會混淆 WO 在 takeValuesFromRequest 或 invokeAction 中引用該頁面時的解釋。結果會讓你感覺你的 WOComponent 患上了精神分裂症。如果它在 takeValuesFromRequest 期間變得混亂,它將從表單上的一個或多個欄位中獲取值,並將它們放入相應類檔案中的不相關例項變數中。如果它在 invokeAction 期間變得混亂,它將啟用與你點選的 WOSubmitButton 或 WOHyperlink 繫結的動作方法無關的動作方法。
簡而言之,如果你的頁面開始表現出精神分裂症的行為,這是我第一個要檢查的地方。那麼,到底是什麼問題呢?
從你執行 appendToResponse() 的那一刻起,你必須確保用來建立作為響應傳送出去的 HTML 結構的所有物件,都不會以任何可能導致該 HTML 結構(頁面模板)在隨後的 takeValuesFromRequest() 和 invokeAction() 方法完成之前發生變化的方式發生變化。特別是,如果 WOConditionals 依賴的任何布林值發生變化,如果 WORepetitions 中使用的任何陣列大小發生變化,那麼你就建立了一個問題,其表現形式通常很難追蹤。
當你執行 appendToResponse 時,WO 使用你的 WOComponents、子元件和 WOElements 來建立一個物件的層次結構(一個物件圖),然後它 "遍歷" 該層次結構以生成 HTML。當 takeValuesFromRequest 和 invokeAction 方法執行時,WO 會重新建立此模板並重新 "遍歷" 它,以確定哪些物件接收返回的值以及哪個物件負責呼叫動作。如果你的物件圖的任何更改會導致該模板結構在 appendToResponse 與相應的 takeValuesFromRequest 和 invokeAction 之間發生變化,那麼 WO 會迷路,可能會在你的表單物件中放置錯誤的值,並確定是錯誤的元素(例如,WORadioButton)導致了動作。
這是一個常見且嚴重的錯誤。
如果你有 WOConditionals,最安全的做法是將它們繫結到類檔案中的布林值,你只在 appendToResponse 中更改這些布林值,在它呼叫 super.appendToResponse 之前。如果這很困難,請在你的程式中使用任何自然的邏輯,但在 super.appendToResponse 之前,放置一個布林值(你將 WOConditional 繫結到它),以反映該邏輯,並且只在該方法中的那個點相應地更改布林值。
如果你有 WORepetitions,請確認你的程式碼不會在啟用 super.appendToResponse 和完成該頁面的相應 invokeAction 之間更改這些陣列的大小或它們大小依賴的索引。
有關此過程及其後果的更深入解釋,請參閱[1]。特別注意最後一段以及下一頁[2]。在這最後一頁,請特別注意倒數第二段。
不要使用
MyNewPage nextPage = (MyNewPage)pageWithName("MyNewPage");
更喜歡這種形式
MyNewPage nextPage = (MyNewPage)pageWithName(MyNewPage.class.getName());
class.getName() 允許 Eclipse 進行正確的重構,你可以右鍵單擊=>引用=>工作空間你的類,並真正找到所有引用,而不是僅僅擁有字串引用。它具有的另一個優點是,如果你有兩個同名但位於不同包中的頁面,這可以避免混淆。如果你只使用 pageWithName("MyNewPage";),WO 可能返回錯誤的一個。雖然是微小的變化,但確實有很好的好處。
如果你使用 1.5,你可以使用 1.5 的變體
@SuppressWarnings("unchecked")
public <T extends WOComponent> T pageWithName(Class<T> componentClass) {
return (T) super.pageWithName(componentClass.getName());
}
這將移除一個強制轉換
MyNewPage nextPage = pageWithName(MyNewPage.class);
KeyValueCoding(也稱為 KVC)傾向於鼓勵使用類似於這樣的結構
website.addObjectToBothSidesOfRelationshipWithKey(newFolder, “folders”);
這會使程式碼中充斥著硬編碼的字串。更改屬性名稱會破壞程式碼,不會發出編譯警告。如果你使用 EOGenerator 為名稱生成常量
public static final String FOLDERS = “folders”;
你可以在硬編碼的字串中使用它們,並在更改影響程式碼時獲得錯誤
website.addObjectToBothSidesOfRelationshipWithKey(newFolder, FOLDERS);
執行此操作的 EOGenerator 模板(片段)
public static final String ENTITY_NAME = "<$name$>"; <$foreach propertyName classPropertyNames.@reversedArray do$> public static final String <$propertyName.uppercaseString$> = "<$propertyName$>";<$endforeach do$>
- 這沒有解決在 wod 檔案中繫結中使用屬性名稱時的相關問題
- 這在(不可否認的罕見)情況下不起作用,即一個類實現多個實體。EOGenerator 假設一個實體 == 一個類。因此,MyEO.ENTITY_NAME 將返回最後一個生成的實體的名稱。
有關更多類似技巧,請參閱EOGenerator 頁面。