ASP.NET 開發人員不必擔心 Node 的五大理由

oschina發表於2014-11-12

  我把我上一篇博文獻給了討論為什麼 ASP.NET 開發者需要了解 Node.js 。就像高中辯論賽那樣,因為沒有任何技術抉擇(或者提議)可以憑空存在,我想試試看翻盤,於是我決定從對立面重新想幾個 ASP.NET 開發者應該離 Node 遠點的理由 (最起碼我深思熟慮之後再做決定)。

  哦別誤會……我真的很喜歡 Node,而且我覺得它提出的概念和模式將在很長一段時間內,對服務端 Web 程式設計產生深遠的影響。即使隨著時間的推移 Node 過氣了,我們肯定可以從下一個牛逼玩意身上或多或少的感覺到它的影響(不管好的和/或壞的)。而在這期間,我們中很多人都會選擇它,幸福的在一起,生產。

  不過條條大路通羅馬,雖然現在 Node 可能是"當紅炸子雞",不過這不意味著在Web 伺服器上沒它不行。每天都有大批的實際有效的產品交貨,用那些巨無聊的老框架,比如說 ASP.NET, Java EE, Rails, PHP(!)還有數不清的各種。好吧,甚至還有些瘋嘿用 COBOL 搭起了 HTTP 服務! COBOL 的 MVC … diao炸了。我給320個贊(不過千萬別讓我去幹這事)。 

  對於在這個行業呆了近二十年有點看破紅塵的我來說(攤手),好處就是… Node 提出了一個比較新的有意思的方式來解決那些比較老的無聊的問題。這不是貶低Node。只是說,它不是唯一,昨天不是今天不是明天也不會是。

  綜上……如果你是個 ASP.NET 程式設計師然後辭了職找 Node 的工作,來啊!給我發 email 或者 tweet,讓我知道你能幹啥 (要麼乾脆直接發簡歷……我們有在招聘哦!)。不過你如果還很迷茫,糾結於那些 Node-fanboy-love 的反對言論的話……繼續讀下去。

 1. Node最好的功能(非同步I/O)在.NET中已經存在了

  對Node最大的論據之一:Node通過使用非同步非阻塞模型來處理那些潛在的長時間執行的I/O操作。這意味著大多數在你web應用的伺服器端執行的工作(資料庫查詢、外部請求web service和其他的網路資源、訪問檔案等等)不會在你處理請求的主執行緒中發生,可以放心的繼續處理其他對本站的HTTP請求。出於這個目的,Node會維護一個執行緒池,那些工作將被專門排程給一個可用的執行緒。你可以定義一個回撥函式,當其中一個需要長時間執行的操作完成並返回時,Node將為你呼叫這個函式。這裡有一個使用mongoose.js API來查詢MongoDB的例子。注意回撥函式的引數以及呼叫‘findOne’時缺乏返回值分配。

var query = Kitten.where({ color: 'white' });


// findOne()唯一的引數是一個當findOne()執行完成後被呼叫的函式
// 回撥函式中包括錯誤處理以及查詢結果(可以為null)的處理

query.findOne(function (err, kitten) {
  if (err) return handleError(err);
  if (kitten) {
    console.log(kitten);
  }
});

  這類“連續傳遞”的程式設計風格有的時候對缺乏經驗的人來說很難把握,特別是當你的程式碼巢狀了很多層的時候。 但對於我們熟悉的順序風格(同步)來說還是有很大優勢的:它為你的執行框架提供了一個自然點來做其他事情,而不是(在這個例子裡)等待query.findOne()返回 。對Node來說,總有一些別的東西在處理髮來的請求。確實, Node最初的設計目的就是因為典型web伺服器端的生產瓶頸就是等待I/O的完成。Node的設計正是根據對這一點的觀察,提供了很多效能的優勢和擴充套件能力。

  這裡是對於Node的高階設計的描述:

  所以如果你正在用Node,這很棒。不過有趣的是你在今天的ASP.NET中也可以使用相同的模式!可能許多人熟悉最初由C#5.0引入的async和await關鍵字。在.NET的web應用中使用它們再配合其他輔助框架比如ASP.NET,Entity Framework等同樣可以取得像Node一樣的非阻塞執行風格。

  這裡有一個簡單的ASP.NET MVC控制器向Entity Framework進行查詢的實現(這個模式換成Web API同樣可行):

private DataContext db = new DataContext();

// GET: /Employee/
public async Task<ActionResult> Index()
{
    return View(await db.Employees.ToListAsync());
}

// GET: /Employee/Details/5
public async Task<ActionResult> Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    Employee employee = await db.Employees.FindAsync(id);

    if (employee == null)
    {
        return HttpNotFound();
    }

    return View(employee);
}

  有沒有發現每個方法是如何使用async/await來返回Task<ActionResult>而不是ActionResult?這個模式在語義上確保了和Node同樣的連續執行風格。await關鍵字表明瞭執行暫停的位置(並且當前執行緒可以先去處理其他請求),此時EF查詢在ASP.NET程式外執行。當EF查詢返回時,另一個執行緒用於立即恢復位於'await'後面程式碼的執行。在ASP.NET中暫停/恢復給了我們如同Node中回撥函式般的語義。實現雖然有差異,但基本原理是相同的,寶貴的伺服器端資源不能浪費在等待昂貴I/O操作的完成。 

  一個警告:Node的支持者會告訴你Node的優勢在於它的設計帶領你直接進入“成功的坑”。非同步是Node的預設模式,這對於Node來說非常容易,而同時你也可以在像ASP.NET這樣的框架中使用非同步,許多.NET開發者不這麼認為,但這無疑是正確的。 雖然Node應用和ASP.NET應用比起來可能會更加“非同步”,但不能理解成自身擁有更好的吞吐量或者更好的擴充套件性。應用的擴充套件性並不取決於你使用的框架,而在於你的應用本身是否有良好的擴充套件性。如果你現在在做APS.NET,在你覺得“ASP.NET缺乏擴充套件性”之前,花一些時間來學習並應用非同步模型 。

  2. Node簡化的應用模型同樣在.NET中可用

  另一個Node帶來的好處是它簡化的程式設計模型以及自主的步調,你可以瞭解並選擇一些更強大、更復雜的功能並將其引入。要構建一個“真正”的應用,Node需要掌握比ASP.NET更少的概念,這其實並不一定正確,但它確實給人這種感覺。這是主觀的理解,但許多Node的初學者認為這是正確的。 

  與之相比,ASP.NET MVC需要一系列連鎖的概念:HttpApplication、global.asax、web.config、模型、檢視、控制器、路由、行為、束等等。作為一名有經驗的ASP.NET開發者,我們認為理所當然 。但想象一下19歲的人準備著手做web開發,給他選擇到底是進入奇特的global.asax和web.config還是簡單地查詢幾行Javascript,Node會受到青睞並不奇怪。每一代人都會無意識地帶著自豪進行挖掘:“昨天我們用一個馬拉的犁和一個乾草叉,以及一些進取心,架設了HTTP服務,我們喜歡它!” 並且每一代人都有另外一代的年輕人緊隨其後,轉著它們的眼睛然後向前進,使用新的工具和技術。 

  額...但是再一次我們看到ASP.NET學到了一些新招數和進步。在近幾年,微軟致力於對.NET開發者社群定義的OWIN(.NET的開放Web介面)規範的限制。 它的基本思想是從伺服器端的基礎設施對.NET的web應用解耦,為.NET的web桟(主機,伺服器,中介軟體和應用)定義一個正式的抽象層,同時也定義了相鄰層之間互動的介面,這增進了多個web主機間的可移植性。它同時也作為Katana專案的基礎,Katana專案是微軟對OWIN的實現,旨在通過傳統的ASP.NET管道、HttpListener、IIS、主機以及其他更多東西來處理HTTP請求。

  OWIN和Katana借鑑了Node和其他許多輕量級框架,所以程式設計模型簡單親切。記得在Node裡"hello world"有多簡單嗎?看看Katana:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Run(context =>
      {
         context.Response.ContentType = "text/plain";
         return context.Response.WriteAsync("Hello World!");
      });
   }
}

  很容易吧!為任何給定的終結點簡單定義行為(上面的程式碼使用的簡單行為為這個應用的所有終結點所共用)。注意程式碼預設是非同步的,就像Node一樣。誰說老狗不能學新招數!

  明確地講,上面的程式碼在任何Katana主機上都可以執行:IIS,OWIN.exe(一個微軟提供的控制檯host,類似於node.exe),或是你自定義的host實現。可以在多臺主機和伺服器端執行同樣的程式碼是Katana非常有用的功能,而Node沒有提供。

  等等,還有!Katana有一個在常用IIS+ASP.NET伺服器基礎設施中的弱點,它依賴於System.Web,它不僅包括ASP.NET管道中的型別(HttpApplication,HttpContext,IHttpModule,IHttpHandler等),它還包括一些Web Forms的程式設計模型(pages,contorls,view state等)。你真的想把這些都帶到你現代的輕量級Katana應用程式域中?是的,ASP.NET團隊不認為你會使用其中任何一個。 

  所以他們建立了Helios專案。Helios是一個雛形專案,旨在具體化使用IIS(利用IIS的安全性、快取、程式生命週期管理等)host的OWIN應用不需要將System.Web拖入你的應用程式域。 Helios是一個pre-alpha版本,所以我們需要小心比較。然而,相比ASP.NET host的應用,Helios確實證明可以明顯減少請求錢的記憶體消耗,它預示了.NET的web桟在未來將更加簡潔,更具擴充套件性。這對於ASP.NET開發者而言是好事,你可以現在著手研究OWIN和Katana。最終,讓ASP.NET團隊知道你需要一個官方完整支援、類似於Helios的應用桟!

  3. Node的"到處都是Javascript"很棒!除非它不是 

  Node的其中一個論據是在你整個應用桟中你可以只使用Javascript。這確實有很多優勢。 

  除非你所在的團隊裡沒有專職的的JavaScript程式設計師。除非你願意花錢去招聘一些目前市場上高需求的科技人才。或者除非你願意用JavaScript重寫你的整個應用程式(或者你正從零開始……在這種情況下,你興許沒有重寫的問題,但你肯定有“我到哪可以找到專職JavaScript開發者”這個問題)。

  對一個從更傳統的面嚮物件語言如C#人來說,掌握(或精通)JavaScript是件難事。原型繼承非常強大,但也很容易繞住你。變數的範圍“規則”,嗯,也很有趣。強制型別轉換,有時需要,貌似很隨機。“typeof NaN === ‘number’”。相信我,還會遇到更多。沒有什麼是不可逾越的,JavaScript的生產力是不僅此而已。像TypeScript這類的東西很有幫助,尤其對從C#轉移到JS。只是不要指望一夜之間就能成功。

  這是原因的一部分,對所有時興的技術,Node對企業級來說仍然是新的。當然,一些喜歡嚐鮮的人已使用多年(企業中也有人員在嘗試時髦的應用框架)。但在短期內,如果你在Bigcorp.com上尋找能引入Node的人才,你可能需要付出一些努力。這並不意味著你可以不在乎Node……但要把握實際期望值。

  另外,注意到客戶端JavaScript開發與伺服器端開發相同卻又截然不同很重要。語言的差別並不那麼大(確實不大),但概念和模式只有少量的重疊。你需要的人不僅要了解JavaScript,也要明白網路延遲、非同步、伺服器的安全、規模縮放、雲測試和部署以及高效的資料訪問,等等。即使是一個優秀的客戶端js開發者也未必完全理解這些。反過來,如果你的公司剛開始做.NET開發,我敢打賭你團隊中也有幾個人知道這些東西。他們也許不瞭解Node (目前還不),但他們仍有你可以利用的知識。

  到這裡,我們看到了一方面問題。不管JavaScript和Node目前多火。重要的是它們是否適用於你的具體情況。是的,想一些未來的技術趨勢和“人才市場”走向是很重要的……但你對你掌握的東西有多大的信心?我們可以接受一些培訓來猜測明天……但就是他們所做的,猜測而已。一個全新的區域……C#可能不“酷”了,但它仍不會很快消失。

  更多的在下面。所以,如果你喜歡Node那為它而興奮吧,瞭解下它看看是否適合你和你的團隊。但你要首先專注於今天的需求,適當少關心你將採取的下一個閃光的新東西。當你準備好時它就會出現閃光。

  4.如何你的ASP.NET應用程式規模不大但反應緩慢,也許這個問題在於你的設計

  這種差異將阻礙你使用Node重寫你的Web應用以修復你當前在ASP.NET的實現中所存在問題。用Node重寫不會有顯著幫助,很可能沒有任何幫助。

  這就像在Ye Ole軟體協會中的穆哈咖啡加入印度茶必然會導致溢位一樣。因此轉向Node不會簡單的解決你的問題.....這些問題的根源在於你,而不是微軟。

  詢問你自己(坦誠的)適合下列描述的那種:

  1.你和你的團隊富有遠見,卓越的軟體工程師將利用時間儘可能識別出ASP.NET中最佳的軟體工程實踐並將他們應用於你的專案。你的設計是 SOLID。你可以對何模組進行單元測試。你知道你的的程式碼測試覆蓋標準,並且你知道他為什麼不是100%。你冷靜的分析 Entity Framework,、NHibernate,原生ADO.NET和百萬級 micro-ORMs 框架的優缺點並且基於你專案的限制做出合理的選擇。你經過長時間的艱難思考決定你如何聚集於你客戶端和伺服器端應用程式的業務邏輯,考慮接下來的技術、工 具、生產力和效能等等如何影響你的決策。你與合作伙伴勤奮的模擬現實世界的用例和情節,甚至在專案早期設定效能層級和載入測試場景,所以你在那時就擁有關 於效能和規模的圖表。你可以無數次自由的描繪你的應用和資料訪問許可權,你也可以修改他們或者去掉那些沒有任何差別的附加功能。管理人員理解這些事情需要時間,然而你需要交出高質量的程式碼。

  2. 你和你的團隊目光短淺,非理性的“開發者”幹著沒有能力勝任的工作並且不顧一切保住工作。 根據定義,你從來沒有讀過關於ASP.NET 最佳實踐的書或者文章(如果你正在讀這篇文章,你可以在Stack Overflow上通過連結找到最佳實踐的資料,搜尋GDD或者Google-driven development)。 你的設計原則是,“solid”。 曾在你團隊裡待過的開發者寫了一些單元測試用例,當一些程式碼改變時,你把它們註釋了,這些用例永遠不會再編譯(儘管你的專案經理在給CTO的程式碼質量週報中仍然引用這些用例)。 有一次,你從換過三次工作的同事那裡聽說實體框架“很爛”,NHibernate“太複雜”,因此你編寫自己的DAL拼裝記憶體中的SQL語句(通過請求...沒有快取),並保證你的動態資料庫欄位(ExtraColumn1,ExtraColumn2,…ExtraColumn25)都讀取到適當位置,在一個記錄的基礎上(或者…你從另一個同事那裡聽說實體框架EF“很棒”,因此整個伺服器端架構你採用EF物件圖的操作深層次結構,EF物件圖對映由一個從未見過7張表關聯的“資料庫架構師”設計的相容第五正規化的資料庫)。  你不知道分析器是什麼東西。 “SQL執行計劃”對你而言,聽起來像是要進監獄的事情。 你“測試”系統好幾個月了,卻從未嘗試併發使用者請求,你的可擴充套件性就是“買更多的硬體”。 等等。

  3. 介於第 1 和第 2 種情況之間.

  老實說, 我們當中很多團隊既不屬於第 1 種也不屬於第 2 種, 而是介於 1 和 2 之間. 這很正常, 這世上沒有完美無缺的專案, 也沒有完美無缺的團隊. 所以, 如果你比較傾向於上面提到的第 1 中情況, 而且在提高 ASP.NET 的效能和擴充套件性方面, 你已經竭盡所能, 做了你能做的, 結果依然不盡如人意, 那麼, 也許是時候改用其他框架了.

  只有無能的人才會把自己的過錯推給工具. 自己的程式有問題怨 ASP.NET 這就是現代版的在編譯器中找 bug. 拉不出屎, 別怪茅坑… 問題可能來至你的團隊. 當然, 我不是說 ASP.NET 很完美, 一點問題也沒有 (事實上, ASP.NET 本身也有很多不足). 它不過是個工具, 一個有用的工具, 一個成千上萬的網站每天都在正常使用的工具. 其中一些網站(甚至是大部分的網站), 其複雜程度, 訪問量要比你的高的多. 像這樣一個身經百戰, 被使用多年的框架, 不能滿足你的專案開發需求的可能性, 坦白講, 不大.

  基於對“更好”一詞不同的定義,以上幾點並不是說Node比ASP.NET 更好或更糟。 它是說如果你計劃由ASP.NET 轉向Node,這很好,但是不要批評ASP.NET 在效能和可擴充套件性方面的問題。在“自由地申請更多可擴充套件性”方面,Node並不是神奇的魔法粉。 Node 只是一個類似於ASP.NET 的工具…使用得當,它的效果很好。 草率地使用並且沒有清楚地理解它的優缺點,就像花了大量的時間和金錢重寫Node,最終會回到原點,就是你今天所處的位置。

  我的朋友,這就像一聲相當可悲的低音號

  5. 孩子,“微軟正在消亡!/破產!/邪惡!/無聊!/土裡土氣!/等等。”絕不可能孕育一個科技戰略

  現在,正如你讀到的,由於一點不理性、毫無緣由的討厭微軟,一些在企業級軟體領域工作的人正在由 ASP.NET 轉向 Node。 這些人在他們的組織內部是值得信賴的決策者。 他們對商業上能夠產生很大下游影響(正面或負面)的技術決策負有責任。 當你跳過他們 PPT摘要頁、第一頁或者第二頁檢視後面的內容時,站不住腳的理由消失了,他們的說法幾乎可以歸結為“我不喜歡微軟,我不喜歡 ASP.NET,我想做年輕人正在做的比較酷的事情”。

  截至2013年12月31日,《金融時報》(FT)全球500強指數中微軟市值排名第四。 在同一季度,微軟收入創紀錄地達到245億美元。 微軟還沒有破產,遠非如此。 微軟Azure充滿活力,它為企業持續遷移到雲提供良好的定位,在這一領域,它富有競爭力,而且這一領域我們目前僅僅發展到初期階段。 相對於傳統的Office辦公軟體,Office 365已成為一個可行的基於雲端計算的替代產品。 和其它公司一樣,微軟持續地大量地投資於研發領域(這怎麼會“無聊”呢?)。 微軟“土裡土氣”嗎? 如果你基於企業級IT解決方案的定義而問這個問題,你是不是發現自己已經錯了?

  不要誤會 … 在一個大的全新的專案開始,有很多理由選擇使用其它產品而非微軟的產品。 前期的許可費用可能難以接受,尤其相比於各種開源的軟體(儘管有 方法減輕那些費用)。 在這一點上,至少微軟一些 核心技術的長期生存能力是不穩定的。 基於 Satya Nadella升職為 CEO及他所有快樂的公開演講,我們仍然不知道他是否有能力利用好微軟 已有的優勢,並解決微軟面臨的問題。

  然而,如果你已經投入巨資並顯著地建立了一個技術優勢,拋棄它重新開始通常是一個錯誤。 100年前Joel這樣寫到。 以我的經驗,這通常是一個主觀上的決定,而不是一個客觀上的決定…不管討論哪種技術。

  如果你是一個 CTO,面對遺留的 ASP.NET 程式碼這座大山,你認為用 Node 重寫將會解決所有的問題,你這在給你的公司、你的董事會、你的客戶幫倒忙。 他們給你工資不是為了讓你在流行技術中換來換去。 他們給你工資也不是為了讓你表達對微軟肥皂劇故事“本週流行哪個技術?”的討厭。“他們給你工資是為了實現商業價值 … 可預見的經濟上的價值,並且產品要有高質量。 當開始做的時候,研發技術的選擇比我們想要別人認可的選擇要少的多。 在一個軟體專案中,大部分可變性是以人為中心。 但是當我們能夠批評自己的缺點時,事情卻變得容易得多,”每個人都知道 ASP.NET 不能形成規模“。

  讓我們假設你是一個基於ASP的網路商店,但是你有點擔心過度依賴單一的供應商。你有什麼方案能超越“重寫所有Node”? 首先,你可以標識部分你的架構,它可能得益於各種開源的替代方案,用它們變更盒子中的ASP.NET。對於.NET來說,過去幾年生機勃勃的開源生態系統使得其更加地優雅的重要原因(主要原因?)。整個框架是偉大的,但是你也可以考慮像 Massive或者 Simple.Data那樣的替代方案?也許你的資料訪問策略需要一個改頭換面,使用 NoSQL資料庫MongoDB 或者 RavenDB,您的應用程式會受益?也許,你建立了一個適當的服務層,可以利用新形式,像 responsive UI那樣直接的方式。這些型別的架構更改絕非易事,他們不被認為是輕量級的,但是他們可能需要解決具體的問題,卻面臨著沒有更大的預算去拋掉風險,重新開始。

  其次,考慮更多激進的想法,比如在Mono平臺上執行,選擇自己的主機作業系統。 現在ASP.NET和MVC在Mono上執行得相當好。 如果你對雲技術感興趣,但是不想使用Azure,你有其它的平臺執行ASP.NET… AWS EC2(亞馬遜可擴充套件的雲託管)虛擬機器AWS Elastic Beanstalk (亞馬遜的PaaS服務),小型的雲端計算空間供應商如AppHarbor,還有最近釋出的支援.NET的紅帽OpenShift(雲端計算服務平臺)

  最後,在決定選擇哪個技術和平臺前,確定你已經找到選擇的理由。 除了前面提到的許可費用,還有很多需要考慮的東西。 所有權的總花費並不只有前期費用,也有使用時的費用 … 其中一些費用不容易進行量化。 使用 Node進行重寫,你的團隊能夠按時完成的機會成本是多少? ASP.NET應用開發遇到問題時,你可以 24*7打電話尋求技術支援而不是隨便在一個 Node開發者論壇上尋找答案,這對你而言價值是多少? 你所處的地理區域是前端人才如 Node更多,還是主流技術的專家如 .NET和 Java更多? 找到、吸引、留住優秀的 Node開發者難度是多大? 你是否準備好應對他們可能被挖走的問題? 目前你的團隊很多開發者都掌握了有價值的領域專業知識 … 當你轉向 Node時,你是否計劃繼續保留這些開發者? 如何將專業知識轉化為一門新的技術架構? 如果你計劃不再僱傭他們,你確定你已經準備好看著他們帶著來之不易的領域知識走出公司大門?

  這裡沒有黑白… 它不像招聘”過時的”開發者:精通過時的技術、對招聘人員也沒有吸引力,這是一個成功的招聘策略。 說句公道話,永遠堅持使用ASP.NET(或其它任何一門技術)也不像是正確的選擇。在你做出由ASP.NET轉向Node重大的決定之前,必須客觀而不是主觀地考慮上面的所有因素。 保持謹慎,保持客觀。

  希望我在文章裡已經給你了一些思考的東西。 我很喜歡Node,在接下來的幾年我計劃花費更多的時間學習它。 但是我也很喜歡ASP.NET... 鑑於它的功能和未來的規劃。 明智的做法是對兩者都保持關注,不要過早地下決定。

  最後,對於不同的場景下選擇哪種語言並沒有一個唯一的答案,但是可以參考一些指導性的原則。 讓我們在下一篇文章中對這些原則進行討論。

  原文地址:http://www.wintellect.com/blogs/jlane/five-reasons-asp.net-developers-shouldn%E2%80%99t-worry-about-node

相關文章