Weitere ähnliche Inhalte
Ähnlich wie コードの互換性と進化の両立 (20)
Mehr von Kohsuke Kawaguchi (20)
コードの互換性と進化の両立
- 9. 拡張ポイント
• コア
interface Animal {
void bark();
}
• プラグイン
@Extension
class Dog implements Animal {
void bark() { print(“ワン!”); }
}
©2013 CloudBees, Inc. All Rights Reserved
9
- 10. プラグインはコアをガンガン使う
Project p = …;
Future<Build> f = p.scheduleBuild();
Build b = f.get();
©2013 CloudBees, Inc. All Rights Reserved
10
- 12. ©2013 CloudBees, Inc. All Rights Reserved
mage © http://sfcitizen.com/blog/wp-content/uploads/2011/11/6302790910_c4eb865892_o-copy.jpg
12
- 13. フィールドの隠蔽
class Point {
int x,y;
}
class Point {
int getX();
int getY();
void setX(int);
void setY(int);
}
©2013 CloudBees, Inc. All Rights Reserved
13
- 16. インターフェース?抽象クラス?
abstract class Animal {
public abstract void bark();
public void bark(int times) {
for (int i=0; i<times; i++)
bark();
}
}
©2013 CloudBees, Inc. All Rights Reserved
16
- 17. ピンポンパターン
abstract class Animal {
@deprecated
public void bark() {
bark(1);
}
public void bark(int times) {
for (int i=0; i<times; i++)
bark();
}
}
©2013 CloudBees, Inc. All Rights Reserved
17
- 18. コンストラクタの肥大化
• 外部コードによる
サブクラス化を許可
したい
• GitSCMの例
public GitSCM(
String scmName,
List<UserRemoteConfig> userRemoteConfigs,
List<BranchSpec> branches,
UserMergeOptions userMergeOptions,
Boolean doGenerateSubmoduleConfigurations,
Collection<SubmoduleConfig> submoduleCfg,
boolean clean,
boolean wipeOutWorkspace,
BuildChooser buildChooser, GitRepositoryBrowser browser,
String gitTool,
boolean authorOrCommitter,
String relativeTargetDir,
String reference,
String excludedRegions,
String excludedUsers,
String localBranch,
boolean disableSubmodules,
boolean recursiveSubmodules,
boolean pruneBranches,
boolean remotePoll,
String gitConfigName,
String gitConfigEmail,
boolean skipTag,
String includedRegions,
boolean ignoreNotifyCommit,
boolean useShallowClone) {
©2013 CloudBees, Inc. All Rights Reserved
18
- 19. 我慢してセッター
class Foo {
void initXYZ(int x, int y, int z) { … }
void initABC(String a, String b, String c) { … }
}
©2013 CloudBees, Inc. All Rights Reserved
19
- 21. ©2013 CloudBees, Inc. All Rights Reserved
mage © http://sfcitizen.com/blog/wp-content/uploads/2011/11/6302790910_c4eb865892_o-copy.jpg
21
- 24. だ をつ 修 ア 俺
し く 飾ク俺
て る 子セ
! 道 をス
具
© 小学館
©2013 CloudBees, Inc. All Rights Reserved
24
- 28. バイナリ互換性を活用
interface Animal {
void bark();
}
class Dog implements Animal {
void bark() { print(“ワン”); }
}
Animal a = new Dog();
a.bark();
©2013 CloudBees, Inc. All Rights Reserved
28
- 29. バイナリ互換性を活用
interface Animal {
void bark(int n);
}
1. new Dog()でInstantiationError
class Dog implements Animal{
2. Dog→Animalのキャストで
ClassCastException
void bark() { print(“ワン”); }
3. a.bark(3)でAbstractMethodError
}
4. その他
Animal a = new Dog();
a.bark(3);
©2013 CloudBees, Inc. All Rights Reserved
29
- 32. ジェネリクス
class Foo<T extends X> implements Future<T> {
T get() { … }
}
class Foo<T extends Y> implements Future<T> {
T get() { … }
}
class Y extends X { … }
©2013 CloudBees, Inc. All Rights Reserved
32
- 35. 参照解決のルール
• メソッドへの参照
– クラス名:
– メソッド名:
– 戻り値型:
– パラメータ型:
java.lang.String
indexOf
int
java.lang.String,int
• 関連事項
– アクセス修飾子
– 例外
©2013 CloudBees, Inc. All Rights Reserved
35
- 36. コード進化のパターン
class Foo {
X get() { … }
}
class Foo {
Y get() { … }
}
class Y extends X { … }
©2013 CloudBees, Inc. All Rights Reserved
36
- 37. コード進化のパターン
class Foo {
X get() { … }
}
class Foo {
Y get() { … }
X get() { … }
}
©2013 CloudBees, Inc. All Rights Reserved
37
- 38. Bridge Method Injectorプロジェクト bit.ly/b-mi
class Foo {
@WithBridgeMethods(X.class)
Y get() { … }
}
class Foo {
Y get() { … }
X get() { Y y=get(); return y; }
}
©2013 CloudBees, Inc. All Rights Reserved
38
- 41. シェーディング / パッケージ・リネーミング
package org.jenkinsci.foo;
import org.acme.A;
import org.acme.B;
class Foo {
private List<A> a = …;
void bar() { new B().b(); }
}
©2013 CloudBees, Inc. All Rights Reserved
41
- 42. シェーディング / パッケージ・リネーミング
package org.jenkinsci.foo;
import hidden.org.acme.A;
import hidden.org.acme.B;
class Foo {
private List<A> a = …;
void bar() { new B().b(); }
}
©2013 CloudBees, Inc. All Rights Reserved
42
- 43. シェーディング / パッケージ・リネーミング
• 事後に
– maven-shade-plugin
• 事前に
– 予めリネームしたやつをjarにパッケージしてお
く
©2013 CloudBees, Inc. All Rights Reserved
43
- 45. ©2013 CloudBees, Inc. All Rights Reserved
mage © http://sfcitizen.com/blog/wp-content/uploads/2011/11/6302790910_c4eb865892_o-copy.jpg
45
- 46. ありがちなパターン
class Foo {
static final Foo INSTANCE = new Foo();
…
}
class Bar {
void bar() {
doSomethingWith(Foo.INSTANCE);
}
}
©2013 CloudBees, Inc. All Rights Reserved
46
- 47. 逆立ちしたって無理!
class Foo {
static Foo getInstance() { … }
}
class Bar {
void bar() {
doSomethingWith(Foo.INSTANCE);
}
}
©2013 CloudBees, Inc. All Rights Reserved
47
- 50. Bytecode Compatibility Transformer bit.ly/b-c-t
class Foo {
@AdaptField(name=“INSTANCE”)
static Foo getInstance() { … }
}
foo.jar
Foo.class
変換
定義
©2013 CloudBees, Inc. All Rights Reserved
50
- 51. Bytecode Compatibility Transformer bit.ly/b-c-t
• 実行時
– 変換定義 → byte[] transform(byte[] classFile)
独自class loader
foo.jar
bar.jar
変換
定義
©2013 CloudBees, Inc. All Rights Reserved
51
- 53. 思わぬ落とし穴
class Foo {
static Foo INSTANCE;
}
class Bar extends Foo {
void m() {
System.out.println(INSTANCE);
}
Bar#INSTANCE
}
©2013 CloudBees, Inc. All Rights Reserved
53
- 57. 一分で学ぶInvokedynamic
• Java7の新しい機能
• 実行時リンク
• 静的リンクと同じ速度
void foo() {
+リンカの為の追
int x = 5;
加情報
String y = “hello”;
Object o = intとstringからObjectを返す何か(x,y)
return o;
}
+リンカの名前
©2013 CloudBees, Inc. All Rights Reserved
57
- 59. ビルド時にinvokedynamicに置き換え
new Project()
class Foo {
Project.scheduleBuild()
void foo() {
Project p = [void→Project](this);
Future<Build> f = [Project→Future] (p);
Build b = [Future → Build](f);
…
Future.get()
}
}
©2013 CloudBees, Inc. All Rights Reserved
59
- 60. 実行時に適宜書き換え
class Foo {
void foo() {
Project p = Project.create();
Future<Build> f = p.scheduleBuild(0);
Build b = f.value;
…
}
}
©2013 CloudBees, Inc. All Rights Reserved
60
Hinweis der Redaktion
- 本当に実行するまでわからない
- Jenkinsでも似たような問題に何度も遭遇した
- でも進化しないといけない、どうするか。
- コードの進化と互換性の狭間の苦しみからどう解脱するか。徐々に蓄積してきたノウハウ・ツールを大公開
- コンパイルはできないが動く。ソースコード上の規則とバイナリ上の規則の違い。
- プログラムを書き換えればいいじゃんか