• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
JavaScript Code Quality
 

JavaScript Code Quality

on

  • 6,062 views

「關於 JavaScript 品質,我想說的是...」於 JSDC.tw 2013

「關於 JavaScript 品質,我想說的是...」於 JSDC.tw 2013

Statistics

Views

Total Views
6,062
Views on SlideShare
6,053
Embed Views
9

Actions

Likes
37
Downloads
111
Comments
0

1 Embed 9

https://twitter.com 9

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    JavaScript Code Quality JavaScript Code Quality Presentation Transcript

    • JAVASCRIPTCODE QUALITY講者 josephj關於 JavaScript 品質,我想說的是...
    • 當談到 JavaScript 品質...大家心裡的重要性就好像左邊那一本 XD
    • JavaScript 的興起...讓開發者覺得 JavaScript 就是要複製貼上
    • Bad JavaScript = 違章建築寫程式應該是被維護的,而不是一看就想要拆掉的6000 ⾏行 JavaScript!
    • Agenda・在 Yahoo! 學到的教訓・需要建立前端團隊的架構・在 miiiCasa 學到的教訓・需要先設計、多抽離・未來可持續努力的方向・自動化 Plus成長 = 從過去的錯誤反省!
    • 第 1 課 from Yahoo!前端⼯工程師必須成為真正的團隊、⽽而⾮非只是資源
    • 中央游泳池當時「前端⼯工程師」不屬於任何產品線專案 1專案 2F2E Pool不會有閒置資源
    • 中央游泳池當時「前端⼯工程師」不屬於任何產品線專案 1專案 2F2E Pool基本上都在專案任務導向、缺少團隊機制大家只管自己的眼前的案子缺少水平的機制去管理品質
    • 久了必會發生慘案• 由新人負責、跟其他專案成員關在小房間(沒有其他 F2E)• View 全部用 JS 組、後端只給 JSON• 不支援 NoJS、沒法上一頁• 重複程式碼非常多,沒人敢大改• 專案結束沒多久,新人離職• 2012 年底,此服務關閉
    • 永遠在我心裡的一句話“As a team, F2E 的價值究竟在哪裡?”好不容易培訓⼀一個新⼈人、卻⼜又因制度不健全害了他
    • 開始去思考「團隊」這件事• Code Convention 團隊規範• Code Review 定期 Review 程式碼• Checklist 上線前需達成的清單⾮非常重視⼀一致性、維護性
    • 規範一些最基礎的小事情一致性、像同一個人寫的https://github.com/josephj/f2e-styleguide
    • Code Reviewhttp://programmers.stackexchange.com/questions/170211/php-data-access-layer程式碼接受所有⼈人檢驗
    • 比 JSLint 更傷感情 XDhttps://github.com/miiicasa/youtube-iframe/issues/1
    • 需要比較正面的態度每次 Code Review 都能學到很多東⻄西!
    • Pair Programminghttp://en.wikipedia.org/wiki/File:Pair_programming_1.jpg⼀一個⼈人寫程式、⼀一個⼈人當觀察員
    • 導入正確的模式模組化 (Module) 與觀察者 (Observer) 模式
    • 模組:寫法一致、避免全域變數welcome/_notification.js⼀一個模組即有⼀一個 JS 檔
    • 模組:寫法一致、避免全域變數YUI.add("welcome/_notification",  function  (Y)  {    var  trans  =  {},            module;    module  =  new  Y.Module({            selector:  "#notification",            init:  function  ()  {                                },            on:  {                    viewload:  function  (node)  {                    }            }    });},  "0.0.1",  {"requires":  [            "module"    ]});welcome/_notification.js以 CLI ⾃自動從樣板建⽴立模組⼀一個模組 (Partial) 配⼀一個 JavaScript 檔好⽤用⽅方法與屬性都圍繞在此 instance⼀一旦當此模組存在於 DOM 之中相依模組此模組的 Selector 或物件參考
    • 模組:寫法一致、避免全域變數YUI.add("welcome/_notification",  function  (Y)  {    var  trans  =  {},            module;    module  =  new  Y.Module({            selector:  "#notification",            init:  function  ()  {                                },            on:  {                    viewload:  function  (node)  {                    }            }    });},  "0.0.1",  {"requires":  [            "module"    ]});                            module.broadcast("greeting",  trans.greeting);                            module.listen("need-­‐love",  function  (e)  {  /*  do  something  */  });                            new  Y.ScrollPagination({node:  node});welcome/_notification.js所有的功能都圍繞著模組化開發多國語系送廣播聽廣播加上其他相依模組trans.greeting  =  module.getTrans("greeting",  "Hello  World");,"module-­‐popup",  "module-­‐intl",  "gallery/scroll-­‐pagination"
    • 模組:寫法一致、避免全域變數YUI.add("welcome/_notification",  function  (Y)  {    var  trans  =  {},            module;    module  =  new  Y.Module({            selector:  "#notification",            init:  function  ()  {                                },            on:  {                    viewload:  function  (node)  {                    }            }    });},  "0.0.1",  {"requires":  [            "module"    ]});                            module.alert(trans.greeting);                            module.broadcast("greeting",  trans.greeting);                            module.listen("need-­‐love",  function  (e)  {  /*  do  something  */  });                            new  Y.ScrollPagination({node:  node});welcome/_notification.js所有的功能都圍繞著模組化開發多國語系共⽤用的 popup送廣播聽廣播加上其他相依模組trans.greeting  =  module.getTrans("greeting",  "Hello  World");,"module-­‐popup",  "module-­‐intl",  "gallery/scroll-­‐pagination"限制團隊成員在沙箱(Sandbox) 中開發功能擴充也能有一致介面只專注開發該模組功能、無法污染外界
    • 不只是 JavaScript Ninja!認識軟體⼯工程與持續集成,事半功倍!
    • 需從軟體工程的角度出發• Lint 自動檢查程式碼• Combine/Compress 自動合併及壓縮 JS/CSS• Optimize image 圖檔最佳化• Compass 用 High Level 的語言讓 CSS 簡化• Skeleton 自動建立樣板檔案導⼊入⾃自動化、減少「⼿手⼯工」、才能提昇品質
    • 在 miiiCasa 實踐了這些理念很幸運可以從零開始、擔任前端⼯工程部⾨門主管這些想法與理念都⼀一⼀一地實踐了難道就不會有問題了嗎?http://www.slideshare.net/josephj/ss-7705095建立前端開發團隊
    • 第 2 課 from miiiCasa必須先設計、並導⼊入更好的 JavaScript Pattern
    • miiiCasa Space家庭雲:用單一 URL 存取家中裝置上的資料• 4 個不同的媒體:照片、音樂、影片、文件• 2 個不同的類型:首頁列出 Storage、內頁只列目錄• 都是檔案列表、但差異很大:• View 都各自有差異• 照片要 Slideshow• 音樂要播放器• 影片用 VLC / Flowplayer• 文件要用 Lightbox 顯示照片、同時支援影片、音樂、Google Drive Preview...
    • 有時程壓⼒力...該怎麼快速產出?
    • 『coding』= 複製貼上的工作http://but.tw/2008/10/programmers_rule/團隊的每個⼈人都有責任
    • 用「複製、貼上」達成需求與滿足時程• 一模組約 1,500 行 JS• 4 個不同的媒體• 2 個不同的類型• 差異很大 = 修修改改1,500*4*2 = 12,000 行後續有新功能都幾乎是「複製貼上 x 8」
    • Winchester Mystery Househttp://www.flickr.com/photos/harshlight/3670192350/外表富麗堂皇、也確實地達成應有功能與時程
    • http://www.flickr.com/photos/dalvenjah/33560263/lightbox/內部的結構...http://www.flickr.com/photos/skinnylawyer/5570163978/疊床架屋是軟體開發最常見的問題在煙囪上架屋頂? ⾛走向屋頂的樓梯?
    • 壓縮開發時程之謎Stoyan StefanovThe few man-hours spent writing the codeinitially end up in man-weeks spent reading it.數⼩小時寫出的程式碼、得花數週或更多的時間維護它要在 8 個 JavaScript 上:• 增加新功能• 修改 Bug• 改變邏輯• 看不懂、乾脆重寫⽼老闆跟專案經理永遠無法理解的事...
    • 面對問題未來要怎麼預防同樣的問題、或避免讓問題繼續蔓延
    • EDD – 設計文件圖表BranchURLs檔案結構Controller模組詳細說明預先規劃的假資料JS 的架構日益複雜需要跟後端程式一樣先規劃負責人先仔細思考、撰寫出此文件所有開發人員一起討論可行性、問題點把思考不周延之處找出來、了解配合模式時程預估較為準確、有機會先預防
    • Refactoring - 重構
    • 重構 = 打掉重寫?應避免 NIH 綜合症(非我所創、Not Invented Here Syndrome)NO!技術人員應該用更客觀的心態面對重構重構 = 持續且小的改進。
    • 開發 重構 開發 重構把重構納入產品開發的 Iteration......無法⼀一開始寫出完美的程式碼藉由實作、看到問題與需求,再著⼿手修正逐步達成理想的程式碼品質
    • 重構案例:Pop-up 視窗util.showDialog(module,  title,  message,                                  okText,  cancelText);module.broadcast("dialog-­‐show-­‐request",  {        title:  title,        msg:  message,        buttons:  {                ok  :  {                        label:  okText,                        callback:  okHandler                },                cancel  :  {                        label:  cancelText                }        }});new  Y.Panel({        headerContent:  title,        bodyContent:  message,        buttons:  []        render:  true,        visible:  true})過去⾄至少有三種不同的作法統⼀一作法、將預設⾏行為確認module.alert(message);module.confirm({        title      :  title        content  :  message},  okHandler);module.inform(message);對程式碼精簡、⾏行為的⼀一致性獲得⼤大幅改善
    • 重構案例:Pop-up 視窗util.showDialog(module,  title,  message,                                  okText,  cancelText);module.broadcast("dialog-­‐show-­‐request",  {        title:  title,        msg:  message,        buttons:  {                ok  :  {                        label:  okText,                        callback:  okHandler                },                cancel  :  {                        label:  cancelText                }        }});new  Y.Panel({        headerContent:  title,        bodyContent:  message,        buttons:  []        render:  true,        visible:  true})過去⾄至少有三種不同的作法統⼀一作法、將預設⾏行為確認module.alert(message);module.confirm({        title      :  title        content  :  message},  okHandler);module.inform(message);對程式碼精簡、⾏行為的⼀一致性獲得⼤大幅改善重構的價值減少程式碼中光怪陸離的現象未來開發更容易減少 UI 的不一致
    • Decoupling - 抽離避免把所有程式碼都放在一個 JS 中
    • 為什麼會產出「一大包」JS?• 麻煩!JS 載入需考慮「前後順序」<script/> 有先後順序,例如載入 jQuery UI 的 Tabview.• JS 本身缺乏「模組」的觀念直到最近 ECMAScript 才要內建• 「頁面」眾多、分割不易不像其他的語言,大多只要 require 就可以使用• 對 JavaScript 缺乏「軟體工程」的態度非本科:對程式抽離、正規化概念薄弱。本科:對 JS 不用想這麼多吧!
    • 抽離範例:Space Photo• 主要功能:列出 Router USB 裡的照片。• 其他功能:提供下載檔案、幻燈秀、縮圖產生機制、檔案描述、LightBox、分享、重新命名等機制。這才是此程式中最重要的每一個都可以另開 Module 處理
    • 代碼抽象三原則• DRY - 不要重複自己出現重複時就抽象出一個解決方法• YAGNI - 你不會需要他快 + 簡單!不要把精力放在抽象化上• Rule of 3 - 三次原則當同樣的情況出現三次才進行抽象化http://www.ruanyifeng.com/blog/2013/01/abstraction_principles.html
    • 功能抽離範例space-centralize.js (共 103 行)/**  *  @module  space-­‐centralize  */YUI.add("space-­‐centralize",  function  (Y)  {        //  Implementation  here...        Y.Space.bindCentralize  =  bindCentralize;},  "0.0.1",  {        "requires":  [                "space",  "node-­‐base",  "event-­‐resize"        ]});需要讓圖⽚片隨螢幕寬度置中對⿑齊,瀏覽較舒適原本負擔很重、1500+ ⾏行的 JS 檔/**  *  @module  space/photos/_photos_main  */YUI.add("space/photos/_photos_main",  function  (Y)  {        //  ...        Y.Space.bindCentralize();        //  ...},},  "0.0.1",  {        "requires":  [                //  ...                "space-­‐centralize",                //  ...        ]});只增加兩行
    • 採用模組化 Library解決 HTML 中 JavaScript 缺乏模組機制的問題define(“editor”, [‘a’,’b’,’c’], function() {    function Editor { /* Constructor */ }    return Editor;});require(["editor"], function (Editor) {    new Editor();});editor.js – 定義 editor 模組demo.js – 使⽤用 editor 模組任何⼀一個網站都應該要⽤用!
    • 應加入的規範• 一個 JS 檔案不應超過 500 行• 一行不應超過 100 個字元維護一個大雜匯的 JavaScript 有何意義?會超過 500 行應代表你該抽離功能了
    • 未來還能做些什麼
    • 給自己未來的一些題目大多是更多工具的整合、讓自動化來提升品質⼯工具 ⼯工程師• 無聊• 重複性的• 浪費時間的 藉由⼯工具持續回饋
    • 自動偵測重複的原始碼需要把「避免重複原始碼」變成⼀一個習慣
    • 是很重要的一件事!大家所熟悉的 JSLint, JSHint 卻沒有 Orz...都只有「單一檔案內」的語法檢查
    • PMD - 原始碼分析器其中 CPD 工具可以分析 JS 的重複/bin/run.sh  cpd  -­‐-­‐minimum-­‐tokens  50                                  -­‐-­‐files  ~/project/foo/js                                  -­‐-­‐language  ecmascript
    • 跑出來的結果重複的行數 重複的檔案列表非常需要納入 Commit 流程或 Auto Build 檢查
    • Error Log 管理JavaScript 錯誤應該被即時記錄並回報瀏覽器錯誤window.onerrortry-catch錯誤發生程式決定是否要往上丟程式決定是否要往上丟 把錯誤丟到 Server 做記錄、回報就不用辛苦地翻程式碼找問題控管好這兩個時間點
    •        //  Log  to  server.        window.onerror  =  function  (message,  url,  line)  {                var  queryString,                        el;                queryString  =  location.search.slice(1);                el  =  document.createElement("img");                el.src  =  LOG_URL  +  "?"  +  [                        "hostname="  +  encodeURIComponent(location.host),                        "message="  +  encodeURIComponent(message),                        "line="  +  encodeURIComponent(line),                        "url="  +  encodeURIComponent(url),                        "query="  +  encodeURIComponent(queryString)                ].join("&");                return  true;  //  Avoid  browser  error.                                                                                                                                                                  };把錯誤回報給 Server常見作法:用假圖片 Request 達成、可跨網域但是!錯誤需要被 Grouping 才有價值
    • 推薦工具 - Sentry接收各種程式語言錯誤、分組、寄通知信
    • Esprimahttp://esprima.org/最近只要聊到 JavaScript Code 品質,幾乎都會聽到這個工具
    • Esprima 運行原理程式碼 抽象語法樹Source Code Abstract Syntax Treevar  answer  =  6  *  7;{    "type":  "Program",    "body":  [        {              "type":  "VariableDeclaration",              "declarations":  [                  {                      "type":  "VariableDeclarator",                      "id":  {                          "type":  "Identifier",                          "name":  "answer"                      },                      "init":  {                          "type":  "BinaryExpression",                          "operator":  "*",                          "left":  {                              "type":  "Literal",                              "value":  6,                              "raw":  "6"                          },                          "right":  {                              "type":  "Literal",                              "value":  7,                              "raw":  "7"                          }將程式碼轉成結構⼀一致的 AST 格式,很容易做後續處理經過 Esprima Parse
    • Esprima 範例 – CodePainter問題:每個⼈人寫的空格、引號習慣都不⼀一樣,能否統⼀一?跑⼀一次⽤用 Esprima 實作的 CodePainter ⼯工具,問題全搞定https://github.com/fawek/codepainter
    • Esprima 的可能應用• JSHint: 將會改用 Esprima• 語法高亮• 塞 Log,協助偵錯:• 在每個 Method 都放:console.log("someMethod()  is  executed.")http://www.slideshare.net/ariyahidayat/javascript-parser-infrastructure-for-code-quality-analysis
    • Continuous Integration 持續集成「所有」⾃自動化檢查,都應該與 CI 整合中央 Git個⼈人 Gitgit  pushpost-­‐receivetriggergit  cloneBuildJSHintCode DuplicationUnit TestFunctional TestCode Coverage通知成功或失敗Performance讓檢查像喝⽔水⼀一樣簡單、確保品質CI 伺服器
    • 推薦服務CodeShip懶得⾃自⼰己架⼀一台 CI 伺服器?市⾯面上有好幾家 SaaS 的服務可⽤用若你的原始碼是放在 GitHubCodeShip 與Travis 都只要勾選就可以使⽤用
    • 把團隊更緊密的綁在一起把所有訊息 (Commit, Wiki, Issue) 都倒進聊天室不用交談也知道彼此的做了什麼、點選可看詳細內容
    • 文學編程Literate Programming寫程式的理想型態
    • Donald Knuth現代電腦科學的鼻祖A style of programming that maximize ourability to perceive the structure of a complexpiece of software.文學編程的理念「是時候了,讓我們的程式碼更好!」文學編程是一種寫程式的理想形態 :讓我們對於軟體的每個複雜環節都能充分地理解
    • 更有組織維護自己的文件Leo Editor - 依自己的思路撰寫文件、組織代碼可以是任何的內外部⽂文件、節點可以任意地被複製搬移⾃自由地組織、編排節點順序產出的程式碼可與其他⼈人 Merge、Leo 會幫你追蹤⽀支援Textile、Web 投影⽚片的輸出
    • 更有組織維護自己的文件Leo Editor - 依自己的思路撰寫文件、組織代碼可以是任何的內外部⽂文件、節點可以任意地被複製搬移⾃自由地組織、編排節點順序產出的程式碼可與其他⼈人 Merge、Leo 會幫你追蹤⽀支援Textile、Web 投影⽚片的輸出
    • Leo Editor 很強大、也不針對特定語言,但是...每個人都有自己愛用的編輯器(Vim 或 Sublime)Leo 在程式碼編輯功能上似乎不怎麼樣...在一堆編輯器中切換也是件很愚蠢的事以喜歡的編輯器、⽤用⽂文學編程寫 JavaScriptLeo 的缺點
    • https://github.com/jostylr/literate-programming以 JavaScript 實作的文學編程編譯 Markdown產出 JavaScriptJames Taylor
    • https://gist.github.com/josephj/5580918Demo>  File  count.js  savedliterate-­‐programming  ⽂文學編程.md                                                                                                                                                                                                                                                                    寫程式就像寫部落格⼀一樣!可重新組合章節讓別⼈人⾮非常容易理解
    • Literate CoffeeScriptCoffeeScript 的作者 = 文學編程的大力推廣者Jeremy AshkenasJourno 部落格系統Docco API 文件產生器以⽂文學咖啡寫成:缺點:得依照原始碼的順序寫
    • Journo 的 README.md就是部落格系統的完整原始碼 (journo.litcoffee)$  coffee  -­‐c  journo.litcoffee  #output  journo.js
    • 文學編程過去不是主流、未來也不會文學編程小結但身為一個開發者,應秉持文學編程的精神:「程式碼是給人閱讀的」以上兩種作法,似乎也可以稱為「部落格編程」是我們現今最容易理解技術的一種 Material
    • Code Review設計⽂文件 產出 API ⽂文件模組化模組架構代碼規範Pair Programming檢查清單⾃自動合併與最⼩小化Lint單元測試物件導向重構代碼重複檢查JS 語法分析、重置持續整合品質的 TODO LIST抽離原則⽂文學編程團隊活動 觀念及架構 ⾃自動化整合訊息看團隊需求來做導入或整合Prototyping
    • 寫程式是個良心的事業過去的評價會⼀一直跟著你,我們應該盡⼒力寫好
    • 程式碼品質,大師們都會強調再強調
    • 2b || !2bthat is a question.
    • Thank you!• GitHub - josephj• Facebook - 蔣定宇• Slideshare - josephj• Linkedin - josephj6802聯繫我