扒开腿挺进岳湿润的花苞视频|将军边走边挺进她H树林|挺进朋友人妻张婉莹身体|岳脱得精光让我挺进去视频|第一次挺进莹莹的身体里视频|脱岳裙子从后面挺进去视频

新疆軟件開發(fā)

本站首頁 軟件開發(fā) 成功案例 公司新聞 公司簡介 客服中心 軟件技術(shù) 網(wǎng)站建設(shè)
  您現(xiàn)在的位置: 新疆二域軟件開發(fā)公司 >> Java技術(shù) >> 文章正文

JAVA開發(fā)的6個實踐的例子

            首先,本文的目標(biāo)讀者是正在從事技術(shù)工作的架構(gòu)師。為了避免浪費大家的才智,我會避免講述一些陳腐的最佳實踐,例如"日常構(gòu)建(build daily)"、"測試一切(test everything)"和"經(jīng)常集成( integrate often)。 任何具有稱職架構(gòu)師的項目都有分工明確的、定義良好的團(tuán)隊結(jié)構(gòu)。他們還為進(jìn)行編碼檢查、構(gòu)建代碼(每日或在需要時)、進(jìn)行測試(單元、集成和系統(tǒng)的)、部署和配置/釋放管理而具備已記錄的過程。 
      其次,我將跳過通常吹捧的最佳實踐,例如"基于接口的設(shè)計"、"使用著名的設(shè)計模型"以及"使用面向服務(wù)的架構(gòu)"等。相反,我將集中講述我曾學(xué)過并且使用了若干年的6(不是很多)個方面的in-the-trench課程。最后,本文的目的是讓您思考一下自己的架構(gòu),提供工作代碼示例或者解決方案超出了本文的范圍。下面就讓我介紹一下這6課:
第1課:切勿繞過服務(wù)器端驗證
作為一位軟件顧問,我曾有機會不但設(shè)計并實現(xiàn)了Web應(yīng)用程序,而且還評估/審核了許多Web應(yīng)用程序。在復(fù)雜的、并且用JavaScript客戶端封裝的應(yīng)用程序內(nèi),我經(jīng)常遇到對用戶輸入信息執(zhí)行大量檢查的Web頁面。即使HTML元素具有數(shù)據(jù)有效性的屬性也如此,例如MAXLENGTH。只有在成功驗證所有輸入信息后,才能提交HTML表單。結(jié)果,一旦服務(wù)器端收到通知表單(請求),便恰當(dāng)?shù)貓?zhí)行業(yè)務(wù)邏輯。
在此,您發(fā)現(xiàn)問題了么?開發(fā)人員已經(jīng)做了許多重要的假設(shè)。例如,他們假設(shè)所有的Web應(yīng)用程序用戶都同樣誠實。開發(fā)人員還假設(shè)所有用戶將總是使用他們測試過的瀏覽器訪問Web應(yīng)用程序。還有很多其他的假設(shè)。這些開發(fā)人員忘記了利用可以免費得到的工具,通過命令行很容易地模擬類似瀏覽器的行為。事實上,通過在瀏覽器窗口中鍵入適當(dāng)?shù)腢RL,您可以發(fā)送任何"posted"表單,盡管如此,通過禁用這些頁面的GET請求,您很容易地阻止這樣的"表單發(fā)送"。但是,您不能阻止人們模擬甚至創(chuàng)建他們自己的瀏覽器來入侵您的系統(tǒng)。
根本的問題在于開發(fā)人員不能確定客戶端驗證與服務(wù)器端驗證的主要差別。兩者的主要差別不在于驗證究竟發(fā)生在哪里,例如在客戶端或者在服務(wù)器端。主要的差別在于驗證背后的目的不同。
客戶端驗證僅僅是方便。執(zhí)行它可為用戶提供快速反饋??使應(yīng)用程序似乎做出響應(yīng),給人一種運行桌面應(yīng)用程序的錯覺。
另一方面,服務(wù)器端驗證是構(gòu)建安全Web應(yīng)用程序必需的。不管在客戶端一側(cè)輸入的是什么,它可以確?蛻舳怂屯⻊(wù)器的所有數(shù)據(jù)都是有效的。
因而,只有服務(wù)器端驗證才可以提供真正應(yīng)用程序級的安全。許多開發(fā)人員陷入了錯誤感覺的圈套:只有在客戶端進(jìn)行所有數(shù)據(jù)的驗證才能確保安全。下面是說明此觀點的一個常見的示例:
一個典型的登錄頁面擁有一個用來輸入用戶名的文本框和一個輸入密碼的文本框。在服務(wù)器端,某人在接收servlet中可能遇到一些代碼,這些代碼構(gòu)成了下面形式的SQL查詢:
"SELECT * FROM SecurityTable WHERE username = '" + form.getParameter("username") + "' AND password = '" + form.getParameter("password") + "';",并執(zhí)行這些代碼。如果查詢在結(jié)果集的某一行返回,則用戶登錄成功,否則用戶登錄失敗。
第一個問題是構(gòu)造SQL的方式,但現(xiàn)在讓我們暫時忽略它。如果用戶在用戶名中輸入"Alice'--"會怎樣呢?假設(shè)名為"Alice"的用戶已經(jīng)在SecurityTable中,這時此用戶(更恰當(dāng)?shù)恼f法是黑客)成功地登錄。我將把找出為什么會出現(xiàn)這種情況的原因做為留給您的一道習(xí)題。
許多創(chuàng)造性的客戶端驗證可以阻止一般的用戶從瀏覽器中這樣登錄。但對于已經(jīng)禁用了JavaScript的客戶端,或者那些能夠使用其他類似瀏覽器程序直接發(fā)送命令(HTTP POST和GET命令)的高級用戶(或者說黑客)來說,我們又有什么辦法呢?服務(wù)器端驗證是防止這種漏洞類型所必須的。這時,SSL、防火墻等都派不上用場了。

第2課:安全并非是附加物
如第1課所述,我曾有幸研究過許多Web應(yīng)用程序。我發(fā)現(xiàn)所有的JavaServer Page(JSP)都有一個共同的主題,那就是具有類似下面?zhèn)未a的布局:
HTML, JavaScript, and JSP
code to display data and
allow user interaction -->
如果項目使用諸如Struts這樣的MVC框架,所有的Action Bean都會具有類似的代碼。盡管最后這些代碼可能運行得很好,但如果您發(fā)現(xiàn)一個bug,或者您必須添加一個新的角色(例如,"guest"或者"admin"),這就會代表一場維護(hù)惡夢。
此外,所有的開發(fā)人員,不管您多年輕,都需要熟悉這種編碼模式。當(dāng)然,您可以用一些JSP標(biāo)簽來整理JSP代碼,可以創(chuàng)建一個清除派生Action Bean的基本Action Bean。盡管如此,由于與安全相關(guān)的代碼會分布到多個地方,所以維護(hù)時的惡夢仍舊存在。由于Web應(yīng)用程序的安全是強迫建立在應(yīng)用程序代碼的級別上(由多個開發(fā)人員),而不是建立在架構(gòu)級別上,所以Web應(yīng)用程序還是很可能存在弱點。
很可能,根本的問題是在項目接近完成時才處理安全性問題。最近作為一名架構(gòu)師,我曾在一年多的時間里親歷了某一要實現(xiàn)項目的6個版本,而直到第四版時我們才提到了安全性??即使該項目會將高度敏感的個人數(shù)據(jù)暴露于Web上,我們也沒有注意到安全性。為了更改發(fā)布計劃,我們卷入了與項目資助人及其管理人員的爭斗中,以便在第一版中包含所有與安全相關(guān)的功能,并將一些"業(yè)務(wù)"功能放在后續(xù)的版本中。最終,我們贏得了勝利。而且由于應(yīng)用程序的安全性相當(dāng)高,能夠保護(hù)客戶的私有數(shù)據(jù),這一點我們引以為榮,我們的客戶也非常高興。
遺憾的是,在大多數(shù)應(yīng)用程序中,安全性看起來并未增加任何實際的商業(yè)價值,所以直到最后才解決。發(fā)生這種情況時,人們才匆忙開發(fā)與安全相關(guān)的代碼,而絲毫沒有考慮解決方案的長期可維護(hù)性或者健壯性。忽視該安全性的另一個征兆是缺乏全面的服務(wù)器端驗證,如我在第1課中所述,這一點是安全Web應(yīng)用程序的一個重要組成部分。
記。篔2EE Web應(yīng)用程序的安全性并非僅僅是在Web.xml 和ejb-jar.xml文件中使用合適的聲明,也不是使用J2EE技術(shù),如Java 認(rèn)證和授權(quán)服務(wù)(Java Authentication and Authorization Service,JAAS)。而是經(jīng)過深思熟慮后的設(shè)計,且實現(xiàn)一個支持它的架構(gòu)。
第3課:國際化(I18N)不再是紙上談兵
當(dāng)今世界的事實是許多英語非母語的人們將訪問您的公共Web應(yīng)用程序。隨著電子政務(wù)的實行,由于它允許人們(某個國家的居民)在線與政府機構(gòu)交互,所以這一點特別真實。這樣的例子包括換發(fā)駕照或者車輛登記證。許多第一語言不是英語的人們很可能將訪問這樣的應(yīng)用程序。國際化(即:"i18n",因為在"internationalization"這個單詞中,字母i和字母n之間一共有18個字母)使得您的應(yīng)用程序能夠支持多種語言。
顯然,如果您的JSP 頁面中有硬編碼的文本,或者您的Java代碼返回硬編碼的錯誤消息,那么您要花費很多時間開發(fā)此Web應(yīng)用程序的西班牙語版本。然而,在Web應(yīng)用程序中,為了支持多種語言,文本不是惟一必須"具體化"的部分。因為許多圖像中嵌有文字,所以圖形和圖像也應(yīng)該是可配置的。在極端的情況下,圖像(或者顏色)在不同的文化背景中可能有完全不同的意思。類似地,任何格式化數(shù)字和日期的Java代碼也必須本地化。但問題是:您的頁面布局可能也需要更改。
例如,如果您使用HTML表格來格式化和顯示菜單選項、應(yīng)用程序題頭或注腳,則您可能必須為每一種支持的語言更改每一欄的最小寬度和表格其他可能的方面。為了適應(yīng)不同的字體和顏色,您可能必須為每一種語言使用單獨的樣式表。
顯然,現(xiàn)在創(chuàng)建一個國際化的Web應(yīng)用程序面臨的是架構(gòu)挑戰(zhàn)而不是應(yīng)用程序方面的挑戰(zhàn)。一個架構(gòu)良好的Web應(yīng)用程序意味著您的JSP頁面和所有與業(yè)務(wù)相關(guān)的(應(yīng)用程序特有的)Java代碼都不知不覺地選擇了本地化。要記住的教訓(xùn)是:不要因為Java、J2EE支持國際化而不考慮國際化。您必須從第一天起就記住設(shè)計具有國際化的解決方案。
第4課:在MVC表示中避免共同的錯誤
J2EE開發(fā)已經(jīng)足夠成熟,在表示層,大多數(shù)項目使用MVC架構(gòu)的某些形式,例如Struts。在這樣的項目中,我常見到的現(xiàn)象是對MVC模式的誤用。下面是幾個示例。
常見的誤用是在模型層(例如,在Struts的Action Bean中)實現(xiàn)了所有的業(yè)務(wù)邏輯。不要忘了,表示層的模型層仍然是表示層的一部分。使用該模型層的正確方法是調(diào)用適當(dāng)?shù)臉I(yè)務(wù)層服務(wù)(或?qū)ο螅┎⒔Y(jié)果發(fā)送到視圖層(view layer)。用設(shè)計模式術(shù)語來說,MVC表示層的模型應(yīng)該作為業(yè)務(wù)層的外觀(Fa?ade)來實現(xiàn)。更好的方法是,使用核心J2EE模式(Core J2EE Patterns)中論述到的Business Delegate模式。這段自書中摘錄的內(nèi)容精彩地概述了將您的模型作為Business Delegate來實現(xiàn)的要點和優(yōu)點:
Business Delegate起到客戶端業(yè)務(wù)抽象化的作用。它抽象化,進(jìn)而隱藏業(yè)務(wù)服務(wù)的實現(xiàn)。使用Business Delegate,可以降低表示層客戶端和系統(tǒng)的業(yè)務(wù)服務(wù).之間的耦合程度。根據(jù)實現(xiàn)策略不同,Business Delegate可以在業(yè)務(wù)服務(wù)API的實現(xiàn)中,保護(hù)客戶端不受可能的變動性影響。這樣,在業(yè)務(wù)服務(wù)API或其底層實現(xiàn)變化時,可以潛在地減少必須修改表示層客戶端代碼的次數(shù)。
另一個常見的錯誤是在模型層中放置許多表示類型的邏輯。例如,如果JSP頁面需要以指定方式格式化的日期或者以指定方式排序的數(shù)據(jù),某些人可能將該邏輯放置在模型層,對該邏輯來說,這是錯誤的地方。實際上,它應(yīng)該在JSP頁面使用的一組helper類中。當(dāng)業(yè)務(wù)層返回數(shù)據(jù)時,Action Bean應(yīng)該將數(shù)據(jù)轉(zhuǎn)發(fā)給視圖層。這樣,無需創(chuàng)建模型和視圖之間多余的耦合,就能夠靈活支持多個視圖層(JSP、Velocity、XML等)。也使視圖能夠確定向用戶顯示數(shù)據(jù)的最佳方式。
最后,我見過的大多數(shù)MVC應(yīng)用程序都有未充分應(yīng)用的控制器。例如,絕大多數(shù)的Struts應(yīng)用程序?qū)?chuàng)建一個基本的Action類,并完成所有與安全相關(guān)的功能。其他所有的Action Bean都是此基類的派生類。這種功能應(yīng)該是控制器的一部分,因為如果沒有滿足安全條件,則首先調(diào)用不應(yīng)該到達(dá)Action Bean(即:模型)。記住,一個設(shè)計良好的MVC架構(gòu)的最強大功能之一是存在一個健壯的、可擴(kuò)展的控制器。您應(yīng)該利用該能力以加強自己的優(yōu)勢。
第5課:不要被JOPO束縛住手腳
我曾目睹許多項目為了使用Enterprise JavaBean而使用Enterprise JavaBean。因為EJB似乎給項目帶來優(yōu)越感和妄自尊大的表現(xiàn),所以有時它是顯酷的要素(coolness factor)。而其他時候,它會使J2EE和EJB引起混淆。記住,J2EE和EJB不是同意詞。EJB只是J2EE 的一部分,J2EE 是包含JSP、servlet、Java 消息服務(wù)(JMS)、Java數(shù)據(jù)庫連接(JDBC)、JAAS、 Java管理擴(kuò)展(JMX)和EJB在內(nèi)的一系列技術(shù),同樣也是有關(guān)如何共同使用這些技術(shù)建立解決方案的一組指導(dǎo)原則和模式。
如果在不需要使用EJB的情況下使用EJB,它們可能會影響程序的性能。與老的Web服務(wù)器相比,EJB一般對應(yīng)用服務(wù)器有更多的需求。EJB提供的所有增值服務(wù)一般需要消耗更大的內(nèi)存和更多的CPU時間。許多應(yīng)用程序不需要這些服務(wù),因此應(yīng)用服務(wù)器要與應(yīng)用程序爭奪資源。
在某些情況下,不必要地使用EJB可能使應(yīng)用程序崩潰。例如,最近我遇到了一個在開源應(yīng)用服務(wù)器上開發(fā)的應(yīng)用程序。業(yè)務(wù)邏輯封裝在一系列有狀態(tài)會話bean(EJB)中。開發(fā)人員為了在應(yīng)用服務(wù)器中完全禁用這些bean的"鈍化"費了很大的勁?蛻舳艘髴(yīng)用程序部署在某一商用應(yīng)用服務(wù)器上,而該服務(wù)器是客戶端技術(shù)棧的一部分。該應(yīng)用服務(wù)器卻不允許關(guān)閉"鈍化"功能。事實上,客戶端不想改變與其合作的應(yīng)用服務(wù)器的設(shè)任何置。結(jié)果,開發(fā)商碰到了很大的麻煩。(似乎)有趣的事情是開發(fā)商自己都不能給出為什么將代碼用EJB(而且還是有狀態(tài)會話bean)實現(xiàn)的好理由。不僅僅是開發(fā)商會遇到性能問題,他們的程序在客戶那里也無法工作。
在Web應(yīng)用程序中,無格式普通Java 對象(POJO)是EJB強有力的競爭者。POJO是輕量級的,不像EJB那樣負(fù)擔(dān)額外的負(fù)擔(dān)。在我看來,對許多EJB的優(yōu)點,例如對象入池,估計過高。POJO是您的朋友,不要被它束縛住手腳。


第6課:數(shù)據(jù)訪問并不能托管O/R映射
我曾參與過的所有Web應(yīng)用程序都向用戶提供從其他地方存取的數(shù)據(jù),并且因此需要一個數(shù)據(jù)訪問層。這并不是說所有的項目都需要標(biāo)識并建立這樣一個層,這僅僅說明這樣層的存在不是隱含的就是明確的。如果是隱含的數(shù)據(jù)層,數(shù)據(jù)層是業(yè)務(wù)對象(即:業(yè)務(wù)服務(wù))層的一部分。這適用于小型應(yīng)用程序,但通常與大一些項目所接受的架構(gòu)指導(dǎo)原則相抵觸。
總之,數(shù)據(jù)訪問層必須滿足或超出以下四個標(biāo)準(zhǔn):
具有透明性
業(yè)務(wù)對象在不知道數(shù)據(jù)源實現(xiàn)的具體細(xì)節(jié)情況下,可以使用數(shù)據(jù)源。由于實現(xiàn)細(xì)節(jié)隱藏在數(shù)據(jù)訪問層的內(nèi)部,所以訪問是透明的。
易于遷移
數(shù)據(jù)訪問層使應(yīng)用程序很容易遷移到其他數(shù)據(jù)庫實現(xiàn)。業(yè)務(wù)對象不了解底層的數(shù)據(jù)實現(xiàn),所以遷移僅僅涉及到修改數(shù)據(jù)訪問層。進(jìn)一步地說,如果您正在部署某種工廠策略,您可以為每個底層的存儲實現(xiàn)提供具體的工廠實現(xiàn)。如果是那樣的話,遷移到不同的存儲實現(xiàn)意味著為應(yīng)用程序提供一個新的工廠實現(xiàn)。
盡量減少業(yè)務(wù)對象中代碼復(fù)雜性
因為數(shù)據(jù)訪問層管理著所有的數(shù)據(jù)訪問復(fù)雜性,所以它可以簡化業(yè)務(wù)對象和使用數(shù)據(jù)訪問層的其他數(shù)據(jù)客戶端的代碼。數(shù)據(jù)訪問層,而不是業(yè)務(wù)對象,含有許多與實現(xiàn)相關(guān)的代碼(例如SQL語句)。這樣給開發(fā)人員帶來了更高的效率、更好的可維護(hù)性、提高了代碼的可讀性等一系列好處。
把所有的數(shù)據(jù)訪問集中在單獨的層上
由于所有的數(shù)據(jù)訪問操作現(xiàn)在都委托給數(shù)據(jù)訪問層,所以您可以將這個單獨的數(shù)據(jù)訪問層看做能夠?qū)?yīng)用程序的其他部分與數(shù)據(jù)訪問實現(xiàn)相互隔離的層。這種集中化可以使應(yīng)用程序易于維護(hù)和管理。
注意:這些標(biāo)準(zhǔn)都不能明確地調(diào)出對O/R(對象到關(guān)系)映射層的需求。O/R映射層一般用O/R映射工具創(chuàng)建,它提供對象對關(guān)系數(shù)據(jù)結(jié)構(gòu)的查看和感知(look-and-feel)。在我看來,在項目中使用O/R映射與使用EJB類似。在大多數(shù)情況下,并不要求它。對于包含中等規(guī)模的聯(lián)合以及多對多關(guān)系的關(guān)系型數(shù)據(jù)庫來說,O/R映射會變得相當(dāng)復(fù)雜。由于增加O/R 映射解決方案本身的內(nèi)在復(fù)雜性,例如延遲加載(lazy loading)、高速緩沖等,您將為您的項目帶來更大的復(fù)雜性(和風(fēng)險)。
為了進(jìn)一步支持我的觀點,我將指出按照Sun Microsystem所普及的實體Bean(O/R映射的一種實現(xiàn))的許多失敗的嘗試,這是自1.0版以來一直折磨人的難題。在SUN的防衛(wèi)措施中,一些早期的問題是有關(guān)EJB規(guī)范的開發(fā)商實現(xiàn)的。這依次證明了實體Bean規(guī)范自身的復(fù)雜性。結(jié)果,大多數(shù)J2EE架構(gòu)師一般認(rèn)為從實體Bean中脫離出來是一個好主意。
大多數(shù)應(yīng)用程序在處理他們的數(shù)據(jù)時,只能進(jìn)行有限次數(shù)的查詢。在這樣的應(yīng)用程序中,訪問數(shù)據(jù)的一種有效方法是實現(xiàn)一個數(shù)據(jù)訪問層,該層實現(xiàn)執(zhí)行這些查詢的一系列服務(wù)(或?qū)ο、或API)。如上所述,在這種情況下,不需要O/R映射。當(dāng)您要求查詢靈活性時,O/R映射正合適,但要記。哼@種附加的靈活性并不是沒有代價的。
        就像我承諾的那樣,在本文中,我盡量避免陳腐的最佳實踐。相反,關(guān)于J2EE項目中每一位架構(gòu)師必須做出的最重要的決定,我集中講解了我的觀點。最后,您應(yīng)該記。篔2EE并非某種具體的技術(shù),也不是強行加入到解決方案中的一些首字母縮寫。相反,您應(yīng)該在適當(dāng)?shù)臅r機,恰當(dāng)?shù)牡胤,使用合適的技術(shù),并遵循J2EE的指導(dǎo)原則和J2EE中所包含的比技術(shù)本身重要得多的實踐。

作者:未知 | 文章來源:賽迪網(wǎng) | 更新時間:2008-4-25 13:59:09

  • 上一篇文章:

  • 下一篇文章:

  • 相關(guān)文章:
    JAVA中的抽象類型的一些概念
    java語言開發(fā)程序中的幾個例子大家看看
    了解java開發(fā)語言在軟件開發(fā)中的幾個誤區(qū)
    如何才能使用Java實現(xiàn)內(nèi)部領(lǐng)域的特定語言
    Java開發(fā)學(xué)習(xí)小心使用Date以及Time類
    sun最近修補了一部分java的安全補丁
    Java程序員應(yīng)該了解那些開源協(xié)議
    java性能優(yōu)化的一些見解
    解析c#語言和java語言最相似的地方
    GUI JAVA應(yīng)用程序是怎樣做出來的?
    軟件技術(shù)
    · 開發(fā)語言
    · Java技術(shù)
    · .Net技術(shù)
    · 數(shù)據(jù)庫開發(fā)
    最新文章  
    ·j2se 嵌入式腳本抓取引擎
    ·JAVA開發(fā)的6個實踐的例子
    ·JBuilder7 / Weblogic7開發(fā)
    ·JAVA中的抽象類型的一些概
    ·java語言開發(fā)程序中的幾個
    ·了解java開發(fā)語言在軟件開
    ·如何才能使用Java實現(xiàn)內(nèi)部
    ·Java開發(fā)學(xué)習(xí)小心使用Date
    ·Java程序員應(yīng)該了解那些開
    ·java性能優(yōu)化的一些見解
    ·介紹JDK5.0一些collection
    ·基礎(chǔ)學(xué)習(xí):java中使用存儲
    ·解析c#語言和java語言最相
    ·Java語言學(xué)習(xí):jAVA中 的多
    ·Java是不是應(yīng)該增加新特性
    關(guān)于我們 | 軟件開發(fā) | 下載試用 | 客服中心 | 聯(lián)系我們 | 友情鏈接 | 網(wǎng)站地圖 | 新疆電子地圖 | RSS訂閱
    版權(quán)所有 © 2016 新疆二域軟件開發(fā)網(wǎng) m.jdtbank.com All Rights Reserved 新ICP備14003571號
    新疆軟件開發(fā)總機:0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆烏魯木齊北京中路華聯(lián)大廈A-5C 郵編:830000
     
    苍山县| 抚州市| 滁州市| 眉山市| 开阳县| 益阳市| 长顺县| 耿马| 固始县| 藁城市| 铁岭县| 邵阳市| 大安市| 庆城县| 漳州市| 麟游县| 宁津县| 南丹县| 油尖旺区| 莱芜市| 星子县| 河池市| 称多县| 宿迁市| 青岛市| 张掖市| 沛县| 漳州市| 舟山市| 登封市| 乐陵市| 友谊县| 根河市| 海原县| 仁怀市| 积石山| 高邮市| 张家港市| 翼城县| 武胜县| 二手房|