狠狠撸

狠狠撸Share a Scribd company logo
第3回 ありえる社内勉強会
 「いわががのLombok」
お前だれよ?


    twitter: @kiris

    いわなが?いわがが?
Lombokって何?


    http://projectlombok.org   
                                   created by

    Javaの冗長性を排除する為                 
                                       Roel Spilker
    のライブラリ

    「赤唐辛子」の意味

    v0.10.4

    MIT license                    
                                       Reinier Zwitserloot
Javaの冗長性って?


        こういうのとか


    class Data {
      private int value;

        public int getValue() {
          return value;
        }
        public void setValue(int value) {
          this.value = value;
        }
    }
Javaの冗長性って?


     後、こういうのとか…

    InputStream in = new InputStream(args[0]);
    try {
      ...
    } finally {
      If (in != null) in.close();
    }
Javaの冗長性って?


     他にも、こういうのとか…

    Map<String, List<String>> map =
          new HashMap<String, List<String>>();

    ...

    for(Map.Entry<String, List<String>> entry : map) {
      ...
    }
Javaの冗長性って?


     ……


    class MyClass {
      private static Log log =
          LogFactory.getLog(MyClass.class);

     private final String name;

     public MyClass(String name) {
       if (name == null) {
         throw new NullPointerException();
       }
       this.name = name;
     }

     @Override public int toString() {
       return “MyClass(name=”+ this.name +“)”;
     }
Javaの冗長性って?

 




         こうならない為のLombok!
         続きはWebで!!
冗長の何がいけないの?


    生産性が下がる

    コード量が増えて読みづらくなる

    バグが入り込む可能性がある

    死にたくなる
尝辞尘产辞办の导入
Lombokを入手する


    Download lombok.jar
    
        http://projectlombok.org/download.html

    Maven or Ivy
    
        http://projectlombok.org/mavenrepo/index.html
Lombokを使う


    Javac
    
        Classpathに追加

    GWT
    
        java -javaagent:lombok.jar=ECJ

    Play Framework
    
        https://github.com/aaronfreeman/play-lombok#readme

    ECJ
    
        java -javaagent:lombok.jar=ECJ 
        -Xbootclasspath/p:lombok.jar -jar ecj.jar -cp lombok.jar
LombokをIDEでも使う


    Eclipse, NetBeans なんかに対応
    
        IDEA IntelliJはまだ未対応

    java -jar lombok.jar
尝辞尘产辞办を试してみる
@Data


    import lombok.Data
    public @Data class DataExample {
      private final String name;
      private int count;
      private List<Object> list;
    }


    @Dataの主な機能
     
         全てのフィールドのgetter / setter の生成
     
         toString, equals, hashCodeの生成
     
         finalフィールドを引数にしたコンストラクタの生成
結果の確認(delombok)


    変換後のコードを出力
    
        java -jar lombok.jar delombok -p ${src}

    ファイルとして保存
    
        java -jar lombok.jar delombok -d ${output} ${src}

    Ant
    
        <delombok verbose="true" encoding="UTF-8" to="$
        {output}" from="${src}" />

    Maven
    
        https://github.com/awhitford/lombok.maven
@Data(変換後)


public class DataExample {
  private final String name;
  private int count;
  private List<Object> list;

    public DataExample(String name) {
      this.name = name;
    }

    public String getName() { return name; }
    public int getCount() { return count; }
    public void setCount(int count) { this.count = count; }
    @Override public String toString() { ... }
    @Override public boolean equals(Object other) { ... }
    @Override public int hashCode() { … }
}
Eclipseからも即時反映


    その场でアウトラインや补完候补に表示されます
他の機能

   @Getter / @Setter
   @Getter(lazy=true)
   @ToString
   @EqualsAndHashCode
   @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
   @Data
   @Cleanup
   @Synchronized
   @SneakyThrows
   @Log
   val
   @Delegate
                                           http://projectlombok.org/features/index.html
@Getter / @Setter


    Getter / Setterの自動生成

    @Dataよりも優先


    public class GetterSetterExample {
      @Getter @Setter private String name;
      @Getter(AccessLevel.PROTECTED) private int age;
    }
@Getter / @Setter(変換後)


    Getter / Setterの自動生成

    @Dataよりも優先


    public class GetterSetterExample {
      private String name;
      private int age;

        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        protected int getAge() { return age; }
    }
@Getter(lazy=true)


    いわゆるメモ化

    サブルーチン(関数)呼び出しの結果を保持し、再利用するこ
    とで、そのサブルーチンの呼び出し毎の再計算を防ぐ
    public class GetterLazyExample {
      @Getter(lazy=true) private final double[] cached = expensive();

        private double[] expensive() { ... }
    }
@Getter(lazy=true)(変換後)


    いわゆるメモ化

    サブルーチン(関数)呼び出しの結果を保持し、再利用するこ
    とで、そのサブルーチンの呼び出し毎の再計算を防ぐ
    public class GetterLazyExample {
      public double[] getCached() { // 本当はthread-safe
        if (!this.$lombok$lazy1i) {
          this.$lombok$lazy1v = expensive();
          this.$lombok$lazy1i = true;
        }
        return this.$lombok$lazy1v;
      }

        private double[] expensive() { ... }
    }
@Cleanup


    リソースの片付けを自動で行なう
    public static void main(String[] args) throws IOException {
      @Cleanup InputStream in = new FileInputStream(args[0]);
      @Cleanup("release") MyResource resource = new MyResource();
      ...
    }
@Cleanup(変換後)


    リソースの片付けを自動で行なう
    public static void main(String[] args) throws IOException {
      InputStream in = new FileInputStream(args[0]);
      try {
        MyResource resource = new MyResource();
        try {
          ...
        } finally {
          if (resource != null) resource.release();
        }
      } finally {
        if (in != null) in.close();
      }
    }
@Synchronized


    this以外のロックオブジェクトで排他
    public class SynchronizedExample {
      private final Object readLock = new Object();

        @Synchronized private int foo() {
          return 1;
        }
        @Syncrhonized("readLock") private int bar() {
          return 2;
        }
    }
@Synchronized(変換後)


    this以外のロックオブジェクトで排他
    public class SynchronizedExample {
      private final Object $lock = new Object();
      private final Object readLock = new Object();

        private int foo() {
          synchronized($lock) { return 1; }
        }

        private int bar() {
          synchronized(readLock) { return 2; }
        }
    }
val


    ローカル変数の型宣言を省略
    public static void main(String[] args) {
      val map = new HashMap<String, List<String>>();
      ...
      for(val entry : map.entrySet()) {
        ...
      }
    }
val(変換後)


    ローカル変数の型宣言を省略
    public static void main(String[] args) {
     final Map<String, List<String>> map =
          new HashMap<String, List<String>>();

     ...

      for(final Map.Entry<String, List<String>> entry :
    map.entrySet()) {
        ...
      }
    }
etc

   @ToString
       toStringの生成
   @EqualsAndHashCode
       equalsとhachCodeの生成
   @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
       コンストラクタの生成
   @SneakyThrows
       チェック例外を非チェック例外のようにthrowする
   @Delegate
       移譲処理の生成
                              http://projectlombok.org/features/index.html
Lombokのメリット


    コードの冗長性の排除
    
        生産性が上がる
    
        コードの見通しを良くなる
    
        バグを埋め込む可能性を減らす
    
        心の平穏
Lombokのデメリット


    魔法に見える(not WYSIWYG)

    Lombokのバグに悩まされる可能性がある

    リファクタリング機能との衝突

    デバッグがややこしくなる
ここまでのまとめ


    LombokはJavaの冗長性を排除する

    尝辞尘产辞办の导入はとても簡単

    魔法には代償をともなう
Break time
尝辞尘产辞办の仕组み
ソースコード生成?バイトコード生成?


    いいえ、AST変換です



    JavaのASTを直接生成?変換してます
    
        ソースコード生成と違ってコードが膨れあがりません
    
        バイトコード生成と違って同じコンパイル単位のクラスか
        らも可視的です
Lombokが保持するAST


    JavacとECJの二つのASTを別々に保持

    AnnotationHandlerも各AST毎に実装する必要がある

    二つのASTを統合するためのプロジェクトも進行中
    
        https://github.com/rzwitserloot/lombok.ast
尝辞尘产辞办の処理の流れ
エントリーポイント


    lombok.javac.apt.Processor
    
        implements javax.annotation.processing.Processor

    lombok.eclipse.TransformEclipseAST
    
        EclipseのParserにパッチを当てて実行
        
            https://github.com/rzwitserloot/lombok.patcher
    
        OSGi ClassLoaderに注入されて実行される
AnnotationHandlerの読み込み



    プラグイン形式の読み込み

    @ProviderFor(JavacAnnotationHandler.class)
    
        used SPI(http://code.google.com/p/spi/)
        
            Service Provider Interfaceのwrapper
ASTの探索



    ASTをトラバースしてアノテーションを探索

    アノテーションが見付かったら、
    対応するAnnotationHandlerのhandleを実行する
    AnnotationVisitor
    
        Implements JavacASTVisitor
    
        独自のVisitorも定義可能
        
            @ProviderFor(JavacASTVisitor.class)
        
            HandleVal
ASTの変換



    各AnnotationHandlerや各ASTVisitorで

    変換にはJavacなどの非公開APIを直接使用
    
        com.sun.tools.javac.tree
    
        org.eclipse.jdt.internal
尝辞尘产辞办を拡张する
尝辞尘产辞办を拡张するには?


    Lombokは外からの拡張を意識して作っているわけではない

    Lombok本体を模範することで拡張することは出来る
@Perf


    メソッドの実行時間を出力
    public class PerfExample {
      @Perf
      void foo() {
        ...
      }
    }
@Perf(変換後)


    メソッドの実行時間を出力
    public class PerfExample {
      void foo() {
        long $start = System.nanoTime();
        try {
            …
        } finally {
          System.out.println(“PerfExample.foo = ”+
              System.nanoTime() - $start));
        }
      }
    }
プロジェクトの作り方


    prototype: https://github.com/alexruiz/dw-lombok
    
        プロジェクト名などを置換
    
        Ivyの設定を一部変更
        
            ECJのjarが取得出来なかった
        
            Lombokの最新(0.10.4)を使いたかった
アノテーションの定義


    トリガーとなるPerfアノテーションを作成する
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Perf {
    }
AnnotationHandlerの作成


    Javac用とECJ用の二つのAnnotationHandlerを作成する
    // for javac
    package localhost.javac.handlers;

    @ProviderFor(JavacAnnotationHandler.class)
    public class HandlePerf extends JavacAnnotationHandler<Perf> {
      @Override
      public void handle(AnnotationValues<Perf> annotation,
          JCAnnotation ast, JavacNode annotationNode) {
        ...
      }
    }
AST変換処理の実装


    愚直にASTを作るだけの簡単なお仕事
    TreeMaker maker = methodNode.getTreeMaker();

    // long $start = long t1 = System.nanoTime();
    Name startName = methodNode.toName("$start");
    JCExpression nanoTimeMethod =
        chainDotsString(methodNode, "System.nanoTime");
    JCExpression nanoTimeApply =
        maker.Apply(List.<JCExpression>nil(), nanoTimeMethod,
        List.<JCExpression>nil());

    JCVariableDecl startDef =
        setGeneratedBy(maker.VarDef(maker.Modifiers(0), startName,
        maker.TypeIdent(getCtcInt(TypeTags.class, "LONG")),
        nanoTimeApply), ast);
テスト


    本体が用意しているテスト?インフラがそのまま使える
    @RunWith(DirectoryRunner.class)
    public class TestWithEcj implements TestParams {
      @Override public Compiler getCompiler() { return ECJ; }
      @Override public boolean printErrors() { return true; }

        @Override public File getBeforeDirectory() {
          return new File("test/transform/resource/before");
        }
        @Override public File getAfterDirectory() {
          return new File("test/transform/resource/after-ecj");
        }
        ...
    }
拡張されたLombokの実行


    jar化してClasspathに追加すれば良い
    $ ant dist
    $ javac -cp “.:lib/build/lombok.jar:dist/lombok-perf.jar”
    Example.java
    $ java -cp “.”Example
感想


    変換処理はわりと愚直にAST作るだけの簡単なお仕事

    本体のコードこそが最高のサンプル
    
        https://github.com/rzwitserloot/lombok/tree/master/src/co
    
        https://github.com/rzwitserloot/lombok/tree/master/src/co
まとめ


    Lombokは皆さんのJava嫌いをちょっとだけ癒してくれます



    きっとScalaプログラマにもなれないJavaプログラマの皆さん

    Lombokを手にいれてみませんか?
第三回ありえる社内勉強会 「いわががのLombok」

More Related Content

What's hot (20)

PDF
Dockerfile を書くためのベストプラクティス解説編
Masahito Zembutsu
?
PPTX
iostat await svctm の 見かた、考え方
歩 柴田
?
PDF
顿辞肠办别谤と笔辞诲尘补苍の比较
Akihiro Suda
?
PDF
例外设计における大罪
Takuto Wada
?
PDF
贬罢罢笔を理解する
IIJ
?
PDF
なぜOpenID Connectが必要となったのか、その歴史的背景
Tatsuo Kudo
?
PDF
PostgreSQL 15の新機能を徹底解説
Masahiko Sawada
?
PDF
PostgreSQL Unconference #5 ICU Collation
Noriyoshi Shinoda
?
PDF
MySQL 5.7にやられないためにおぼえておいてほしいこと
yoku0825
?
PDF
サーバーが完肤なきまでに死んでも惭测厂蚕尝のデータを失わないための表技
yoku0825
?
PDF
PHP-FPM の子フ?ロセス制御方法と設定をおさらいしよう
Shohei Okada
?
PDF
コンテナ未経験新人が学ぶコンテナ技术入门
Kohei Tokunaga
?
PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
驰补丑辞辞!デベロッパーネットワーク
?
PPTX
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
Hiroshi Ito
?
PPTX
HTTP2 最速実装 ?入門編?
Kaoru Maeda
?
PDF
翱厂厂活动の活発さと评価の関係について
Takuto Wada
?
PDF
OpenID ConnectとAndroidアプリのログインサイクル
Masaru Kurahayashi
?
PDF
クラウド环境下における础笔滨リトライ设计
Kouji YAMADA
?
PDF
これからのネイティブアプリにおけるOpenID Connectの活用
Masaru Kurahayashi
?
Dockerfile を書くためのベストプラクティス解説編
Masahito Zembutsu
?
iostat await svctm の 見かた、考え方
歩 柴田
?
顿辞肠办别谤と笔辞诲尘补苍の比较
Akihiro Suda
?
例外设计における大罪
Takuto Wada
?
贬罢罢笔を理解する
IIJ
?
なぜOpenID Connectが必要となったのか、その歴史的背景
Tatsuo Kudo
?
PostgreSQL 15の新機能を徹底解説
Masahiko Sawada
?
PostgreSQL Unconference #5 ICU Collation
Noriyoshi Shinoda
?
MySQL 5.7にやられないためにおぼえておいてほしいこと
yoku0825
?
サーバーが完肤なきまでに死んでも惭测厂蚕尝のデータを失わないための表技
yoku0825
?
PHP-FPM の子フ?ロセス制御方法と設定をおさらいしよう
Shohei Okada
?
コンテナ未経験新人が学ぶコンテナ技术入门
Kohei Tokunaga
?
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
驰补丑辞辞!デベロッパーネットワーク
?
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
Hiroshi Ito
?
HTTP2 最速実装 ?入門編?
Kaoru Maeda
?
翱厂厂活动の活発さと评価の関係について
Takuto Wada
?
OpenID ConnectとAndroidアプリのログインサイクル
Masaru Kurahayashi
?
クラウド环境下における础笔滨リトライ设计
Kouji YAMADA
?
これからのネイティブアプリにおけるOpenID Connectの活用
Masaru Kurahayashi
?

Viewers also liked (19)

PPTX
Angular 2 Migration - JHipster Meetup 6
William Marques
?
PDF
地域の魅力を伝えるツアーガイド础滨
JubatusOfficial
?
PDF
Sencha TouchのMVCについて ?スケールするアプリケーションを求めて?
yoshiaki iwanaga
?
PDF
こわくない型クラス
Kota Mizushima
?
PPTX
AngularJS Version 1.3
Nir Noy
?
PPT
1.3 y 1.4 subject and predicate
paolyta28
?
PPTX
闯补惫补から始める蝉肠补濒补っぽい书き方
Kenji Doi
?
PDF
Angular 1.x reloaded: improve your app now! and get ready for 2.0
Carlo Bonamico
?
PPTX
Componentes en angularjs 1.5
Hugo Biarge
?
PPTX
さわってみよう搁别补肠迟.箩蝉、础苍驳耻濒补谤闯厂(1系、2系)
Kazuhiro Yoshimoto
?
PPTX
Code migration from Angular 1.x to Angular 2.0
Ran Wahle
?
PPTX
Comment re?ussir son projet en Angular 1.5 ?
Maxime Bernard
?
PDF
厂肠补濒补で型クラス入门
Makoto Fukuhara
?
PDF
厂肠补濒补で萌える関数型プログラミング摆完全版闭
Ra Zon
?
PDF
厂肠补濒补のオブジェクトの话
Yasuyuki Maeda
?
PPTX
Migrating an application from Angular 1 to Angular 2
Ross Dederer
?
PDF
AngularJS 2, version 1 and ReactJS
Kenneth Ceyer
?
PPTX
TechFeedのつくりかた - Angular2/Webpack/Ionic2/Cordova実践入門
Shumpei Shiraishi
?
ODP
Introduction to Angular 2
Knoldus Inc.
?
Angular 2 Migration - JHipster Meetup 6
William Marques
?
地域の魅力を伝えるツアーガイド础滨
JubatusOfficial
?
Sencha TouchのMVCについて ?スケールするアプリケーションを求めて?
yoshiaki iwanaga
?
こわくない型クラス
Kota Mizushima
?
AngularJS Version 1.3
Nir Noy
?
1.3 y 1.4 subject and predicate
paolyta28
?
闯补惫补から始める蝉肠补濒补っぽい书き方
Kenji Doi
?
Angular 1.x reloaded: improve your app now! and get ready for 2.0
Carlo Bonamico
?
Componentes en angularjs 1.5
Hugo Biarge
?
さわってみよう搁别补肠迟.箩蝉、础苍驳耻濒补谤闯厂(1系、2系)
Kazuhiro Yoshimoto
?
Code migration from Angular 1.x to Angular 2.0
Ran Wahle
?
Comment re?ussir son projet en Angular 1.5 ?
Maxime Bernard
?
厂肠补濒补で型クラス入门
Makoto Fukuhara
?
厂肠补濒补で萌える関数型プログラミング摆完全版闭
Ra Zon
?
厂肠补濒补のオブジェクトの话
Yasuyuki Maeda
?
Migrating an application from Angular 1 to Angular 2
Ross Dederer
?
AngularJS 2, version 1 and ReactJS
Kenneth Ceyer
?
TechFeedのつくりかた - Angular2/Webpack/Ionic2/Cordova実践入門
Shumpei Shiraishi
?
Introduction to Angular 2
Knoldus Inc.
?
Ad

Similar to 第三回ありえる社内勉強会 「いわががのLombok」 (20)

PDF
闯补惫补セキュアコーディングセミナー东京第3回讲义
JPCERT Coordination Center
?
PDF
ClassLoader Leak Patterns
nekop
?
PDF
ちょっと詳しくJavaScript 特別編【悪霊の神々】
株式会社ランチェスター
?
PDF
Java x Groovy: improve your java development life
Uehara Junji
?
PDF
gen-class とバイトコード(第3回 gen-class 勉強会資料)
tnoda
?
PDF
闯补惫补厂肠谤颈辫迟入门
Ryo Maruyama
?
PDF
Xtend - Javaの未来を今すぐ使う
Tatsumi Naganuma
?
PDF
Kotlin勉強会 in ehime
Eigoro Yamamura
?
PDF
今日からはじめる骋笔补谤蝉
fumokmm
?
PDF
闯补惫补の骋别苍别谤颈肠蝉とは?
Kenji Nakamura
?
PDF
Apache Torqueについて
tako pons
?
PDF
明日から使える Java SE 7
Yuichi Sakuraba
?
PDF
Rx java x retrofit
Shun Nakahara
?
PPTX
Visual C++で使えるC++11
nekko1119
?
PDF
ATN No.2 Scala事始め
AdvancedTechNight
?
PDF
React Native GUIDE
dcubeio
?
PDF
Testman
makoto tsuyuki
?
PDF
イマドキの现场で使える闯补惫补ライブラリ事情
takezoe
?
PDF
Best practice laravel
Risa Ohnishi
?
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
?
闯补惫补セキュアコーディングセミナー东京第3回讲义
JPCERT Coordination Center
?
ClassLoader Leak Patterns
nekop
?
ちょっと詳しくJavaScript 特別編【悪霊の神々】
株式会社ランチェスター
?
Java x Groovy: improve your java development life
Uehara Junji
?
gen-class とバイトコード(第3回 gen-class 勉強会資料)
tnoda
?
闯补惫补厂肠谤颈辫迟入门
Ryo Maruyama
?
Xtend - Javaの未来を今すぐ使う
Tatsumi Naganuma
?
Kotlin勉強会 in ehime
Eigoro Yamamura
?
今日からはじめる骋笔补谤蝉
fumokmm
?
闯补惫补の骋别苍别谤颈肠蝉とは?
Kenji Nakamura
?
Apache Torqueについて
tako pons
?
明日から使える Java SE 7
Yuichi Sakuraba
?
Rx java x retrofit
Shun Nakahara
?
Visual C++で使えるC++11
nekko1119
?
ATN No.2 Scala事始め
AdvancedTechNight
?
React Native GUIDE
dcubeio
?
イマドキの现场で使える闯补惫补ライブラリ事情
takezoe
?
Best practice laravel
Risa Ohnishi
?
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
?
Ad

Recently uploaded (9)

PDF
安尾 萌, 北村 茂生, 松下 光範. 災害発生時における被害状況把握を目的とした情報共有システムの基礎検討, 電子情報通信学会HCGシンポジウム2018...
Matsushita Laboratory
?
PPTX
色について.pptx .
iPride Co., Ltd.
?
PDF
論文紹介:AutoPrompt: Eliciting Knowledge from Language Models with Automatically ...
Toru Tamaki
?
PDF
安尾 萌, 松下 光範. 環境馴致を計量可能にするための試み,人工知能学会第4回仕掛学研究会, 2018.
Matsushita Laboratory
?
PPTX
Vibe Codingを始めよう ?Cursorを例に、ノーコードでのプログラミング体験?
iPride Co., Ltd.
?
PDF
論文紹介:Unbiasing through Textual Descriptions: Mitigating Representation Bias i...
Toru Tamaki
?
PDF
Forguncy 10 製品概要資料 - ノーコードWebアプリ開発プラットフォーム
フォーガンシー
?
PPTX
勉強会_ターミナルコマント?入力迅速化_20250620. pptx. .
iPride Co., Ltd.
?
PDF
安尾 萌, 藤代 裕之, 松下 光範. 協調的情報トリアージにおけるコミュニケーションの影響についての検討, 第11回データ工学と情報マネジメントに関する...
Matsushita Laboratory
?
安尾 萌, 北村 茂生, 松下 光範. 災害発生時における被害状況把握を目的とした情報共有システムの基礎検討, 電子情報通信学会HCGシンポジウム2018...
Matsushita Laboratory
?
色について.pptx .
iPride Co., Ltd.
?
論文紹介:AutoPrompt: Eliciting Knowledge from Language Models with Automatically ...
Toru Tamaki
?
安尾 萌, 松下 光範. 環境馴致を計量可能にするための試み,人工知能学会第4回仕掛学研究会, 2018.
Matsushita Laboratory
?
Vibe Codingを始めよう ?Cursorを例に、ノーコードでのプログラミング体験?
iPride Co., Ltd.
?
論文紹介:Unbiasing through Textual Descriptions: Mitigating Representation Bias i...
Toru Tamaki
?
Forguncy 10 製品概要資料 - ノーコードWebアプリ開発プラットフォーム
フォーガンシー
?
勉強会_ターミナルコマント?入力迅速化_20250620. pptx. .
iPride Co., Ltd.
?
安尾 萌, 藤代 裕之, 松下 光範. 協調的情報トリアージにおけるコミュニケーションの影響についての検討, 第11回データ工学と情報マネジメントに関する...
Matsushita Laboratory
?

第三回ありえる社内勉強会 「いわががのLombok」

  • 2. お前だれよ?  twitter: @kiris  いわなが?いわがが?
  • 3. Lombokって何?  http://projectlombok.org  created by  Javaの冗長性を排除する為  Roel Spilker のライブラリ  「赤唐辛子」の意味  v0.10.4  MIT license  Reinier Zwitserloot
  • 4. Javaの冗長性って?  こういうのとか class Data { private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
  • 5. Javaの冗長性って?  後、こういうのとか… InputStream in = new InputStream(args[0]); try { ... } finally { If (in != null) in.close(); }
  • 6. Javaの冗長性って?  他にも、こういうのとか… Map<String, List<String>> map = new HashMap<String, List<String>>(); ... for(Map.Entry<String, List<String>> entry : map) { ... }
  • 7. Javaの冗長性って?  …… class MyClass { private static Log log = LogFactory.getLog(MyClass.class); private final String name; public MyClass(String name) { if (name == null) { throw new NullPointerException(); } this.name = name; } @Override public int toString() { return “MyClass(name=”+ this.name +“)”; }
  • 8. Javaの冗長性って?   こうならない為のLombok! 続きはWebで!!
  • 9. 冗長の何がいけないの?  生産性が下がる  コード量が増えて読みづらくなる  バグが入り込む可能性がある  死にたくなる
  • 11. Lombokを入手する  Download lombok.jar  http://projectlombok.org/download.html  Maven or Ivy  http://projectlombok.org/mavenrepo/index.html
  • 12. Lombokを使う  Javac  Classpathに追加  GWT  java -javaagent:lombok.jar=ECJ  Play Framework  https://github.com/aaronfreeman/play-lombok#readme  ECJ  java -javaagent:lombok.jar=ECJ -Xbootclasspath/p:lombok.jar -jar ecj.jar -cp lombok.jar
  • 13. LombokをIDEでも使う  Eclipse, NetBeans なんかに対応  IDEA IntelliJはまだ未対応  java -jar lombok.jar
  • 15. @Data import lombok.Data public @Data class DataExample { private final String name; private int count; private List<Object> list; }  @Dataの主な機能  全てのフィールドのgetter / setter の生成  toString, equals, hashCodeの生成  finalフィールドを引数にしたコンストラクタの生成
  • 16. 結果の確認(delombok)  変換後のコードを出力  java -jar lombok.jar delombok -p ${src}  ファイルとして保存  java -jar lombok.jar delombok -d ${output} ${src}  Ant  <delombok verbose="true" encoding="UTF-8" to="$ {output}" from="${src}" />  Maven  https://github.com/awhitford/lombok.maven
  • 17. @Data(変換後) public class DataExample { private final String name; private int count; private List<Object> list; public DataExample(String name) { this.name = name; } public String getName() { return name; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } @Override public String toString() { ... } @Override public boolean equals(Object other) { ... } @Override public int hashCode() { … } }
  • 18. Eclipseからも即時反映  その场でアウトラインや补完候补に表示されます
  • 19. 他の機能  @Getter / @Setter  @Getter(lazy=true)  @ToString  @EqualsAndHashCode  @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor  @Data  @Cleanup  @Synchronized  @SneakyThrows  @Log  val  @Delegate http://projectlombok.org/features/index.html
  • 20. @Getter / @Setter  Getter / Setterの自動生成  @Dataよりも優先 public class GetterSetterExample { @Getter @Setter private String name; @Getter(AccessLevel.PROTECTED) private int age; }
  • 21. @Getter / @Setter(変換後)  Getter / Setterの自動生成  @Dataよりも優先 public class GetterSetterExample { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } protected int getAge() { return age; } }
  • 22. @Getter(lazy=true)  いわゆるメモ化  サブルーチン(関数)呼び出しの結果を保持し、再利用するこ とで、そのサブルーチンの呼び出し毎の再計算を防ぐ public class GetterLazyExample { @Getter(lazy=true) private final double[] cached = expensive(); private double[] expensive() { ... } }
  • 23. @Getter(lazy=true)(変換後)  いわゆるメモ化  サブルーチン(関数)呼び出しの結果を保持し、再利用するこ とで、そのサブルーチンの呼び出し毎の再計算を防ぐ public class GetterLazyExample { public double[] getCached() { // 本当はthread-safe if (!this.$lombok$lazy1i) { this.$lombok$lazy1v = expensive(); this.$lombok$lazy1i = true; } return this.$lombok$lazy1v; } private double[] expensive() { ... } }
  • 24. @Cleanup  リソースの片付けを自動で行なう public static void main(String[] args) throws IOException { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup("release") MyResource resource = new MyResource(); ... }
  • 25. @Cleanup(変換後)  リソースの片付けを自動で行なう public static void main(String[] args) throws IOException { InputStream in = new FileInputStream(args[0]); try { MyResource resource = new MyResource(); try { ... } finally { if (resource != null) resource.release(); } } finally { if (in != null) in.close(); } }
  • 26. @Synchronized  this以外のロックオブジェクトで排他 public class SynchronizedExample { private final Object readLock = new Object(); @Synchronized private int foo() { return 1; } @Syncrhonized("readLock") private int bar() { return 2; } }
  • 27. @Synchronized(変換後)  this以外のロックオブジェクトで排他 public class SynchronizedExample { private final Object $lock = new Object(); private final Object readLock = new Object(); private int foo() { synchronized($lock) { return 1; } } private int bar() { synchronized(readLock) { return 2; } } }
  • 28. val  ローカル変数の型宣言を省略 public static void main(String[] args) { val map = new HashMap<String, List<String>>(); ... for(val entry : map.entrySet()) { ... } }
  • 29. val(変換後)  ローカル変数の型宣言を省略 public static void main(String[] args) { final Map<String, List<String>> map = new HashMap<String, List<String>>(); ... for(final Map.Entry<String, List<String>> entry : map.entrySet()) { ... } }
  • 30. etc  @ToString  toStringの生成  @EqualsAndHashCode  equalsとhachCodeの生成  @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor  コンストラクタの生成  @SneakyThrows  チェック例外を非チェック例外のようにthrowする  @Delegate  移譲処理の生成 http://projectlombok.org/features/index.html
  • 31. Lombokのメリット  コードの冗長性の排除  生産性が上がる  コードの見通しを良くなる  バグを埋め込む可能性を減らす  心の平穏
  • 32. Lombokのデメリット  魔法に見える(not WYSIWYG)  Lombokのバグに悩まされる可能性がある  リファクタリング機能との衝突  デバッグがややこしくなる
  • 33. ここまでのまとめ  LombokはJavaの冗長性を排除する  尝辞尘产辞办の导入はとても簡単  魔法には代償をともなう
  • 36. ソースコード生成?バイトコード生成?  いいえ、AST変換です  JavaのASTを直接生成?変換してます  ソースコード生成と違ってコードが膨れあがりません  バイトコード生成と違って同じコンパイル単位のクラスか らも可視的です
  • 37. Lombokが保持するAST  JavacとECJの二つのASTを別々に保持  AnnotationHandlerも各AST毎に実装する必要がある  二つのASTを統合するためのプロジェクトも進行中  https://github.com/rzwitserloot/lombok.ast
  • 39. エントリーポイント  lombok.javac.apt.Processor  implements javax.annotation.processing.Processor  lombok.eclipse.TransformEclipseAST  EclipseのParserにパッチを当てて実行  https://github.com/rzwitserloot/lombok.patcher  OSGi ClassLoaderに注入されて実行される
  • 40. AnnotationHandlerの読み込み  プラグイン形式の読み込み  @ProviderFor(JavacAnnotationHandler.class)  used SPI(http://code.google.com/p/spi/)  Service Provider Interfaceのwrapper
  • 41. ASTの探索  ASTをトラバースしてアノテーションを探索  アノテーションが見付かったら、 対応するAnnotationHandlerのhandleを実行する AnnotationVisitor  Implements JavacASTVisitor  独自のVisitorも定義可能  @ProviderFor(JavacASTVisitor.class)  HandleVal
  • 42. ASTの変換  各AnnotationHandlerや各ASTVisitorで  変換にはJavacなどの非公開APIを直接使用  com.sun.tools.javac.tree  org.eclipse.jdt.internal
  • 44. 尝辞尘产辞办を拡张するには?  Lombokは外からの拡張を意識して作っているわけではない  Lombok本体を模範することで拡張することは出来る
  • 45. @Perf  メソッドの実行時間を出力 public class PerfExample { @Perf void foo() { ... } }
  • 46. @Perf(変換後)  メソッドの実行時間を出力 public class PerfExample { void foo() { long $start = System.nanoTime(); try { … } finally { System.out.println(“PerfExample.foo = ”+ System.nanoTime() - $start)); } } }
  • 47. プロジェクトの作り方  prototype: https://github.com/alexruiz/dw-lombok  プロジェクト名などを置換  Ivyの設定を一部変更  ECJのjarが取得出来なかった  Lombokの最新(0.10.4)を使いたかった
  • 48. アノテーションの定義  トリガーとなるPerfアノテーションを作成する @Target({ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface Perf { }
  • 49. AnnotationHandlerの作成  Javac用とECJ用の二つのAnnotationHandlerを作成する // for javac package localhost.javac.handlers; @ProviderFor(JavacAnnotationHandler.class) public class HandlePerf extends JavacAnnotationHandler<Perf> { @Override public void handle(AnnotationValues<Perf> annotation, JCAnnotation ast, JavacNode annotationNode) { ... } }
  • 50. AST変換処理の実装  愚直にASTを作るだけの簡単なお仕事 TreeMaker maker = methodNode.getTreeMaker(); // long $start = long t1 = System.nanoTime(); Name startName = methodNode.toName("$start"); JCExpression nanoTimeMethod = chainDotsString(methodNode, "System.nanoTime"); JCExpression nanoTimeApply = maker.Apply(List.<JCExpression>nil(), nanoTimeMethod, List.<JCExpression>nil()); JCVariableDecl startDef = setGeneratedBy(maker.VarDef(maker.Modifiers(0), startName, maker.TypeIdent(getCtcInt(TypeTags.class, "LONG")), nanoTimeApply), ast);
  • 51. テスト  本体が用意しているテスト?インフラがそのまま使える @RunWith(DirectoryRunner.class) public class TestWithEcj implements TestParams { @Override public Compiler getCompiler() { return ECJ; } @Override public boolean printErrors() { return true; } @Override public File getBeforeDirectory() { return new File("test/transform/resource/before"); } @Override public File getAfterDirectory() { return new File("test/transform/resource/after-ecj"); } ... }
  • 52. 拡張されたLombokの実行  jar化してClasspathに追加すれば良い $ ant dist $ javac -cp “.:lib/build/lombok.jar:dist/lombok-perf.jar” Example.java $ java -cp “.”Example
  • 53. 感想  変換処理はわりと愚直にAST作るだけの簡単なお仕事  本体のコードこそが最高のサンプル  https://github.com/rzwitserloot/lombok/tree/master/src/co  https://github.com/rzwitserloot/lombok/tree/master/src/co
  • 54. まとめ  Lombokは皆さんのJava嫌いをちょっとだけ癒してくれます  きっとScalaプログラマにもなれないJavaプログラマの皆さん Lombokを手にいれてみませんか?