C# code refactoring with Scope Functions
by
Masaya Yashiro
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
スコープファンクションでコード の見通しを改善する 2018/09/26 Gotanda.unity #8 @yashims85
Slide 2
Slide 2 text
誰 ● Twitter: @yashims85 ● 会社: モバイルファクトリー@ 五反田 ● Unity: 趣味でさわってる ● 最近気になる言語: Rust ● 緩募: 継続するダイエット
Slide 3
Slide 3 text
質問です 皆さんはイケてないな。。。 と思いながら、そんなもんだろうと諦めて コードを書いていることはありませんか?
Slide 4
Slide 4 text
● PBXProjectのプロパティ ● 関数に外出しするほどではないちょっとし た計算 ● Builder, Factoryパターンを採用するほど でもないちょっとした手順 ● 大量のnullチェックもしくは ?. 地獄 私がイケてなぁと思いながらコードを書 いているとき
Slide 5
Slide 5 text
スコープファンクション もしかしたらスコープ ファンクションがそれ らの悩みを一助にな るかもしれません。
Slide 6
Slide 6 text
スコープファンクション ● Kotlinの文脈で登場する ● (基本的に)引数にLambdaを1つとって、そ の中で自己参照をする ● C#のExtensionで作った関数のように全部 のObjectに生えてる
Slide 7
Slide 7 text
なるほど
Slide 8
Slide 8 text
いくつか移植してみた CSharpScopeExtensions: https://github.com/yashims/CSharpScop eExtensions ここでスター欲しいって言えば 優しい人がしてくれるって聞きました
Slide 9
Slide 9 text
導入方法 ● releaseにunitypackageがおいてあるので ご自由にお使い下さい ● もしくは簡単なのでコピペ
Slide 10
Slide 10 text
実際の実装 今回は諸般の事情により2つだけ紹介
Slide 11
Slide 11 text
Also
Slide 12
Slide 12 text
Also public static T Also(this T self, Action action) { action(self); return self; }
Slide 13
Slide 13 text
Also public static T Also(this T self, Action action) { action(self); return self; } ジェネリクスのExtensionなので、どの Objectからも呼び出せる
Slide 14
Slide 14 text
Also public static T Also(this T self, Action action) { action(self); return self; } 自分自身を引数に取る Actionに自分 自身を渡す
Slide 15
Slide 15 text
Also public static T Also(this T self, Action action) { action(self); return self; } 戻り値として自分を返す。
Slide 16
Slide 16 text
Let
Slide 17
Slide 17 text
Let public static R Let(this T self, Func action) { return action(self); }
Slide 18
Slide 18 text
Let public static R Let(this T self, Func action) { return action(self); } ジェネリクスのExtensionなので、どの Objectからも呼び出せる
Slide 19
Slide 19 text
Let public static R Let(this T self, Func action) { return action(self); } 自分自身をFuncに渡し、Funcの戻り 値がLetの戻り値となる。
Slide 20
Slide 20 text
それがどしたの
Slide 21
Slide 21 text
実際の使用感をみてみる
Slide 22
Slide 22 text
Alsoの使い所 例えばインスタンスのプロパティ設 定
Slide 23
Slide 23 text
Alsoを使わない void Start() { Transform t1 = GetComponent(); Quaternion q1 = new Quaternion(); q1.x = 0; q1.y = 0; q1.x = 0; t1.rotation = q1; }
Slide 24
Slide 24 text
Alsoを使う void Start() { Transform t2 = GetComponent().Also((it) => { it.rotation = new Quaternion().Also((that) => { that.x = 0; that.y = 0; that.z = 0; }); }); }
Slide 25
Slide 25 text
Alsoを使う ● Start()のスコープを一時変数で汚さない ● いくつかの処理が記述されてるようならコレはメリット ● 引数の変数名を`it`等の代名詞にしておけば、何に対して の処理かが明確になり、それ以外に言及するコードを避 けられる ● コレを使えばPBXProjectの設定が超絶スッキリする
Slide 26
Slide 26 text
Letの使い所 例えばLINQのSelectの様に使う
Slide 27
Slide 27 text
Letを使わない Transform t = GetComponent(); float distanceX = t.parent.transform.localPosition.x + t.localPosition.x;
Slide 28
Slide 28 text
Letを使う float distanceX = GetComponent().Let((it) => { return it.parent.transform.localPosition.x + it.localPosition.x; });
Slide 29
Slide 29 text
Letを使う ● LINQやRxのSelectと同じイメージで、Lambda内で変形を 行える ● Alsoと同じく、一時変数でスコープを汚さない
Slide 30
Slide 30 text
Letの使い所 例えばC#6.xのnullableの unwrapping
Slide 31
Slide 31 text
Letを使わない string say(string comment) { return comment != null ? $"I said: {comment}" : ""; }
Slide 32
Slide 32 text
Letを使う string say(string comment) { return comment?.Let(it => $"I said: {it}") ?? ""; }
Slide 33
Slide 33 text
Letを使う ● C#でのnull条件演算子「?.」は、nullチェックして、非null であればローカル変数に格納するのと同義 ● それをLetの引数で受け取っているので、Letの中では Null安全な変数を自由に使える
Slide 34
Slide 34 text
できなかったこと
Slide 35
Slide 35 text
できなかったこと ● Lambdaの中でthisコンテキストを変える ● KotlinではLambdaの中ではthisがそれ自身になるス コープファンクションがある(例: Apply)
Slide 36
Slide 36 text
Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; }
Slide 37
Slide 37 text
Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } ジェネリクスのExtensionなので、どの Objectからも呼び出せる
Slide 38
Slide 38 text
Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } TをthisとしてActionを呼び出す
Slide 39
Slide 39 text
Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } 自分自身を返す
Slide 40
Slide 40 text
Applyを使えたら void Start() { Transform t2 = GetComponent().Apply(() => { this.rotation = new Quaternion().Apply(() => { x = 0; y = 0; z = 0; }); }); } this以外の事について言及する余地 が無くなる
Slide 41
Slide 41 text
まとめ
Slide 42
Slide 42 text
まとめ ● ScopeFunctionを使うと一時変数が減ら せ、コードの見通しが良くなる ● ブロックで区切られることで、何について述 べられているコードかが簡潔になる ● Lambdaの中でthisを変える方法があった ら誰か教えてください
Slide 43
Slide 43 text
ありがとうございました