どっかにあるかもしれんね。
groovy style guide in ja
概要
http://groovy-lang.org/style-guide.html
の雑な和訳をしたい
1. No セミコロン
C/C++/C#/Javaのバックグラウンドを持つ人はよくセミコロンを使っていたし、Groovyも99% javaのシンタックスをサポートしているので使用できる。がgroovyでは削除できるし
慣例的なそれを削除できる。
2. Returnはオプションです
groovyでは関数のbodyの最後のステートメントはreturnがなくとも戻り値として評価される。特に短い関数やクロージャは削除するのが良いだろう
ただ下記の例のような場合最後のステートメントの前に改行をするか、returnをつけるとより見やすくなるだろう。
def props() {
def m1 = [a: 1, b: 2]
m2 = m1.findAll { k, v -> v % 2 == 0 }
m2.c = 3
m2
}
注意しておくべきなのは、def
で定義された場合で、最後のステートメントが戻り値として返ってくるので、voidかその他のtypeのような特定の方を使ったほうが良いだろう。
後if/else
,try/catch
のようなステートメントも戻り値を返します。下記のサンプルコードを参考にしてください。
def foo(n) {
if(n == 1) {
"Roshan"
} else {
"Dawrani"
}
}
assert foo(1) == "Roshan"
assert foo(2) == "Dawrani"
3. Defとtype
def
とtype
両方共使えるけどその場合、def
って余分だからdef
かtype
どちらかを使うようにして。
goorvyにおけるdef
とはObject
です。
(そのためdefで定義した関数はなんでも戻り値を取れるしなんでも引数をとれる)
defを使う場合、こう書かずに
void doSomething(def param1, def param2) { }
こう書きましょう
void doSomething(param1, param2) { }
でも、最後で言うけど、型は指定したほうが良いよ。IDEとかあるでしょ。
あとコンストラクタのdefは余分だよ
4. 何もしなければPublic
Groovyは基本publicの修飾子をつけているので、publicにしたければ何も指定しなくても良いよ。
packageスコープを気にするかもしれないけど、デフォルトではgroovyはサポートしてないからpublicを省略できる。
まあでも使いたかったらこうすればいい
class Server {
@PackageScope Cluster cluster
}
5. 括弧を省略
トップレベルの括弧は省略できる。(するべきとは書いていないような気がする)
下記のようなクロージャの場合は三番目を選択するべき
list.each( { println it } )
list.each(){ println it }
list.each { println it }
幾つかのケースで括弧は必要で,ネスト内で関数を呼ぶケースや、引数を呼ばずに関数を呼ぶケースなどが該当する
def foo(n) { n }
def bar() { 1 }
println foo 1 // won't work
def m = bar // won't work
6. 第一級オブジェクトとしてのクラス
groovyでは.class
は必要ない。
connection.doPost(BASE_URI + "/modify.hqu", params, ResourcesResponse.class)
ではなく
connection.doPost("${BASE_URI}/modify.hqu", params, ResourcesResponse)
こうかける
7. GettersとSetters
Groovyの場合gettersとsettersはpropertyと呼ぶ。javaのようにgetters/settersを呼ぶよりも、下のように呼ぶほうが良い
resourceGroup.getResourcePrototype().getName() == SERVER_TYPE_NAME
resourceGroup.resourcePrototype.name == SERVER_TYPE_NAME
resourcePrototype.setName("something")
resourcePrototype.name = "something"
修飾子が無い変数に対してGroovyコンパイラはprivate変数とgetterとsetterを生成してくれる。
8. beans(class)の初期化
下記のようなclassに対して
class Server {
String name
Cluster cluster
}
下のように初期化せずに
def server = new Server()
server.name = "Obelix"
server.cluster = aCluster
こんな感じで初期化しよう
def server = new Server(name: "Obelix", cluster: aCluster)
9. 同じbean上繰り返し操作はwith()を使おう
server.name = application.name
server.status = status
server.sessionCount = 3
server.start()
server.stop()
serverがいっぱい出てきてダサいので
server.with {
name = application.name
status = status
sessionCount = 3
start()
stop()
}
こう書こうぜ
10. Equalsと==
==
はGroovyのis()
でGroovyの==
はequals()
よりもイケてる。
Objectの比較は ==
より a.is(b)
を使うべき
だが、equals()
を使用して比較している場合Groovyの==
を使ったほうが良い。
なぜならNullPointerException
に対応してくれるからだ。
status != null && status.equals(ControlConstants.STATUS_COMPLETED)
よりも
status == ControlConstants.STATUS_COMPLETED
こちらのほうが良いだろう
11.GStrings
Stringの連結とか改行について
throw new Exception("Unable to convert resource: " + resource)
とかけるところを
GStringだと、
throw new Exception("Unable to convert resource: $resource")
もかける。
こちらのほうが記述するのに楽じゃないだろうか。
遅延評価も${-> resource}
のようにかけるし、Stringであることを明確にしたければtoString()
と書くこともできる。
下記に遅延評価の例を書く
int i = 3
def s1 = "i's value is: ${i}"
def s2 = "i's value is: ${-> i}"
i++
assert s1 == "i's value is: 3" // eagerly evaluated, takes the value on creation
assert s2 == "i's value is: 4" // lazily evaluated, takes the new value into account
また継続文字として\
が従来通り使えるが、triple quotesによてmultiline stringsも使用することできる。
また正規表現についてスラッシュが使えるのでそちらの方を使うべきである
assert "foooo/baaaaar" ==~ /fo+\/ba+r/
最後に文字列定数はsingle quotedを使用するべきである。
double quoteは明確にstring interpolationの場合使用するべき
single quoteとdouble quoteの違い
sigle quote: java Stringsを常に作成(${x}が使えない?)
doudle quote: interpolated variables(多分${x}みたいなやつのこと)がある場合GStringを作成して,それ以外はjava Stringsを作成する
12. データ構築のためのNative syntax
Groovyはlist,maps,regex,rangesのnative syntax構築方を提供しています。(訳自信なし)
下記のように構築できるので参考にして
def list = [1, 4, 6, 9]
// by default, keys are Strings, no need to quote them
// you can wrap keys with () like [(variableStateAcronym): stateName] to insert a variable or object as a key.
def map = [CA: 'California', MI: 'Michigan']
def range = 10..20
def pattern = ~/fo*/
// equivalent to add()
list << 5
// call contains()
assert 4 in list
assert 5 in list
assert 15 in range
// subscript notation
assert list[1] == 4
// add a new key value pair
map << [WA: 'Washington']
// subscript notation
assert map['CA'] == 'California'
// property notation
assert map.WA == 'Washington'
// matches() strings against patterns
assert 'foo' ==~ pattern
13. The Groovy Development Kit
色々なデータ構造をいじるためにGroovyではいろいろなmethodを提供している。
基本的なデータ構造をいじるときにGDK APIドキュメントを参考にすると良いかも。
(提案だと思います。)
14. switchのちから
GroovyのswitchはCっぽい言語のようなプリミティブ型しか許可されないswitchよりも強い。
Groovyのswitchは数多の型を許容する。
def x = 1.23
def result = ""
switch (x) {
case "foo": result = "found foo"
// lets fall through
case "bar": result += "bar"
case [4, 5, 6, 'inList']:
result = "list"
break
case 12..30:
result = "range"
break
case Integer:
result = "integer"
break
case Number:
result = "number"
break
case { it > 3 }:
result = "number > 3"
break
default: result = "default"
}
assert result == "number"
isCase()
を使えば型の一致も確認できる。
15. 別名でImportできる
同じ名前のライブラリをインポートするとき別名を指定できるようになった。
import java.util.List as UtilList
import java.awt.List as AwtList
import javax.swing.WindowConstants as WC
UtilList list1 = [WC.EXIT_ON_CLOSE]
assert list1.size() instanceof Integer
def list2 = new AwtList()
assert list2.size() instanceof java.awt.Dimension
// これもできるぞ
import static java.lang.Math.abs as mabs
assert mabs(-4) == 4
16. Groovy Truth
null
,void
,zero
そしてemptyはfalse
と評価され、それ以外はtrue
if (name != null && name.length > 0) {}
よりも
if (name) {}
こうかこう
17. 安全なGraph navigation
javaの場合、複雑なifを書く場合nulをチェックするために下記のようなコードを書いていたかも
if (order != null) {
if (order.getCustomer() != null) {
if (order.getCustomer().getAddress() != null) {
System.out.println(order.getCustomer().getAddress());
}
}
}
?.
を使えばすごくシンプルになる。
println order?.customer?.address
この場合NullPointerException
を投げずに戻りとしてnull
が返される。
18. Assert
javaの場合assertを実施する場合有効化する必要があったが、Groovyの場合常に確認する。
def check(String name) {
// name non-null and non-empty according to Groovy Truth
assert name
// safe navigation + Groovy Truth to check
assert name?.size() > 3
}
19. エルビス演算子
が使えます。(javaでもjava8から使えるようになったらしい。)
def result = name ?: "Unknown"
この場合nameがtrueの場合はnameを代入、falseの場合"Unknown"が代入される
20. 想定していない例外をCatchする場合
try {
// ...
} catch (Exception t) {
// something bad happens
}
ではなく
try {
// ...
} catch (any) {
// something bad happens
}
こうかこう
注意
上記の書き方は全てのExceptionは補足できるが、Throwableで投げれるものは受け取れないのでThrowableなオブジェクトを受け取るには、明示的にThrowable オブジェクトをキャッチしよう。
21. 型についてのアドバイス
Groovyは強い型指定するか、defを使うかを決めさせる。
単純なルールとして他人が使うようなAPIは型指定をするべき。(型が違う引数を渡されるとか、良いドキュメントを作成できるし)
自分だけが使用するようなprivate関数は好きにしなさい。
誤字脱字、誤訳は多分いっぱいあるので雰囲気だけぜひ掴んでほしい