A. 如何在Scala中使用條件表達式
條件表達式
Scala的if/else語法結構和Java或C++一樣。不過,在Scala中if/else表達式有值,這個值就是跟在if或else之後的表達式的值。例如:
if (x > 0) 1 else -1
上述表達式的值是1或−1,具體是哪一個取決於x的值。你可以將if/else表達式的值賦值給變數:
val s = if (x > 0) 1 else -1
這與如下語句的效果一樣:
if (x > 0) s = 1 else s = -1
不過,第一種寫法更好,因為它可以用來初始化一個val。而在第二種寫法當中,s必須是var。
(之前已經提過,Scala中的分號絕大多數情況下不是必需的。)
Java和C++有一個?:操作符用於同樣目的。如下表達式
x > 0 ? 1 : -1 // Java或C++
等同於Scala表達式 if (x > 0) 1 else −1。不過,你不能在?:表達式中插入語句。Scala的if/else將在Java和C++中分開的兩個語法結構if/else和?:結合在了一起。
在Scala中,每個表達式都有一個類型。舉例來說,表達式 if (x > 0) 1 else −1的類型是Int,因為兩個分支的類型都是Int。混合類型表達式,比如:
if (x > 0) "positive" else -1
上述表達式的類型是兩個分支類型的公共超類型。在本例中,其中一個分支是java.lang.String,而另一個分支是Int。它們的公共超類型叫做Any。(詳細內容參見8.11節。)
如果else部分缺失了,比如:
if (x > 0) 1
那麼有可能if語句沒有輸出值。但是在Scala中,每個表達式都應該有某種值。這個問題的解決方案是引入一個Unit類,寫做()。不帶else的這個if語句等同於
if (x > 0) 1 else ()
你可以把()當做是表示「無有用值」的佔位符,將Unit當做Java或C++中的void。(從技術上講,void沒有值但是Unit有一個表示「無值」的值。如果你一定要深究的話,這就好比空的錢包和裡面有一張寫著「沒錢」的無面值鈔票的錢包之間的區別。)
說明:Scala沒有switch語句,不過它有一個強大得多的模式匹配機制,我們將在第14章中看到。在現階段,用一系列的if語句就好。
注意:REPL比起編譯器來更加「近視」——它在同一時間只能看到一行代碼。
舉例來說,當你鍵入如下代碼時:
if (x > 0) 1
else if (x == 0) 0 else -1
REPL會執行 if (x > 0) 1,然後顯示結果。之後它看到接下來的else關鍵字就會不知所措。
如果你想在else前換行的話,用花括弧:
if (x > 0) { 1
} else if (x == 0) 0 else -1
只有在REPL中才會有這個顧慮。在被編譯的程序中,解析器會找到下一行的else。
提示:如果你想在REPL中粘貼成塊的代碼,而又不想擔心REPL的近視問題,可以使用粘貼模式。鍵入:
:paste
把代碼塊粘貼進去,然後按下Ctrl+D。這樣REPL就會把代碼塊當做一個整體來分析。
語句終止
在Java和C++中,每個語句都以分號結束。而在Scala中——與JavaScript和其他腳本語言類似——行尾的位置不需要分號。同樣,在}、else以及類似的位置也不必寫分號,只要能夠從上下文明確地判斷出這里是語句的終止即可。
不過,如果你想在單行中寫下多個語句,就需要將它們以分號隔開。例如:
if (n > 0) { r = r * n; n -= 1 }
我們需要用分號將 r = r * n 和 n -= 1 隔開。由於有},在第二個語句之後並不需要寫分號。
如果你在寫較長的語句,需要分兩行來寫的話,就要確保第一行以一個不能用做語句結尾的符號結尾。通常來說一個比較好的選擇是操作符:
s = s0 + (v - v0) * t + // +告訴解析器這里不是語句的末尾
0.5 * (a - a0) * t * t
在實際編碼時,長表達式通常涉及函數或方法調用,如此一來你並不需要過分擔心——在左括弧(之後,編譯器直到看到匹配的)才會去推斷某處是否為語句結尾。
正因如此,Scala程序員們更傾向於使用Kernighan & Ritchie風格的花括弧:
if (n > 0) {
r = r * n
n -= 1
}
以{結束的行很清楚地表示了後面還有更多內容。
許多來自Java或C++的程序員一開始並不適應省去分號的做法。如果你傾向於使用分號,用就是了——它們沒啥壞處。
塊表達式和賦值
在Java或C++中,塊語句是一個包含於{ }中的語句序列。每當你需要在邏輯分支或循環中放置多個動作時,你都可以使用塊語句。
在Scala中,{ }塊包含一系列表達式,其結果也是一個表達式。塊中最後一個表達式的值就是塊的值。
這個特性對於那種對某個val的初始化需要分多步完成的情況很有用。例如,
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }
{ }塊的值取其最後一個表達式,在此處以粗體標出。變數dx和dy僅作為計算所需要的中間值,很乾凈地對程序其他部分而言不可見了。
在Scala中,賦值動作本身是沒有值的——或者,更嚴格地說,它們的值是Unit類型的。你應該還記得,Unit類型等同於Java和C++中的void,而這個類型只有一個值,寫做()。
一個以賦值語句結束的塊,比如
{ r = r * n; n -= 1}
的值是Unit類型的。這沒有問題,只是當我們定義函數時需要意識到這一點。
由於賦值語句的值是Unit類型的,別把它們串接在一起。
x = y = 1 // 別這樣做
y = 1的值是(),你幾乎不太可能想把一個Unit類型的值賦值給x。(與此相對應,在Java和C++中,賦值語句的值是被賦的那個值。在這些語言中,將賦值語句串接在一起是有意義的。)
輸入和輸出
如果要列印一個值,我們用print或println函數。後者在列印完內容後會追加一個換行符。舉例來說,
print("Answer: ")
println(42)
與下面的代碼輸出的內容相同:
println("Answer: " + 42)
另外,還有一個帶有C風格格式化字元串的printf函數:
printf("Hello, %s! You are %d years old.\n", "Fred", 42)
你可以用readLine函數從控制台讀取一行輸入。如果要讀取數字、Boolean或者是字元,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。與其他方法不同,readLine帶一個參數作為提示字元串:
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
printf("Hello, %s! Next year, your will be %d.\n", name, age + 1)
B. Scala 是一門怎樣的語言,具有哪些優勢
曾經有人問Java的創始人高斯林這樣一個問題,「除了Java語言以外,您現在還使用JVM平台上的哪種編程語言?」他毫不猶豫的說是Scala。
Scala到底是什麼?在目前眾多的JVM語言當中,Scala無疑是最引人注意的語言之一。Scala是一個靜態語言,更適合大型工程項目,Scala直接編譯成Java位元組碼,性能接近Java。Scala是一個多範式的語言,你可以混合使用函數式和面向對象編程,混合使用可變類和不變類,混合使用Actor和傳統的Java並發庫。
短短一個月的時間,Scala於本月沖進了TIOBE的前五十名。一個 Twitter 的開發人員說過,Scala 將會成為現代 Web2.0 的發起語言。LinkedIn 也用這種語言。同樣許多其他大的公司如 Sony Picture, EDF, SAP 也開始使用這種語言。為什麼Scala發展這么迅猛,可以獲得如此熱烈的社區支持。
曾冠東還表示,Scala不是Java的殺手,它無法取代Java的地位,也突破不了JVM的限制、Java實現不了的功能它也實現不了。我們可以將Scala形象的理解成大量語法糖的Java。
Scala 開發團隊發布了最新的2.9.2穩定版本,Scala 語言的特性有許多,例如高階函數和對象、抽象類型綁定,actor 使得函數在 Scala 中能是一個子類成為可能,Scala 中的設計模式使得面向對象和函數編程無縫結合。Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和 Scala 的 Actor 模型應用。它已經成功運用在電信行業。Spark 是一種可擴展的數據分析平台,它整合了內存計算的基元,因此,相對於 Hadoop 的集群存儲方法,它在性能方面更具優勢。Spark 是在 Scala 語言中實現的,並且利用了該語言,為數據處理提供了獨一無二的環境。Scala 編譯器可以生成位元組碼,直接運行在使用JVM上。該語言(它實際上代表了可擴展語言)被定義為可直接集成到語言中的簡單擴展。
Scala作為一門靜態語言,它的主要特性有哪些?
· Scala是面向對象的
Scala是一個純面向對象語言,在某種意義上來講所有數值都是對象。對象的類型和行為是由class和trait來描述的。Class的抽象可由子類化和一種靈活的基於mixin的組合機制(它可作為多重繼承的簡單替代方案)來擴展。
· Scala是函數式的
Scala還是一個函數式語言,在某種意義上來講所有函數都是數值。Scala為定義匿名函數提供了一種輕量級的語法,它支持高階(higher-order)函數、允許函數嵌套、支持局部套用(currying)。Scala的case類及其內置支持的模式匹配模型代數類型在許多函數式編程語言中都被使用。
· Scala是靜態類型的
Scala配備了一套富有表現力的類型系統,該抽象概念以一種安全的和一致的方式被使用。
· Scala是可擴展的
Scala的設計承認了實踐事實,領域特定應用開發通常需要領域特定語言擴展。Scala提供了一個獨特的語言組合機制,這可以更加容易地以類庫的形式增加新的語言結構:
任何方式可以被用作中綴(infix)或後綴(postfix)操作符閉包按照所期望的類型(目標類型)自動地被構造
兩者結合使用可方便地定義新語句,無需擴展語法,也無需使用類似宏的元編程工具。
· Scala可與Java和.NET進行互操作
Scala設計時就考慮了與流行編程環境良好交互,如Java 2運行時環境(JRE)和 .NET框架(CLR)。特別是與主流面向對象語言,如Java和C#盡量無縫交互。Scala有像Java和C#一樣的編譯模型(獨立編譯,動態裝載類),允許訪問成千上萬的高質量類庫。
在並發性方面,與 Scala 在 .NET 領域中的姐妹語言 F# 相似,Scala 是針對 「並發性問題」 的解決方案之一,讓開發人員能夠更加輕松地專注於問題的實質,而不用考慮並發編程的低級細節。Actor 編程模式讓高度並行應用程序的開發更加簡單。Scala把Erlang風格的基於actor的並發帶進了JVM。我們可以利用Scala的actor模型在JVM上設計具伸縮性的並發應用程序,以自動獲得多核心處理器帶來的優勢,而不必依照復雜的Java線程模型來編寫程序。Scala 為並發性提供了兩種級別的支持,這與其他與 Java 相關的主題極為類似:
首先,對底層庫的完全訪問(比如說 java.util.concurrent)以及對 「傳統」 Java 並發性語義的支持(比如說監控程序和wait()/notifyAll())。其次,這些基本機制上面有一個抽象層
Scala 提供了在穩定的高性能平台(Java 虛擬機)上生成的能力同時也是一門敏捷性語言。這一類型的語言也有其他的選擇,例如 Jython, JRuby, Groovy 和 Clojure, 但是這些都是運行在 JVM 上的動態類型語言。Open Class 的效果讓大家會覺得Scala是動態語言,但它是選擇隱式轉換來實現的,這也正好證明了Scala是靜態語言。隱式轉換(Implicit conversion)使 Scala 具有類型安全性,正如擴展方法(extension method)之於 C#,開放類(open class)之於 ruby。即:向未曾定義的類型添加方法(如字元串、列表、整數)。這是使得 Scala 符合 DSL(特定領域語言)模型的特性之一。
Scala結合了面向對象和函數編程的優勢,函數編程的一個好處就是你能夠像運用一個數據那樣運用函數,可以用來定義真正高層級的庫,或者去定義新的領域特殊語言(DSL)。
在談及Java與Scala的對比時,曾冠東表示,Scala能調用絕大部分的Java,而Java調用Scala獨有的東西會比較難。Java 擁有非常強的概念規范,因此任何一個 Java 程序之間具有非常多的相似之處,並且這樣能夠方便的進行程序員交替。但是 Scala 並沒有這樣的統一性,因為這是一門很有表現力的語言。現場曾冠東為我們演示了實際案例,如下圖所示:
正所謂,金無足赤,人無完人。Scala對二進制不兼容,語法也越來越復雜,不能突破Bytecode的限制、編譯速度有所緩慢。當它被廣泛用於單元測試、開發工具、Socket開發、以及面對多核挑戰的並發應用。總而言之,Scala是一種函數式面向對象語言,它融匯了許多前所未有的特性,而同時又運行於JVM之上。正如JRuby 創建者之一Charles Nutter 所宣稱的那樣Scala就是 Java 王位的合法繼承人。隨著開發者對Scala的興趣日增,以及越來越多的工具支持,無疑Scala語言將成為廣大軟體工程師手上一件必不可少的工具。更多精彩內容,請關注專題:http://www.it168.com/remen/qcon/
C. scala 什麼是隱式類
一、隱式類概念
所謂隱式類: 就是對類增加implicit 限定的類,其作用主要是對類的加強!
如:
implicit class ImpInt(tmp:Int){
def add(tmp2: Int) = tmp + tmp2
}123
class 前面的implicit,通過這個隱式類,就可以讓Int型數據具有 add 方法。
二、隱式類型實例
import scala.io.Sourceimport java.io.File/**
* 隱式類
* 其作用主要是對類的加強
*
* Created by wang on 2015/7/22.
*/object Implicit_Class {
import Context_Helper._ def main(args: Array[String]) {
println( 1.add(2)) //在當前作用域中尋找 將Int(1) 作為變數的類同時具有add 的方法的類,如有,則執行
println(new File("I:\aa.txt").read()) //在當前作用域中尋找 將File 作為變數的類同時具有read的方法的類,如有,則執行
}
}object Context_Helper{
implicit class ImpInt(tmp:Int){
def add(tmp2: Int) = tmp + tmp2
}
implicit class FileEnhance(file:File){
def read() = Source.fromFile(file.getPath).mkString
}
}
三、執行過程分析
當 1.add(2) 時,scala 編譯器不會立馬報錯,而檢查當前作用域有沒有 用implicit 修飾的,同時可以將Int作為參數的構造器,並且具有方法add的類,經過查找 發現 ImpInt 符合要求
利用隱式類 ImpInt 執行add 方法
D. 請問"Scala"是什麼
Scala軟體的特點集中體現在以財務管理為核心的的高度集成化與全球化。
Scala Global Series是Scala全集成的電子商務管理軟體,具有財務及資源管理、市場營銷管理、供應流程管理、服務及項目流程管理、製造及商務智能管理。
Scala Global Series是多語言的,並繼翻譯成30多種語言,在世界60多個國家銷售、安裝和提供技術支持和服務。
Scala軟體符合跨國公司對貨幣的要求。
Scala 5.1 - 最新版,它基於Microsoft SQL Server 7.0,提供超強的資料庫管理能力,為客戶提供增強的會計核算能力。Scala 5.1已通過BASDA(商業及會計軟體開發商協會)按其有關EMU多貨幣和三角式運算的高級要求認證。
Scala Global Series
本地化及將全球運作集成起來絕非易事。然而Scala Global Series的電子商務管理解決方案已為您打造好了一切。Scala的用戶能用自己的語言操作軟體,並同時用總部的語言和貨幣製作報表。不僅如此,Scala國際化的員工隊伍為您提供本地化的專業知識,以及全球性的技術支持服務。
詳細情況,請與當地Scala銷售代表聯系[email protected]
Scala Global Series是全集成的電子商務管理解決方案(eBMS),可管理眾多的商務流程,具有多語言能力(被譯成30多種語言),且全面支持跨國公司(其中當然包括歐元)對世界各貨幣的要求,它運行於Microsoft SQL Server 7.0之上, 具有出色的資料庫管理能力。支持Windows 2000。Scala Global Serie在世界60多個國家銷售、安裝和提供技術支持服務。
Scala Global Series具有按本地會計准則和國際公認會計准則US-GAAP並行呈報的能力。此外,Scala Global Series符合跨國公司對貨幣的要求。Scala將全球化標准融於本地化專長之中。
Scala深諳您的全球商務。
●財務
總分類帳;銷售分類帳;采購分類帳;合並
●物流
采購管理;銷售訂單;銷售訂單/開發票;統計;庫存管理;直接開發票;市場信息
●製造流程管理
製造流程管理;產品成品核算/實際成本;車間管理;基礎製造數據;主生產計劃;物料需求計劃;訂單計劃/生產活動管理
●服務
服務管理;項目管理
●人力資源
人事薪資
●系統實施
Signature
1. 總分類帳
會計核算是各公司運營的核心。Scala的總分類帳功能和靈活性體現了Scala其它商務管理模塊的通用性。十構面的會計核算體系貫穿各個模塊,它不僅能滿足不同的法規要求,還能滿足分析型會計核算的要求。您能從所用的任何構面呈報或查詢實際數值或預算值。加之Scala系統中內置的多貨幣多語言功能,使Scala成為當今全球及本地會計核算及商務管理領域中最強大的系統之一。
2. 銷售分類帳
要改善公司的現金流量,就要先建立有效的銷售分類帳。一個功能強大的銷售分類帳,不僅能更好地完成貨款回收,還能奠定銷售及市場營銷的基礎。Scala的銷售分類帳模塊是您實現財務及經營目標的有力工具。它包括開發票、付款、收款及呈報的常式,同時,它還能詳細地記錄相應的新幣值及記帳值。它提供的客戶原始數據及統計數據功能,能幫助您分析及細分市場。它具有的多貨幣及多語言靈活性,為國際化組織帶來突出的優勢。
3. 采購分類帳
Scala的采購分類帳模塊為您提供了全面的供應商信息及付款信息。它幫助您協調采購及審批作業,為您准備了豐富的付款方式,它簡化各種增值稅及營業稅的會計核算程序,更方便地製作各種法定會計報表。您可單獨使用該模塊,如與采購管理模塊及總分類帳模塊共同使用,更能發揮出其強大功效。如果您的業務復雜,采購分類帳的會計核算構面定能將它們輕松解決。
4. 合並
會計核算本身並不是最終目的。總分類帳中的數據需呈報出來。呈報時,可能需轉成另一種貨幣,或需與其他實體的數據合並。也許需用另一種貨幣的憑證重報憑證(如在高通漲的國家)或按不同的科目表及/或會計年度重報。最後,也許要將數年的經營結果,為了某個特定的呈報目的而合並在一起。
5.采購管理
采購常式有多種使用方法。無論您是何類型的企業,批發、零售還是製造,系統能完全適應您的業務方式。采購計劃、訂單處理、交貨及發票管理功能既可集中也可分散, 未結的采購訂單信息自動提供給Scala的各個後勤模塊。使您具有一個全面的采購訂單計劃環境,並有助於您削減整體采購成本。
6. 銷售訂單
Scala銷售訂單模塊為您提供了銷售及後勤的全部功能。通常,銷售是您的主要營業收入,銷售功能的靈活性和方便性影響著您的競爭性。Scala具有范圍廣泛的功能,支持銷售及分銷的各個階段。由於銷售訂單模塊與庫存管理、采購及製造管理模塊緊密集成,您可在銷售時就能確定製造或采購的明細,以確保按時交貨。
7. 銷售訂單/開發票
Scala銷售訂單模塊為您提供了銷售及後勤的全部功能。通常,銷售是您的主要營業收入,銷售功能的靈活性和方便性影響著您的競爭性。Scala具有范圍廣泛的功能,支持銷售及分銷的各個階段。由於銷售訂單模塊與庫存管理、采購及製造管理模塊緊密集成,您可在銷售時就能確定製造或采購的明細,以確保按時交貨。
8. 統計
Scala的統計模塊是一個極為有用的分析工具。與其他安裝的Scala模塊相連,統計模塊提供的信息遠較其他模塊內置的統計功能更詳盡。您能定製報表定義、創建模板,以及專用報表,如傭金報表、毛利分析或產品統計。除能列印輸出報表外,您還能保存在磁碟上、Excel文件中。統計模塊是Scala後勤模塊的有益補充。
9. 庫存管理
全面地管理您公司的物流狀態,從采購到交貨,需要出色的管理工具。庫存管理模塊可單獨使用,但如與采購訂單及銷售訂單模塊集成使用,則更能發揮它的強大功效。庫存管理的主要優點之一是它與各庫存物料的大量數據相連。重訂水平、安全庫存及短缺報告能幫助您有效地管理庫存,降低資本投入。庫存管理模塊也具有序列號及物料清單處理能力。為您提供靈活的批次處理能力、完整的跟蹤能力及豐富的呈報能力。
10. 直接開發票
當您需要一種簡捷有效的開發票常式時,Scala的直接開發票模塊就是您的有力工具。它能方便地創建非庫存物料、簡單服務、部門間或子公司間的發票。該模塊需銷售分類帳模塊,以使您有效管理付款和其它作業。直接開發票模塊與總分類帳集成後,具有10個會計核算構面,讓您能事後分析所有數據。直接開發票模塊使用方便,並與您的整個商務管理集成為一體。
11. 市場信息
一個高效的銷售組織需要出色的市場營銷工具。Scala的市場信息模塊收集您潛在及未來客戶的信息。能為您挖掘新的市場機會,它集成了當前的市場活動信息,客戶信息及供應商主文件中的信息。它允許您設計自己的資料庫,給予您工作的完全自由。
12. Scala製造流程管理
Scala的製造管理模塊是一個製造業資源計劃系統(MRP II)。它能滿足您對信息的最苛刻要求。它幫助您管理並控制整個製造過程。此外,它還能與財務模塊相連。共同創建一個功能強大的集成系統。由於它內置了豐富的功能,整個系統具有極高的靈活性,並能對製造過程中的各個活動提供各自不同的計劃和管理方法。Scala的製造管理模塊對重復型,以產定銷及以銷定產型生產過程均適用。該模塊支持准時生產、ISO 9000、EDI及CIM。
13. 產品成品核算/實際成本
掌握您的生產成本至關重要。成本核算模塊強化了產品加工的成本核算能力和分析潛在的隱含成本能力。成本核算模塊是您標準的成本計算工具,以及各訂單報價核算的工具。
14. 車間管理
生產能力瓶頸總是制約您產出的因素。生產部門計劃功能使您擁有一個有效的資源管理工具。
15. 基礎製造數據
基礎製造數據能創建並維護物料清單及製造物料的工藝路線。高質量的基礎數據是極為重要的,因為這些數據將成為各計算的基礎。其質量高低決定著製造計劃和管理有效性的高低。
16. 主生產計劃
主生產計劃的目的是,提前多達一年時間,根據預測和實際銷售量對物料和生產能力進行評估和准備。您能選擇主生產計劃中的產品,且主產計劃能評估不同的銷售預測,以確定對生產能力和物料的影響。
17. 物料需求計劃
物料需求計劃可使您調查未來對所購原材料及已加工部件的需求。例如,您能查看完成整個生產計劃(主生產計劃)、一組客戶訂單或一個客戶的訂單的物料需求。
18. 訂單計劃/生產活動管理
當您在生產資源中對員工、機器和工具作好充分定義後,以及在基礎MPC數據中對物料清單作了描述後,您便能充分利用這些資源使其充分發揮作用。生產活動管理有助於計劃、跟蹤和分析您的加工單, 您能手工輸入加工單,或用客戶訂單創建加工單,或從上層模塊輸入(比如,需求計劃模塊)。加工單放發後,其所需物料便被預留,相應生產部門的可用生產能力自動降低。
19.服務管理
人們認為服務是昂貴的。事實上,很多公司通過高效的服務,來自零備件及技術支持的收入高於其實際產品的銷售收入。Scala服務管理模塊為您提供了管理服務活動的全新境界,包括對物料及資源的完全管理。Scala服務管理模塊能管理上百名的技術服務人員,他們可以是分處不同地點(對於提供現場服務的公司)也可以是在室內提供服務與技術支持。有了Scala的服務管理模塊,您便能計劃和跟蹤各項服務活動。如與Scala的其他模塊集成使用,系統將更加靈活,並為您提供更大的發展空間。
20. 項目管理
在當今以客戶為導向的世界中,許多銷售活動已成為一個個項目。一套系統設施需要大量的材料及人力來完成。有些設備的交付需要協調分包商和設計公司。即使內部活動,例如改建倉庫也是一個項目。如果您的業務充滿了各種項目,將由誰控制預算,又將由誰跟蹤呢?Scala的項目管理模塊是您的集成化工具,它能評估、預算、計劃資源和跟蹤項目。其靈活的四層結構能幫助您隨時控制項目的進程,集中精力解決有問題的地方。
21. 人事薪資
人事薪資模塊適用於薪資計算周期中的各個階段,包括雇員的錄用與辭退、輸入或導入的計時單、根據不同的僱傭類型及不同的支付形式計算雇員的工資單、 列印工資單、生成會計報表、稅務報表、人力資源報表、審記表及各種管理日報表並自動創建總分類帳憑證。
22. Signature
Signature是我們實施Scala軟體的方法。它建立在團隊精神之上。它是我們在各行業、在世界各國實施眾多項目的知識和經驗結晶。Signature提供的標准工具和方法,能確保成功地實施系統。如您採用Scala軟體及我們的系統實施方法Signature,您能在數月內擁有一個可運行的全集成的商務管理系統。明確的共同目標 - 使新系統平穩地過渡是任何一個多用戶系統的基本前提。利用Signature,我們訓練有素的顧問將在實施過程中一步一步地指導您。
E. scala語言會取代java的嗎
不可能
scala復雜度僅僅次於c++
小眾
個人以為objectivec java delphi c# 都是單繼承多介面
沒本質區別
做gui開發很爽
做後端 創業公司更喜歡python nodejs這樣的多范型工具
出活快 效率高 跨平台
F. Scala代碼做模式匹配用到的符號是什麼
在Erlang中等號 = 表示一個模式匹配操作
在這兩種語言中,賦值語句都明確的定義為模式匹配,那麼scala中,所有的賦值語句是否都是模式匹配呢?
尤其scala可以說在函數式風格上與ML(及其家族)語言有某種血緣,在這一點上是否也與ML完全一致呢?
先分析一下上面的每條賦值語句:val a = 100 和 val A = 100是直觀且沒有歧義的。
G. 我為什麼想並且要學習Scala
為什麼學習函數式編程
在閱讀DDD巨著《Patterns, Principles, and Practices of Domain-Driven Design》的過程中,Scott在第5章提到了使用函數式編程語言配合貧血模型去實踐DDD的一種思路,這激發了我的無限遐想。
在軟體開發領域,我們已經擁有了許多的抽象方法論和大量的實現技術。但我個人認為,這一切歸根結底,都是人類思維在軟體開發領域的具體表達方式。而人類在認識和分析軟體所要解決的業務領域問題時,思考的內容不外乎由兩個部分組成:『業務流程』與『業務規則』。前者,回答了業務活動中先做什麼後做什麼的問題;後者,則回答了遇到什麼情況時應該怎麼做的問題。兩者結合後,得到我們需要的業務結果,或者叫作「實現業務目標」。
再想想目前學習和掌握的面向對象的一系列方法,又是如何將上述思維結果映射到軟體中去的呢?我認為是這樣的:
對於業務流程,我們將其表達為若干對象之間的合作,比如UML里序列圖的對象與消息,進而具化為具體的類及其職責,比如類及其若干業務方法。
對於業務規則,我們將其表達為若乾的判斷邏輯,比如UML流程圖里的判斷分支,進而具化為業務方法里的if-else語句,或者再復雜一點,表達為工廠、策略等設計模式的實際運用。
然後,我認為,對於復雜業務規則的梳理,可以象數學歸納法一樣進行演繹:假設一個函數y=f(x),給定x的定義域,確定y的值域。特別是在排列組合等方面的一些問題,也經常採用遞歸的方式來解決。所以,從這個角度講,函數式編程更貼近人類思維習慣,所以讓我自然而然地把目光轉向了它。
為什麼選擇Scala
在選擇具體的函數式編程語言時,我首先想到的是它最好是同時能支持面向對象編程的。因為即便LISP作為函數式編程語言的先祖,誕生已長達半個世紀,但單純的函數式編程語言與面向對象編程語言相比,在抽象領域概念、組合系統模塊、實現信息隱蔽等方面存在一定的差距,所以一直沒有成為軟體開發的主流。
信息隱蔽原理:在西安電子科大蔡希堯與陳平老師於1993年合作出版的《面向對象技術》一書中是這樣描述的:把需求和求解的方法分離;把相關信息——數據結構和演算法,集中在一個模塊之中,和其他模塊隔離,它們不能隨便訪問這個模塊內部的信息。
其次,由於我的語言路線是從Pascal → C → C++ → C#,所以我希望能選擇一種風格近似於C、強類型的函數式編程語言。在比較了F#、R、ErLang等幾種常見的函數式編程語言之後,我最終選擇了Scala。
Scala有何優勢
註:以下內容,節選翻譯或參考自《Programming in Scala》第1章、第3章,《Programming Scala》第6章,不算完整意義上的個人心得。
函數式編程的優勢
純的函數是沒有副作用的。無論何時何地,對於一個函數y=f(x),給定x必定得到y,不會因此產生二義結果。因此無論對於代碼測試還是並發,由於給定輸入必定得到預期輸出,而不受其他因素干擾,所以能有效減少Bug產生。
在函數式編程里,大量使用immutable的值。這意味著函數運算的結果總會創建一個新的實例,避免了通常並發環境下為防止數據共享沖突而採取的保護機制。盡管這需要額外的Copy操作,但Scala針對性地提供了高效的Copy實現,以及延遲計算等彌補機制。
函數是一等公民。函數作為表達式的一部分,可以藉由函數之間的嵌套、組合,實現復雜的判斷邏輯。
Scala語言本身的優勢
Scala是面向對象與函數式編程的混合語言,所以能有效結合二者的優點。
Scala屬於Java生態圈,可以在JVM平台上與Java一起編譯運行,所以許多Java的框架、工具都可以直接應用於Scala語言編寫的項目。
Scala視一切數據類型皆為對象,且支持閉包、lambda、by-name參數等特性,語法簡潔明快。
Scala使用Actor作為並發模型,與Akka框架自然契合。這是一種區別於傳統的、基於數據共享、以鎖為主要機制的並發模型,其特點在於以Actor為基本單位、沒有數據共享、基於消息傳遞實現Actor之間的協作,因此可以有效避免死鎖、減少競爭。
最後,如果有朝一日要轉向大數據領域,有Spark這樣的大型框架作為支撐。知乎:與 Hadoop 對比,如何看待 Spark 技術?
Scala對實踐DDD有何意義
說了那麼多,我的根本目的還是要將Scala作為實現DDD的主要武器。那麼試想一下,Scala在我們實現DDD的過程中能有哪些幫助呢?我暫且胡侃亂謅如下:
表示值對象、領域事件等元素更直觀。值對象、領域事件在DDD里都應該是immutable的,以往多採取POCO形式表示,現在改用Scala里的val以及case class表示,在語法層面就直觀地表明是不可修改的。
在類的方法層面實現CQRS時有語法支持。用Scala里的Function(返回類型為非Unit)對應CQRS里的Query,保證類的方法沒有副作用;用Procere(返回類型為Unit)對應CQRS里的Command,明確表明這一類方法會產生修改狀態等副作用。這同樣從語法層面就能對二者進行明確區分。
模式匹配豐富了函數操作。除了正則表達式,Scala形式多樣的模式匹配語法,為提取數據、完成數據分組聚合等運算、實現邏輯判斷提供了強大支持。比如定義def sum_count(ints:Seq[Int) = (ints.sum, ints.size)這樣一個函數後,我們可以這樣調用,以得到一個1至6的整數序列的整數值合計,及該序列的尺寸:val(sum, count) = sum_count(List(1, 2, 3, 4, 5, 6))。
為實現DSL提供有力支持。Scala自帶有解析框架,加上靈活的函數語法支持,要自己實現一套DSL及其相應的語法解析器將不再困難。比如在配置文件里這樣的一條配置語句,表示退休條件為年齡達到60周歲或者工齡屆滿30年:retire = (Age >= 60) || (ServiceLength >= 30)。以往的方式是自己寫一個語法解析器,把這條文本轉換成相應的Specification對象,然後扔給聚合去使用。現在有了Scala的幫助,就使編寫語法解析器這一環節的工作量大大減少。
合理的高階函數設計,使規則編寫得到簡化。比如打折規則、費用報銷規則,以往可能需要若干層的if-else嵌套,現在則將通過高階函數得到大幅簡化。對此,我強烈推薦劉光聰先生的視頻Refactoring to Functions,你會在劉先生的重構過程中發現高階函數的強大。
Actor為高效並發打下基礎。Actor
內部完全自治,自帶用於存儲消息的mailbox,與其他Actor只能通過消息進行交互,每個Actor都是並發的一個基本單位。這些特點,非常適合於
採取Event
Sourcing方式實現的DDD。每個聚合都好比一個Actor,在聚合內部始終保持數據的強一致性,而在聚合之間交互的領域事件則好比Actor之間
的消息,聚合之間藉由領域事件和Saga保證數據的最終一致性。
Trait成為AOP利器。Trait是Scala的另一大特色,它就象AOP織入一樣,能動態地給某個類型注入方法或者結構。比如配合類Circuit和with後面那4個Trait的定義,val circuit = new Circuit with Adders with Multiplexers with Flipflops with MultiCoreProcessors這樣就創建了一個帶有加法器、乘法器、觸發器和多核處理器的元件。
隱式實現為類型擴展提供支持。對應C#里的靜態擴展方法,Scala通過implicit為實現數據類型的方法擴展提供了便捷,成為Trait之外的另一個功能擴展手段。
能降低常見BDD框架的學習成本。盡管這一點可能比較牽強,但我正在努力摸索如何將BDD與DDD結合,而常見的Cucumber、Spock等一些BDD框架,其語法與Scala比較相近,所以我才有如此一說。
有哪些Scala學習資料
以下是我目前主要的學習資料,並衷心歡迎各位留言補充。
書籍
Programming in Scala:由Scala語言的設計師Martin Odersky編寫,循序漸進,配合了大量實例,入門必讀吧。
Programming Scala:視角與上面那本有點不一樣,沒有Scala語言基礎會感覺很困難,適合掌握了基本語法後溫故而知新。
在線文檔與視頻
Scala 官方文檔:Scala的官網,作為尋找資料的出發點是不錯的。
Scala 課堂:中文版的Scala基本語法在線課堂。
Scala Synatax Primer:由Jim McBeath整理的Scala語法概要,可以當字典用。
The Neophyte』s Guide to Scala:很出名的一個Scala入門指南,以Scala中的提取器Extractor作為實例開始。
Scala 初學指南:這是上面那本指南的中譯本。
Effective Scala:中文版的Scala高效編程
SBT中文入門指南:Scala Build Tool
社區
Scala 中文社區:不算活躍,原因你懂的。
Scala User:Scala入門者聚集地,沒有Stack Overflow那麼嚴格,但也需要點爬牆的身手。
SDK及IDE
Java SE:先裝這個
Scala SDK:再裝這個
SBT:然後裝這個
IntelliJ IDEA:最後裝這個,就能比較方便地開始Scala編程了
寫在最後
最
近讀的書很多也很雜,DDD、BDD、Scala、Cucumber以及Java基礎等等都有涉及,真恨不得一口吃成個大胖子。由於時間和精力有限,所以
現在知識消化很成問題,遲遲沒有進入學以致用的環節,只能先這樣紙上談兵了,好歹先把自己在學習過程中的一些思考、看到的好東西先記載下來,以備將來之
需。
H. 學習scala有哪些好的資源
為什麼學習函數式編程
在閱讀DDD巨著《Patterns, Principles, and Practices of Domain-Driven Design》的過程中,Scott在第5章提到了使用函數式編程語言配合貧血模型去實踐DDD的一種思路,這激發了我的無限遐想。
在開發領域,我們已經擁有了許多的抽象方法論和大量的實現技術。但我個人認為,這一切歸根結底,都是人類思維在開發領域的具體表達方式。而人類在認識和分析所要解決的業務領域問題時,思考的內容不外乎由兩個部分組成:『業務流程』與『業務規則』。前者,回答了業務活動中先做什麼後做什麼的問題;後者,則回答了遇到什麼情況時應該怎麼做的問題。兩者結合後,得到我們需要的業務結果,或者叫作「實現業務目標」。
再想想目前學習和掌握的面向對象的一系列方法,又是如何將上述思維結果映射到中去的呢?我認為是這樣的:
對於業務流程,我們將其表達為若干對象之間的合作,比如UML里序列圖的對象與消息,進而具化為具體的類及其職責,比如類及其若干業務方法。
對於業務規則,我們將其表達為若乾的判斷邏輯,比如UML流程圖里的判斷分支,進而具化為業務方法里的if-else語句,或者再復雜一點,表達為工廠、策略等設計模式的實際運用。
然後,我認為,對於復雜業務規則的梳理,可以象數學歸納法一樣進行演繹:假設一個函數y=f(x),給定x的定義域,確定y的值域。特別是在排列組合等方面的一些問題,也經常採用遞歸的方式來解決。所以,從這個角度講,函數式編程更貼近人類思維習慣,所以讓我自然而然地把目光轉向了它。
為什麼選擇Scala
在選擇具體的函數式編程語言時,我首先想到的是它最好是同時能支持面向對象編程的。因為即便LISP作為函數式編程語言的先祖,誕生已長達半個世紀,但單純的函數式編程語言與面向對象編程語言相比,在抽象領域概念、組合系統模塊、實現信息隱蔽等方面存在一定的差距,所以一直沒有成為開發的主流。
信息隱蔽原理:在西安電子科大蔡希堯與陳平老師於1993年合作出版的《面向對象技術》一書中是這樣描述的:把需求和求解的方法分離;把相關信息——數據結構和演算法,集中在一個模塊之中,和其他模塊隔離,它們不能隨便訪問這個模塊內部的信息。
其次,由於我的語言路線是從Pascal → C → C++ → C#,所以我希望能選擇一種風格近似於C、強類型的函數式編程語言。在比較了F#、R、ErLang等幾種常見的函數式編程語言之後,我最終選擇了Scala。
Scala有何優勢
註:以下內容,節選翻譯或參考自《Programming in Scala》第1章、第3章,《Programming Scala》第6章,不算完整意義上的個人心得。
函數式編程的優勢
純的函數是沒有副作用的。無論何時何地,對於一個函數y=f(x),給定x必定得到y,不會因此產生二義結果。因此無論對於代碼測試還是並發,由於給定輸入必定得到預期輸出,而不受其他因素干擾,所以能有效減少Bug產生。
在函數式編程里,大量使用immutable的值。這意味著函數運算的結果總會創建一個新的實例,避免了通常並發環境下為防止數據共享沖突而採取的保護機制。盡管這需要額外的Copy操作,但Scala針對性地提供了高效的Copy實現,以及延遲計算等彌補機制。
函數是一等公民。函數作為表達式的一部分,可以藉由函數之間的嵌套、組合,實現復雜的判斷邏輯。
Scala語言本身的優勢
Scala是面向對象與函數式編程的混合語言,所以能有效結合二者的優點。
Scala屬於Java生態圈,可以在JVM上與Java一起編譯運行,所以許多Java的框架、工具都可以直接應用於Scala語言編寫的項目。
Scala視一切數據類型皆為對象,且支持閉包、lambda、by-name參數等特性,語法簡潔明快。
Scala使用Actor作為並發模型,與Akka框架自然契合。這是一種區別於傳統的、基於數據共享、以鎖為主要機制的並發模型,其特點在於以Actor為基本單位、沒有數據共享、基於消息傳遞實現Actor之間的協作,因此可以有效避免死鎖、減少競爭。
最後,如果有朝一日要轉向大數據領域,有Spark這樣的大型框架作為支撐。知乎:與 Hadoop 對比,如何看待 Spark 技術?
Scala對實踐DDD有何意義
說了那麼多,我的根本目的還是要將Scala作為實現DDD的主要武器。那麼試想一下,Scala在我們實現DDD的過程中能有哪些幫助呢?我暫且胡侃亂謅如下:
表示值對象、領域事件等元素更直觀。值對象、領域事件在DDD里都應該是immutable的,以往多採取POCO形式表示,現在改用Scala里的val以及case class表示,在語法層面就直觀地表明是不可修改的。
在類的方法層面實現CQRS時有語法支持。用Scala里的Function(返回類型為非Unit)對應CQRS里uery,保證類的方法沒有副作用;用Procere(返回類型為Unit)對應CQRS里的Command,明確表明這一類方法會產生修改狀態等副作用。這同樣從語法層面就能對二者進行明確區分。
模式匹配豐富了函數操作。除了正則表達式,Scala形式多樣的模式匹配語法,為提取數據、完成數據分組聚合等運算、實現邏輯判斷提供了強大支持。比如定義def sum_count(ints:Seq[Int) = (ints.sum, ints.size)這樣一個函數後,我們可以這樣調用,以得到一個1至6的整數序列的整數值合計,及該序列的尺寸:val(sum, count) = sum_count(List(1, 2, 3, 4, 5, 6))。
為實現DSL提供有力支持。Scala自帶有解析框架,加上靈活的函數語法支持,要自己實現一套DSL及其相應的語法解析器將不再困難。比如在配置文件里這樣的一條配置語句,表示退休條件為年齡達到60周歲或者工齡屆滿30年:retire = (Age >= 60) || (ServiceLength >= 30)。以往的方式是自己寫一個語法解析器,把這條文本轉換成相應的Specification對象,然後扔給聚合去使用。現在有了Scala的幫助,就使編寫語法解析器這一環節的工作量大大減少。
合理的高階函數設計,使規則編寫得到簡化。比如規則、費用報銷規則,以往可能需要若干層的if-else嵌套,現在則將通過高階函數得到大幅簡化。對此,我強烈劉光聰先生的Refactoring to Functions,你會在劉先生的重構過程中發現高階函數的強大。
Actor為高效並發打下基礎。Actor
內部完全自治,自帶用於存儲消息的mailbox,與其他Actor只能通過消息進行交互,每個Actor都是並發的一個基本單位。這些特點,非常適合於
採取Event
Sourcing方式實現的DDD。每個聚合都好比一個Actor,在聚合內部始終保持數據的強一致性,而在聚合之間交互的領域事件則好比Actor之間
的消息,聚合之間藉由領域事件和Saga保證數據的最終一致性。
Trait成為AOP利器。Trait是Scala的另一大特色,它就象AOP織入一樣,能動態地給某個類型注入方法或者結構。比如配合類Circuit和with後面那4個Trait的定義,val circuit = new Circuit with Adders with Multiplexers with Flipflops with MultiCoreProcessors這樣就創建了一個帶有加法器、乘法器、觸發器和多核處理器的元件。
隱式實現為類型擴展提供支持。對應C#里的靜態擴展方法,Scala通過implicit為實現數據類型的方法擴展提供了便捷,成為Trait之外的另一個功能擴展手段。
能降低常見BDD框架的學習成本。盡管這一點可能比較牽強,但我正在努力摸索如何將BDD與DDD結合,而常見的Cucumber、Spock等一些BDD框架,其語法與Scala比較相近,所以我才有如此一說。
有哪些Scala學習資料
以下是我目前主要的學習資料,並衷心歡迎各位留言補充。
書籍
Programming in Scala:由Scala語言的設計師Martin Odersky編寫,循序漸進,配合了大量實例,入門必讀吧。
Programming Scala:視角與上面那本有點不一樣,沒有Scala語言基礎會感覺很困難,適合掌握了基本語法後溫故而知新。
在線文檔與
Scala 官方文檔:Scala的,作為尋找資料的出發點是不錯的。
Scala 課堂:中文版的Scala基本語法在線課堂。
Scala Synatax Primer:由Jim McBeath整理的Scala語法概要,可以當字典用。
The Neophyte』s Guide to Scala:很出名的一個Scala入門指南,以Scala中的提取器Extractor作為實例開始。
Scala 初學指南:這是上面那本指南的中譯本。
Effective Scala:中文版的Scala高效編程
SBT中文入門指南:Scala Build Tool
社區
Scala 中文社區:不算活躍,原因你懂的。
Scala User:Scala入門者聚集地,沒有Stack Overflow那麼嚴格,但也需要點爬牆的身手。
SDK及IDE
Java SE:先裝這個
Scala SDK:再裝這個
SBT:然後裝這個
IntelliJ IDEA:最後裝這個,就能比較方便地開始Scala編程了
寫在最後
最
近讀的書很多也很雜,DDD、BDD、Scala、Cucumber以及Java基礎等等都有涉及,真恨不得一口吃成個大胖子。由於時間和精力有限,所以
現在知識消化很成問題,遲遲沒有進入學以致用的環節,只能先這樣紙上談兵了,好歹先把自己在學習過程中的一些思考、看到的好東西先記載下來,以備將來之
需。
I. Spark平台下,scala比java更有優勢么
Scala到底是什麼?在目前眾多的JVM語言當中,Scala無疑是最引人注意的語言之一。Scala是一個靜態語言,更適合大型工程項目,Scala直接編譯成Java位元組碼,性能接近Java。Scala是一個多範式的語言,你可以混合使用函數式和面向對象編程,混合使用可變類和不變類,混合使用Actor和傳統的Java並發庫。
短短一個月的時間,Scala於本月沖進了TIOBE的前五十名。一個 Twitter 的開發人員說過,Scala 將會成為現代 Web2.0 的發起語言。LinkedIn 也用這種語言。同樣許多其他大的公司如 Sony Picture, EDF, SAP 也開始使用這種語言。為什麼Scala發展這么迅猛,可以獲得如此熱烈的社區支持。
曾冠東還表示,Scala不是Java的殺手,它無法取代Java的地位,也突破不了JVM的限制、Java實現不了的功能它也實現不了。我們可以將Scala形象的理解成大量語法糖的Java。
Scala 開發團隊發布了最新的2.9.2穩定版本,Scala 語言的特性有許多,例如高階函數和對象、抽象類型綁定,actor 使得函數在 Scala 中能是一個子類成為可能,Scala 中的設計模式使得面向對象和函數編程無縫結合。Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和 Scala 的 Actor 模型應用。它已經成功運用在電信行業。Spark 是一種可擴展的數據分析平台,它整合了內存計算的基元,因此,相對於 Hadoop 的集群存儲方法,它在性能方面更具優勢。Spark 是在 Scala 語言中實現的,並且利用了該語言,為數據處理提供了獨一無二的環境。Scala 編譯器可以生成位元組碼,直接運行在使用JVM上。該語言(它實際上代表了可擴展語言)被定義為可直接集成到語言中的簡單擴展。
Scala作為一門靜態語言,它的主要特性有哪些?
· Scala是面向對象的
Scala是一個純面向對象語言,在某種意義上來講所有數值都是對象。對象的類型和行為是由class和trait來描述的。Class的抽象可由子類化和一種靈活的基於mixin的組合機制(它可作為多重繼承的簡單替代方案)來擴展。
· Scala是函數式的
Scala還是一個函數式語言,在某種意義上來講所有函數都是數值。Scala為定義匿名函數提供了一種輕量級的語法,它支持高階(higher-order)函數、允許函數嵌套、支持局部套用(currying)。Scala的case類及其內置支持的模式匹配模型代數類型在許多函數式編程語言中都被使用。
· Scala是靜態類型的
Scala配備了一套富有表現力的類型系統,該抽象概念以一種安全的和一致的方式被使用。
· Scala是可擴展的
Scala的設計承認了實踐事實,領域特定應用開發通常需要領域特定語言擴展。Scala提供了一個獨特的語言組合機制,這可以更加容易地以類庫的形式增加新的語言結構:
任何方式可以被用作中綴(infix)或後綴(postfix)操作符閉包按照所期望的類型(目標類型)自動地被構造
兩者結合使用可方便地定義新語句,無需擴展語法,也無需使用類似宏的元編程工具。
· Scala可與Java和.NET進行互操作
Scala設計時就考慮了與流行編程環境良好交互,如Java 2運行時環境(JRE)和 .NET框架(CLR)。特別是與主流面向對象語言,如Java和C#盡量無縫交互。Scala有像Java和C#一樣的編譯模型(獨立編譯,動態裝載類),允許訪問成千上萬的高質量類庫。
在並發性方面,與 Scala 在 .NET 領域中的姐妹語言 F# 相似,Scala 是針對 「並發性問題」 的解決方案之一,讓開發人員能夠更加輕松地專注於問題的實質,而不用考慮並發編程的低級細節。Actor 編程模式讓高度並行應用程序的開發更加簡單。Scala把Erlang風格的基於actor的並發帶進了JVM。我們可以利用Scala的actor模型在JVM上設計具伸縮性的並發應用程序,以自動獲得多核心處理器帶來的優勢,而不必依照復雜的Java線程模型來編寫程序。Scala 為並發性提供了兩種級別的支持,這與其他與 Java 相關的主題極為類似:
首先,對底層庫的完全訪問(比如說 java.util.concurrent)以及對 「傳統」 Java 並發性語義的支持(比如說監控程序和wait()/notifyAll())。其次,這些基本機制上面有一個抽象層
Scala 提供了在穩定的高性能平台(Java 虛擬機)上生成的能力同時也是一門敏捷性語言。這一類型的語言也有其他的選擇,例如 Jython, JRuby, Groovy 和 Clojure, 但是這些都是運行在 JVM 上的動態類型語言。Open Class 的效果讓大家會覺得Scala是動態語言,但它是選擇隱式轉換來實現的,這也正好證明了Scala是靜態語言。隱式轉換(Implicit conversion)使 Scala 具有類型安全性,正如擴展方法(extension method)之於 C#,開放類(open class)之於 ruby。即:向未曾定義的類型添加方法(如字元串、列表、整數)。這是使得 Scala 符合 DSL(特定領域語言)模型的特性之一。
Scala結合了面向對象和函數編程的優勢,函數編程的一個好處就是你能夠像運用一個數據那樣運用函數,可以用來定義真正高層級的庫,或者去定義新的領域特殊語言(DSL)。
在談及Java與Scala的對比時,曾冠東表示,Scala能調用絕大部分的Java,而Java調用Scala獨有的東西會比較難。Java 擁有非常強的概念規范,因此任何一個 Java 程序之間具有非常多的相似之處,並且這樣能夠方便的進行程序員交替。但是 Scala 並沒有這樣的統一性,因為這是一門很有表現力的語言。現場曾冠東為我們演示了實際案例,如下圖所示:
正所謂,金無足赤,人無完人。Scala對二進制不兼容,語法也越來越復雜,不能突破Bytecode的限制、編譯速度有所緩慢。當它被廣泛用於單元測試、開發工具、Socket開發、以及面對多核挑戰的並發應用。總而言之,Scala是一種函數式面向對象語言,它融匯了許多前所未有的特性,而同時又運行於JVM之上。正如JRuby 創建者之一Charles Nutter 所宣稱的那樣Scala就是 Java 王位的合法繼承人。隨著開發者對Scala的興趣日增,以及越來越多的工具支持,無疑Scala語言將成為廣大軟體工程師手上一件必不可少的工具。
J. 如何通過雪球查詢股票之前的變動狀況
一. 雪球公司介紹
雪球 聰明的投資者都在這里。
web 1.0:新聞資訊,股價信息,K線圖
web 2.0:SNS 訂閱,分享,聊天
web 3.0:移動 APP,交易閉環
雪球現在員工數還不到100,其中技術人員佔一半。去年9月C輪融資4kw刀。我們現在的技術棧由下列組件組成:Java,Scala,Akka,Finagle,Nodejs,Docker ,Hadoop。我們當前是租用IDC機房自建私有雲,正在往「公私混合雲」方向發展。
在雪球上,用戶可以獲取滬深港美2w+股票的新聞信息,股價變化情況,也可以獲取債券,期貨,基金,比特幣,信託,理財,私募等等理財產品的各類信息,也可以關注雪球用戶建立的百萬組合,訂閱它們的實時調倉信息,還可以關注雪球大V。雪球當前有百萬日活躍用戶,每天有4億的API調用。App Store 財務免費榜第 18 名。歷史上曾排到財務第二,總免費榜第 19。
二. 雪球當前總體架構
作為一個典型的移動互聯網創業公司,雪球的總體架構也是非常典型的設計:
最上層是三個端:web端,android端和iOS端。流量比例大約為 2:4:4 。web3.0 的交易功能,在 web 端並不提供。
接入層以及下面的幾個層,都在我們的自建機房內部。雪球當前只部署了一個機房,還屬於單機房時代。正在進行「私有雲+公有雲混合部署」方案推進過程中。
我們當前使用 nodejs 作為 web 端模板引擎。nodejs 模塊與android 和 ios 的 app 模塊一起屬於大前端團隊負責。
再往下是位於 nginx 後面的 api 模塊。跟 linkedin 的 leo 和微博的 v4 一樣,雪球也有一個遺留的大一統系統,名字就叫 snowball 。最初,所有的邏輯都在 snowball 中實現的。後來慢慢的拆出去了很多 rpc 服務,再後來慢慢的拆出去了一些 http api 做成了獨立業務,但即便如此,snowball 仍然是雪球系統中最大的一個部署單元。
在需要性能的地方,我們使用 netty 搭建了一些獨立的介面,比如 quoto server,是用來提供開盤期間每秒一次的股價查詢服務,單機 qps 5w+,這個一會再細說;而 IM 服務,起初設計里是用來提供聊天服務,而現在,它最大的用途是提供一個可靠的 push 通道,提供 5w/s 的消息下發容量,這個也一會再細說。
雪球的服務化拆分及治理採用 twitter 開源的 finagle rpc 框架,並在上面進行了一些二次開發和定製。定製的功能主要集中在 access log 增強,和 fail fast,fail over 策略及降級開關等。 finagle 的實現比較復雜,debug 和二次開發的門檻較高,團隊內部對此也進行了一些討論。
雪球的業務比較復雜,在服務層中,大致可以分為幾類:第一類是web1.0,2.0 及基礎服務,我們稱為社區,包括用戶,帖子,新聞,股價,搜索等等,類比對象就是新浪財經門戶+微博;第二類是組合及推薦,主要提供股票投資策略的展示和建議,類比對象是美國的motif;第三類是通道,類似股市中的「支付寶」,接入多家券商,提供瞬間開戶,一鍵下單等等各種方便操作的功能。
雪球的業務實現中,包含很多非同步計算邏輯,比如搜索建索引,比如股票漲跌停發通知,比如組合收益計算等等,為此,我們設計了一個獨立的 Thread/Task 模塊,方便管理所有的後台計算任務。但隨著這些 task 越來越多,邏輯差異越來越大,一個統一的模塊並不是總是最佳的方案,所以,我們又把它拆成了兩大類:流式的,和批量式的。
雪球的推薦體系包括組合推薦「買什麼」和個性化推薦。我們最近正在重新梳理我們的大數據體系,這個感興趣的話可以單聊。
最下面是基礎設施層。雪球基礎設施層包括:redis,mysql,mq,zk,hdfs,以及容器 docker。
線上服務之外,我們的開發及後台設施也很典型:gitlab開發,jenkins打包,zabbix 監控系統向 openfalcon 遷移,redimine向confluence遷移,jira,以及內部開發的 skiing 後台管理系統。
** 三. 雪球架構優化歷程**
首先描述一下標題中的「股市動盪」定語修飾詞吧:
上證指數從年初的3000點半年時間漲到了5000多,6月12號達到最高點5200點,然後就急轉直下,最大單日跌幅 8.48%,一路跌回4000點以下。最近一周都在3900多徘徊。
3月最後一周,A股開戶 166萬戶,超過歷史最高紀錄 2007年5月第二周165萬戶。
4月份,證監會宣布A股支持單用戶開設多賬戶。
6月底,證金公司代表國家隊入場救市。
7月份,證監會宣布嚴打場外配資。
中國好聲音廣告第一晚,帶來超過平時峰值200倍的注冊量
挑戰:小 VS 大:
小:小公司的體量,團隊小,機器規模小
大:堪比大公司的業務線數量,業務復雜度,瞬間峰值沖擊
雪球的業務線 = 1個新浪財經 + 1 個微博 + 1 個 motif + 1 個大智慧/同花順。由於基數小,API調用瞬間峰值大約為平時峰值的 30+ 倍。
挑戰:快速增長,移動互聯網 + 金融,風口,A股大盤劇烈波動。
首先,在app端,在我們核心業務從 web2.0 sns 向 3.0 移動交易閉環進化的過程中,我們開發了一個自己的 hybrid 框架:本地原生框架,加離線 h5 頁面,以此來支撐我們的快速業務迭代。當前,雪球前端可以做到 2 周一個版本,且同時並行推進 3 個版本:一個在 app store 等待審核上線,一個在內測或公測,一個在開發。我們的前端架構師孟祥宇在今年的 wot 上有一個關於這方面的詳細分享,有興趣的可以稍後再深入了解。
雪球App實踐—構建靈活、可靠的Hybrid框架 http://wot.51cto.com/2015mobile/ http://down.51cto.com/data/2080769
另外,為了保障服務的可用性,我們做了一系列的「端到端服務質量監控」。感興趣的可以搜索我今年4月份在環信SM meetup上做的分享《移動時代端到端的穩定性保障》。其中在 app 端,我們採用了一種代價最小的數據傳輸方案:對用戶的網路流量,電池等額外消耗幾乎為0
每個請求里帶上前一個請求的結果
succ or fail : 1 char
失敗原因:0 - 1 char
請求介面編號: 1 char
請求耗時:2 - 3 char
其它:網路制式,etc
炒股的人大多都會盯盤:即在開盤期間,開著一個web頁面或者app,實時的看股價的上下跳動。說到「實時」,美股港股當前都是流式的數據推送,但國內的A股,基本上都是每隔一段時間給出一份系統中所有股票現價的一個快照。這個時間間隔,理論上是3秒,實際上一般都在5秒左右。 交了錢簽了合同,雪球作為合作方就可以從交易所下屬的數據公司那裡拿到數據了,然後提供給自己的用戶使用。
剛才介紹總體架構圖的時候有提到 quote server ,說到這是需要性能的地方。
業務場景是這樣的,雪球上個人主頁,開盤期間,每秒輪詢一次當前用戶關注的股票價格變動情況。在內部,所有的組合收益計算,每隔一段時間需要獲取一下當前所有股票的實時價格。起初同時在線用戶不多,這個介面就是一個部署在 snowball 中的普通介面,股價信息被實時寫入 redis ,讀取的時候就從 redis 中讀。後來,A股大漲,snowball 抗不住了。於是我們就做了一個典型的優化:獨立 server + 本地內存存儲。開盤期間每次數據更新後,數據接收組件主動去更新 quote server 內存中的數據。 後續進一步優化方案是將這個介面以及相關的處理邏輯都遷移到公有雲上去。
對於那些不盯盤的人,最實用的功能就是股價提醒了。在雪球上,你除了可以關注用戶,還可以關注股票。如果你關注的某隻股票漲了或跌了,我們都可以非常及時的通知你。雪球上熱門股票擁有超過 50w 粉絲(招商銀行,蘇寧雲商)粉絲可以設置:當這支股票漲幅或跌幅超過 x%(默認7%)時提醒我。曾經連續3天,每天超過1000股跌停,證監會開了一個會,於是接下來2天超過1000股漲停
原來做法:
股票漲(跌)x%,掃一遍粉絲列表,過濾出所有符合條件的粉絲,推送消息
新做法:
預先建立索引,開盤期間載入內存
1%:uid1,uid2
2%:uid3,uid4,uid5
3%:uid6
問題:有時候嫌太及時了:頻繁跌停,打開跌停,再跌停,再打開。。。的時候
內部線上記錄:
4台機器。
單條消息延時 99% 小於 30秒。
下一步優化目標:99% 小於 10 秒
IM 系統最初的設計目標是為雪球上的用戶提供一個聊天的功能:
送達率第一
雪球IM:Netty + 自定義網路協議
Akka : 每個在線client一個actor
推模式:client 在線情況下使用推模式
多端同步:單賬號多端可登錄,並保持各種狀態同步
移動互聯網時代,除了微信qq以外的所有IM,都轉型成了推送通道,核心指標變成了瞬間峰值性能。原有架構很多地方都不太合適了。
優化:
分配更多資源:推送賬號actor池
精簡業務邏輯:重復消息只存id,實時提醒內容不推歷史設備,不更新非活躍設備的session列表等等
本地緩存:拉黑等無法精簡的業務邏輯遷移到本地緩存
優化代碼:非同步加密存儲,去除不合理的 akka 使用
akka這個解釋一下:akka 有一個自己的 log adapter,內部使用一個 actor 來處理所有的 log event stream 。當瞬間峰值到來的時候,這個 event stream 一下子就堵了上百萬條 log ,導致 gc 顛簸非常嚴重。最後的解決辦法是,繞過 akka 的 log adapter,直接使用 logback 的 appender
線上記錄:5w/s (主動限速)的推送持續 3 分鍾,p99 性能指標無明顯變化
7月10號我們在中國好聲音上做了3期廣告。在廣告播出之前,我們針對廣告可能帶來的對系統的沖擊進行了壓力測試,主要是新用戶注冊模塊,當時預估廣告播出期間2小時新注冊100萬
壓測發現 DB 成為瓶頸:
昵稱檢測 cache miss > 40%
昵稱禁用詞 where like 模糊查詢
手機號是否注冊 cache miss > 80%
注冊新用戶:5 insert
優化:
redis store:昵稱,手機號
本地存儲:昵稱禁用詞
業務流程優化:DB insert 操作同步改非同步
下一步優化計劃:
將 sns 系統中所有的上行操作都改成類似的非同步模式
介面調用時中只更新緩存,而且主動設置5分鍾過期,然後寫一個消息到 mq 隊列,隊列處理程序拿到消息再做其它耗時操作。
為了支持失敗重試,需要將主要的資源操作步驟都做成冪等。
前置模塊HA:
合作方合規要求:業務單元部署到合作方內網,用戶的敏感數據不允許離開進程內存
業務本身要求:業務單元本身為有狀態服務,業務單元高可用
解決方案:
使用 Hazelcast In-Memory Data Grid 的 replication map 在多個 jvm 實例之間做數據同步。
java 啟動參數加上 -XX:+DisableAttachMechanism -XX:-UsePerfData,禁止 jstack,jmap 等等 jdk 工具連接
關於前置模塊,其實還有很多很奇葩的故事,鑒於時間關系,這里就不展開講了。以後有機會可以當笑話給大家講。
組合凈值計算性能優化:
一支股票可能在超過20萬個組合里(南車北車中車,暴風科技)
離線計算,存儲計算後的結果
股價3秒變一次,涉及到這支股票的所有組合理論上也需要每 3 秒重新計算一次
大家可能會問,為什麼不用戶請求時,實時計算呢?這是因為「組合凈值」中還包括分紅送配,分股,送股,拆股,合股,現金,紅利等等,業務太過復雜,開發初期經常需要調整計算邏輯,所以就設計成後台離線計算模式了。當前正在改造,將分紅送配邏輯做成離線計算,股價組成的凈值實時計算。介面請求是,將實時計算部分和離線計算部分合並成最終結果。
實際上,我們的計算邏輯是比較低效的:循環遍歷所有的組合,對每個組合,獲取所有的價值數據,然後計算。完成一遍循環後,立即開始下一輪循環。
優化:
分級:活躍用戶的活躍組合,其它組合。
批量:拉取當前所有股票的現價到 JVM 內存里,這一輪的所有組合計算都用這一份股價快照。
關於這個話題的更詳細內容,感興趣的可以參考雪球組合業務總監張岩楓在今年的 arch summit 深圳大會上的分享:構建高可用的雪球投資組合系統技術實踐 http://sz2015.archsummit.com/speakers/201825
最後,我們還做了一些通用的架構和性能優化,包括jdk升級到8,開發了一個基於 zookeeper 的 config center 和開關降級系統
四. 聊聊關於架構優化的一些總結和感想
在各種場合經常聽說的架構優化,一般都是優化某一個具體的業務模塊,將性能優化到極致。而在雪球,我們做的架構優化更多的是從問題出發,解決實際問題,解決到可以接受的程度即可。可能大家看起來會覺得很凌亂,而且每個事情單獨拎出來好像都不是什麼大事。
我們在對一個大服務做架構優化時,一般是往深入的本質進行挖掘;當我們面對一堆架構各異的小服務時,「架構優化」的含義其實是有一些不一樣的。大部分時候,我們並不需要(也沒有辦法)深入到小服務的最底層進行優化,而是去掉或者優化原來明顯不合理的地方就可以了。
在快速迭代的創業公司,我們可能不會針對某一個服務做很完善的架構設計和代碼實現,當出現各種問題時,也不會去追求極致的優化,而是以解決瓶頸問題為先。
即使我們經歷過一回將 snowball 拆分服務化的過程,但當我們重新上一個新的業務時,我們依然選擇將它做成一個大一統的服務。只是這一次,我們會提前定義好每個模塊的 service 介面,為以後可能的服務化鋪好路。
在創業公司里,重寫是不能接受的;大的重構,從時間和人力投入上看,一般也是無法承擔的。而「裱糊匠」式做法,哪裡有性能問題就加機器,加緩存,加資料庫,有可用性問題就加重試,加log,出故障就加流程,加測試,這也不是雪球團隊工作方式。我們一般都採用最小改動的方式,即,准確定義問題,定位問題根源,找到問題本質,制定最佳方案,以最小的改動代價,將問題解決到可接受的范圍內。
我們現在正在所有的地方強推3個數據指標:qps,p99,error rate。每個技術人員對自己負責的服務,一定要有最基本的數據指標意識。數字,是發現問題,定位根源,找到本質的最重要的依賴條件。沒有之一。
我們的原則:保持技術棧的一致性和簡單性,有節制的嘗試新技術,保持所有線上服務依賴的技術可控,簡單來說,能 hold 住。
能用cache的地方絕不用db,能非同步的地方,絕不同步。俗稱的:吃一塹,長一智。
特事特辦:業務在發展,需求在變化,實現方式也需要跟著變化。簡單的來說:遺留系統的優化,最佳方案就是砍需求,呵呵。