2015/08/10

Top scala libraries in github projects

在 javacodegeeks 有篇文章,作者針對 github projects 裡面去分析使用了哪些 scala libraries,藉此得知目前 scala 在社群中發展的狀況,哪些 scala library 最熱門,被使用最多的 project。

文章

這個 popular scala library 的 survey 在 2014 年也有做,是另一個同樣在 takipi 工作的工程師處理的。

2015: The Top 100 Scala Libraries in 2015 – Based on 64,562 GitHub Libraries

2014: Top 100 Most Popular Scala Libraries – Based on 10,000 GitHub Projects

分析結果

在作者分析過 Top 100 Libraries 之後得到幾個結論

  1. scala 社群正在快速的發展當中,有 33 個新進榜的專案
  2. spark #45 的排名超越了 hadoop #95
  3. 21.3% 的 top scala projects 使用了 Play framework
  4. 出現了很多 javascript 與 scala 整合的 library,包含了 scala.js(scala to js compiler)
  5. 最熱門的 Scala IDE 是 IntelliJ

另外還有一些次要的結論

  1. 21個專案來自 Typesage team
  2. Akka 很熱門,排名 #9
  3. scalatest 與 junit 是最多人引用的專案,scalatest 有 2521個(34.4%)專案使用
  4. logback 是最熱門的 logging library
  5. Google Guava在 Java 領域中排名 #4,但在 scala 領域中排名 #37
  6. Scalaz 類似 Guava 的角色,延伸了 scala 的核心,排名 #18
  7. H2 是最熱門的 database
  8. Jetty在 scala 領域中比 java 熱門

比較一下2014年的結果

  1. 2014年還是 slf4j 與 log4j 的年代,但在 2015年已經換成了 logback
  2. scalatest, Akka 維持了熱門程度

特別的發現 scala.js

scalajs 是我沒有聽過的一個專案,專案目標是可以將 scala code 轉換為 javascript,還將一堆 scala 專案都 porting 到了 javascript。

scala.js 把 scala 跟 javascript 連結在一起,讓 javascript library 取得了 scala 靜態資料型別的優勢,同時我們可以從 demo code 中發現,簡潔的 scala 語法,轉換出來的 javascript code 的成效,也就等於把 scala 帶入了 browser 的領域,不再專屬於 java JVM。

Tutorial/Training: Why Scala.js - Preview 是一個簡短的 scalajs tutorial,影片中簡短 demo 了 scalajs 的能力,首先是在網頁上繪圖,另外是從 scalajs 中呼叫另一個氣象網站的 API。

T2_Haoyi_Why_Scala.js.pdf 是 Li Haoyi,一位早期的 scala.js code contributor 的簡報,他提到 scala.js 誕生的原因,是因為現在的 web programmer 都需要學習 client 與 server 兩種語言,程式碼不能重用。另外 javascript 程式碼中 String 的濫用,如果使用 scala.js 可以讓 String-typing 變成 Strong-typing,更容易寫出堅固的 web application。

scala.js 並不是 javascript,有個最簡單的例子:

javascript>["10", "10", "10", "10"].map(parseInt)
[10, NaN, 2, 3] // WTF

scala.js> List("10", "10", "10", "10").map(parseInt)
List(10, 10, 10, 10) // Yay!

2015/08/04

自訂AngularJS Directives(一)

AngularJS

AngularJS是當前知名的JavaScript框架,其主要理念是透過MVC(Model-View-Controller)架構來幫助Web App開發者建置網站。

Directives

在AngularJS中,Directives指的是其自行定義的DOM元件,屬性,class名稱...等。曾接觸過AngularJS的讀者,一定對ng-controller,ng-bind,ng-model, ng-repeat...等等名詞不陌生,這些都是AngularJS內建的Directives。

AngularJS透過Directives賦與DOM元件額外的能力,如:ng-bind可以自動將某個記憶體中的變數與HTML元件建立關連;當該變數內容異動時,相關連的HTML元件的內容也將自動更新。

此外,AngularJS允許網頁開發者自訂Directives,這也是本篇文章將要探討的主題。

自訂Directives為AngularJS中稍微進階的議題。未曾接觸過AngularJS的讀者們,建議可以先參考幾篇AngularJS的基本介紹:

AngularJS官方文件

前端工程的極致精品: AngularJS 開發框架介紹

AngularJS 入門簡介(slideshare)

對於AngularJS的基本概念,本篇文章將暫不贅述。

為何需要自訂Directives

筆者前陣子開始研究AngularJS,並試著思考:已往曾經寫過的網頁,倘若是使用AngularJS食,該如何撰寫。

然而,卻遇到了一些瓶頸。如:我需要把我的網頁切成多個子頁面,並將每個子頁面的HTML/JavaScript獨立出來,並視情況顯示某些子頁面,或是移除某些子頁面。最重要的-這些子頁面可能需要可以被重複使用。

後來看了各大論壇的討論,以及幾篇部落格文章,都介紹到了AngularJS的自訂Directives功能,如:
SushiWen's Blog: 比較Backbone.js, Angular.js, Ember.js, Knockout.js 心得。

AngularJS的自訂Directives功能,概念上接近允許使用者自訂一個DOM元件。
您若已經非常熟悉AngularJS,亦可參考AngularJS官方對自訂Directives功能的介紹:Creating Custom Directives

本文僅從最簡單的範例開始介紹。

自訂Directives範例一:Hello World

以下範例自訂了一個helloWorld directive。

<!doctype html>
<html lang="en" ng-app="myapp">
<head>
  <meta charset="utf-8">
  <title>My HTML File</title>
  <script src="angular.js"></script>
  <script>
    angular.module('myapp', [])
    .directive('helloWorld', function() {
        return {
            restrict: 'AE',                
            template: '<h3>Hello World!!</h3>',
            replace: true,
        };
    });
  </script>
</head>
<body>    
    <hello-world></hello-world>
</body>
</html>

結果呈現了簡單的:

Hello World!!

若使用瀏覽器的開發工具檢視DOM元件,可以看到:

<body>    
    <h3>Hello World!!</h3>
</body>

Directive名稱

以上範例在HTML中,寫的是hello-world;而AngularJS會自動將其轉換為helloWorld。

Directive名稱的轉換規則如下:

1.去掉元素/屬性名稱前面的x-以及data-。

2.將冒號( : ), 連字號( - )或底線( _ )作為分隔符號,將元素/屬性名稱轉為駝峰式大小寫(camelCase)格式。

如以下寫法都會符合helloWorld directive:

<hello-world></hello-world> <br/>
<hello:world></hello:world> <br/>
<hello_world></hello_world> <br/>
<data-hello-world></data-hello-world> <br/>
<x-hello-world></x-hello-world> <br/>

restrict參數

restrict參數表示此Directive允許以何種方式呈現。

A表示屬性:

<div hello-world></div>

E表示元素:

<hello-world></hello-world>

C表示類別:

<div class="hello-world"></div>

A, E, C參數可以混合使用。如範例中使用'AE',表示以下兩種寫法都會被接受:

<div hello-world></div>
<hello-world></hello-world>

template/templateURL參數

template參數表示此Directive實際上呈現的HTML內容,
如上例中:

<h3>Hello World!!</h3>

此外,若HTML內容比較龐大時,可以改將其放在一個檔案中,
並使用templateURL參數。

因此上例可改成:

  <script>
    angular.module('myapp', [])
    .directive('helloWorld', function() {
        return {
            restrict: 'AE',                
            templateURL: 'helloWorldTemplate.html',
            replace: true,
        };
    });
  </script>

helloWorldTemplate.html內容如下:

<h3>Hello World!!</h3>

replace參數

replace參數表示原本的DOM元素是否需要被取代。

在上例中,replace為true,因此在使用瀏覽器的開發工具檢視DOM元件,只會看到:

<body>    
    <h3>Hello World!!</h3>
</body>

若replace為false時,則會看到:

<body>    
    <hello-world>
        <h3>Hello World!!</h3>
    </hello-world>
</body>

需特別注意的是,replace參數在AngularJS 1.3之後已不被建議使用,並可能在未來的版本被移除;因此可能的話,請避免使用replace參數。

小結

上述內容僅讓讀者對AngularJS的自訂Directives有了最基礎的概念;而下一篇將進一步介紹如何為自訂Directives建立其專屬的函式/API, 發揮其真正強大的功能, 以建立可重用的web元件。

2015/08/03

Null 造成了數十億的損失 Null Reference is the Billion Dollar Mistake

Tony Hoare 是 Quick Sort 的發明者、發明 Hoare logic 用來驗證程式的正確性,同時也是 Null Reference 的發明者,1980 ACM Turing Award 的得主。

在 2009 年的 conference 中,他主講了一個主題Null References: The Billion Dollar Mistake, 8/25 2009,Null Reference 造成了系統一些不可預期的錯誤,間接就等於是大量的金錢損失。

Null 的問題是語意不清,字面上的意思是「空」、「無」、「沒有」、「不存在」,Java 開發者常常會在 method 不需要傳送任何東西時傳回 return null。

然而吊詭的是,明明在那個 method 的定義上,就要回傳一個物件,使用這個 method 的開發者,並不一定會知道,這個 method 回傳的物件有可能會是 null,這就造成了 NullPointerException 問題,而這個 Exception 沒辦法在編譯時期就被發現,只能在運作時期產生出來,並在 JVM 直接造成系統停止運作。

這常會造成一種開發的循環,開發者說程式寫好了,上線測試了一段時間,怎麼系統突然掛掉了,然後找開發者去問,第一時間會回答不知道為什麼,然後去伺服器上取 log,找了半天,才發現出了 NullPointerException,然後就修改程式,判斷一下是不是 null,又重演一次上面的循環。

回頭來看看作者對 Null Reference 的看法:1965年時,我正在設計程式語言 ALGOL W ,這是第一個 comprehensive type system for reference in OO language,目標是確保每一個 object reference 都是安全可用的,而且可以由 compiler 自動檢查。

但是他卻沒辦法抗拒將 Null Reference 放進實作中,因為它實在是太容易實作出來了,而 Null 造成了 innerable errors, vulnerabilities 與 system crash,間接等於近四十年來造成了數億元的損失。

要避免遇到 NullPointerException,唯一的解決方法就是完全不使用 null,不過,剛說完不使用 null 可能馬上就會被打臉,因為 RDBMS 的資料欄位中,設計時為了節省儲存實體的硬碟空間,通常預設值都是 null。

Java 8 提出要用 Optional 處理 null,scala 也建議要使用 Option/Some/None Pattern,當語言的設計本身難免都會有一些誤區,也就是 Anti-Pattern,建議開發者要多深入了解語法的意義,並以「正確」的方式使用他們。

說避免不使用 null 還是夢想,還是得回頭提醒開發者,隨時都得要注意,除非確定該變數不是 null,否則一定要針對 null reference 進行處理,多寫一些檢查的程式碼,不會讓你的生命多浪費幾秒鐘,反而會讓系統更加穩定,不會發生不可預期的錯誤。

Refernces

補救null的策略

圖靈獎得主Tony Hoare:我的錯誤造成了十億美元損失