SlideShare une entreprise Scribd logo
1  sur  26
Télécharger pour lire hors ligne
Android で DIxAOP
     




        Android で DIxAOP


1             Android で DIxAOP
Android で DIxAOP
 
 自己紹介

 ・名前    robo (兼高理恵)

 ・お仕事   Java 技術者
         設計から実装まで

 ・好きなもの  モバイル端末



2            Android で DIxAOP
Android を取り巻く環境の変遷

       国内携帯電話に占めるスマートフォン率は、
            過半数を超えたそうですが、
    国内初のAndroid端末販売(2009年7月)から2年が過ぎ、

             Android アプリも、
     黎明期・普及期から、充実期に至っていると思います。


参考先
2009年夏 docomo PRO/他 series HT-03A (発売日:2009.07.10)
http://www.doplaza.jp/products/docomo/ht03a.html
携帯電話販売に占めるスマートフォン比率、初めて5割超に (2011/04/08 記事)
http://itpro.nikkeibp.co.jp/article/Research/20110408/359254/


3                                           Android で DIxAOP
Android アプリ開発もまた…
    限られた開発情報から、
    少数の先進開発者が
    独自に解析や開発を行う時代を経て、

    開発情報の蓄積と洗練による、
    多数の一般開発者が
    参加する時代になりました。
参考先
個人ディベロッパーの時代は終わったのか? iPhoneアプリ業界の現状を追え
http://itlifehack.jp/archives/5704588.html




4                              Android で DIxAOP
Android アプリ開発もまた…
アプリ供給が増えたことによる競争力をつけるため、
アプリには、
高度なデザインや性能を豊富に含むことを迫られ、
Android アプリ開発は、
組織的な開発と大規模化の時代を迎えています。
      小さくてもOKな例外は、「特定目的のみに特化」したアプリでしょうか。

参考先
個人ディベロッパーの時代は終わったのか? iPhoneアプリ業界の現状を追え
http://itlifehack.jp/archives/5704588.html




5                              Android で DIxAOP
高機能化・大規模化の波

    画面周りでは、
    デザイン重視のカスタムViewや、アニメーション表現

    機能面では、
    各種センサー情報や、Webサービスとの連携強化

    実装方式では、
    実装への内部規約や設計思想の統一反映要求…


6             Android で DIxAOP
高機能化・大規模化の波
                      追い討ちをかける、
             Android 特有のフラグメンテーション対応
 画面サイズや解像度、CPU速度・搭載センサー…
 という表面的な違いだけでなく、
 端末機種によっては、API挙動の違いまであり、
               これに対応するには、
          端末ごとの対応(別実装)が必要になります。
参考先
Android 機種互換性問題対応顛末記
http://typea.info/blg/glob/2011/01/android-4.html
Androidのカメラアプリは難しい
http://www.toyship.org/archives/76


7                                                   Android で DIxAOP
DIxAOPフレームワークの登場

     Android アプリの高機能化・大規模化に伴い、
    開発形態は、多人数のチームが多分野のグループ
             下で行うようになりました。


          クラス数やソースコード、
     画面数や画面挙動パターンが増大するにつれ、
    テストやソース・コード管理のコスト(メンテナンスや実装統一)も、
           益々増大しています。

8                Android で DIxAOP
DIxAOPフレームワークの登場
      Java界隈では、
      複雑化したJavaEE開発に対応するため、
      Android に先んじること数年前(2004年頃)より、
    Spring(Spring2)、Seaser(Seaser2)、Guiceなどの
         DIコンテナやDIxAOPフレームワークが
                   使われています。
参考先
Spring Frameworkで理解するDI                                                  The seaser project (Seaser 本家サイト)
http://www.atmarkit.co.jp/fjava/index/index_springdi.html                http://www.seasar.org/
このバランス感覚、さすが - GoogleのDIフレームワーク"Guice"を使ってみる
http://journal.mycom.co.jp/articles/2007/03/14/googleguice/menu.html



9                                                     Android で DIxAOP
DIxAOPについて (DIとは)
DI:Dependency Injection
依存性注入
共通に扱いたいコンポーネントに対し、依存関係を
分離して、プログラム実行時に、外部から依存関係を
決定(依存性注入)させるプログラム技巧を表します。
          (インターフェースと実装の分離)
                          ※説明を短くするため、一般的な用語解説を意訳しています。

参考先
DI(依存性の注入)×AOP(アスペクト指向)の常識
http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html
Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ
(書籍)ISBN97804-7973-5340-2


10                                                  Android で DIxAOP
DIxAOPについて (DIとは)
DI活用例
端末ごとに対応実装が異なってしまうメソッドがある場合、
当該メソッド用のインターフェースを定義(依存関係分離)し
て、端末ごとのインターフェース実装クラスを作成しておき、
実行時に端末ごとのインスタンスを間接的に与えてもらうこ
とで、コンポーネント利用処理が共通でありながら、端末ごと
の対応ができるようになります。

参考先
DI(依存性の注入)×AOP(アスペクト指向)の常識
http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html
Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ
(書籍)ISBN97804-7973-5340-2


11                                                  Android で DIxAOP
DIxAOPについて (DIとは)
DI実装例イメージ
     interface Camera {                       端末名により、
        public void capture();}               Xperia用かIS03用の
     class XperiaCamera implements Camera {   いずれかのインスタンスを
        public void capture(){//Xperia用の実装};} 返します。
     class IS03Camera implements Camera {
        public void capture(){//IS03用の実装};}
     /*利用側*/Camera camera = Factory.getCamera(端末名);
     camera.capture();
     (※)挙動を固定化させてしまう、特定クラスを new する実装記述を避けます。


【補足】 依存性注入形式の違い
コンポーネントへのインスタンス注入を
フレームワークが自動的に行う場合は、DIパターンになり、
利用者側が自発的に行う場合は、Factory パターンになります。

12                       Android で DIxAOP
DIxAOPについて (AOPとは)
AOP:Aspect-Oriented Proguraming
アスペクト(局面)指向プログラミング
関心事物中心視点での開発を実現するため、
複数のコンポーネント間で共通に行いたい処理
(関心事物)をひとまとまりの処理で扱えるようにする
プログラム技巧です。
                          ※説明を短くするため、一般的な用語解説を意訳しています。

参考先
DI(依存性の注入)×AOP(アスペクト指向)の常識
http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html
Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ
(書籍)ISBN97804-7973-5340-2


13                                                  Android で DIxAOP
DIxAOPについて (AOPとは)
AOPの特色
テンプレート・パターンを用いて、
基盤クラスを継承させることで共通処理を行わせる場合、
共通処理を組み込むメソッドのシグニチャが固定されますが
AOPでは、
複数の異なるメソッド・シグニチャであっても、
Proxy技法を利用して対応できる点が大きく異なります。

参考先
DI(依存性の注入)×AOP(アスペクト指向)の常識
http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html
Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ
(書籍)ISBN97804-7973-5340-2


14                                                  Android で DIxAOP
DIxAOPについて (AOPとは)
AOPの特色
drawDisplay(View view)、animation(int patternNo)など、
シグニチャの異なるメソッドに対して、実行時の引数と結果
の内容や実行時間のデバッグ出力を後から追加したい場合
でも、一括して共通処理が追加できるのです。
      各メソッド実装へのデバッグ出力の追加は、不要です。


参考先
DI(依存性の注入)×AOP(アスペクト指向)の常識
http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html
Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ
(書籍)ISBN97804-7973-5340-2


15                                                  Android で DIxAOP
Android 対応のDIコンテナ
roboguice
                                        RoboGuice は、
                                        Android にシンプルで
                                        簡易な依存性注入(DI)を提供する、
                                        Google Guice Library を用いた
     (2011/09/09での最新版)
                                        DI フレームワークです。
          roboguice-1.1.2.jar
     102.8 KB (105289 バイト)

参考先
roboguice 本家サイト                                          Android MockとRoboGuiceでTDD
http://code.google.com/p/roboguice/                      http://d.hatena.ne.jp/thorikawa/20101127/p1
Android、DI、roboguiceなど                                   Unit Testing in Dependency Injection
http://d.hatena.ne.jp/akitoh/20101203/1291340779         http://d.hatena.ne.jp/esmasui/20100904/1283617914

16                                                 Android で DIxAOP
Android 対応のDIコンテナ
Roboguice利用例:
Roboguice 利用で、典型的なボイラープレート・コードが不要になります。
テストのMock注入にも有効だそうですが、時間の関係上ここまでとします。

     //roboguice 適用前                                                      //roboguice 適用後
     class AndroidWay extends Activity {                                  class RoboWay extends GuiceActivity {
         TextView name;                                                       @InjectView(R.id.name)               TextView name;
         ImageView thumbnail;                                                 @InjectView(R.id.thumbnail)          ImageView thumbnail;
         LocationManager loc;                                                 @InjectResource(R.drawable.icon)     Drawable icon;
         Drawable icon;                                                       @InjectResource(R.string.app_name)   String myName;
         String myName;                                                       @Inject                              LocationManager loc;

         public void onCreate(Bundle savedInstanceState) {                    public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);                                  super.onCreate(savedInstanceState);
             name      = (TextView) findViewById(R.id.name);                      name.setText( "Hello, " + myName );
             thumbnail = (ImageView) findViewById(R.id.thumbnail);            }
             loc       = (LocationManager)                                }
                           getSystemService(Activity.LOCATION_SERVICE);
             icon      = getResources().getDrawable(R.drawable.icon);
             myName    = getString(R.string.app_name);
             name.setText( "Hello, " + myName );
         }
     }
     (※)onCreateメソッドの中では、典型的な決まりきった記述                                     (※)各コンポーネントに外部から依存性注入(DI)してもらい
        (ボイラープレートコード)が行なわれています。                                              定型的なリソース読込処理の記述が不要になりました。




17                                                           Android で DIxAOP
Android における
     DIxAOP フレームワーク導入の問題
     本格的な DIxAOP フレームワークへの取り組みに
            積極的になれない理由
設計当初から、採用するDIxAOPフレームワーク対応を考慮する必要がある
各実装者には、採用するDIxAOPフレームワーク規約を学習済な必要がある
携帯端末のリソース制限から、導入(オーバーヘッド)を避けたい心理がある

     ですが、本格的に取り組みたくない(取り組むリソースがない)場合でも、
     デバッグ時の統一的なデバッグログ出力など、DIxAOP機能を一時的・
     仮設的・限定的でも利用したいことはあるので、

       簡単なDIxAOP機能は、内製対応できることが必要でしょう。

18                Android で DIxAOP
DIxAOP機能の内製実験
     簡単なDIxAOP機能の内製対応の実験をしてみます。
  依存を分離するために、AOP対象のメソッドは、
  インターフェースの定義と実装が必要になっていますが、
  funcFactory メソッドで、依存性の注入(DI)を行い、
  MyProxyクラスで、共通処理の処理先一括化(AOP)を
  行なうことで、
  実装内容を変えずに外部からデバッグ出力を追加できる
  ようにして、
  DIxAOP機能のエッセンスのみを実現してみました。
             (※)ソース全体は、資料巻末を御参照ください。 
19             Android で DIxAOP
DIxAOP機能の内製実験
                内製実験として、階乗関数や平均関数の実装を変えずに、
                   外部からのデバッグ出力を追加してみます。
     DIxAOP利用実装部(抜粋)
                                                           //階乗関数実装
                                                           public int factorial(int in){           階乗関数と平均関数の実装に、
     public void aopTest(){                                   int arg = in;                        デバッグ出力の処理は、
                                    通常とAOPの違いは、               int result = 1;
         //依存性注入(DI)オブジェクト          依存性注入 funcFactoryで                                             ありません。
         Func func = null;                                    for(;in > 0; in--){
                                    Proxy有無を指定するだけ               result *= in;
                                                              }
         //(階乗関数/平均関数)通常の実行
                                                              System.out.println(message+" factorial("+arg+") is "+result);
         func = funcFactory("TEST1 normal", false);
                                                              return result;
         func.factorial(5);
                                                           }
         func.average(new int[]{1, 2, 3, 4, 5});           //平均関数実装
                                                           public float average(int[] ins){
         System.out.println();                                StringBuilder args = new StringBuilder();
                                                              String sep = "";
         //AOP的、(階乗関数/平均関数)関心事物追加プロキシ実行                       int counts = ins.length;
         func = funcFactory("TEST2 AOP", true);               int result = 0;
         func.factorial(5);                                   for(int in: ins){
         func.average(new int[]{1, 2, 3, 4, 5});                 args.append(sep).append(in); sep=", ";
     }                                                           result += in;
                           AOP対応のオブジェクトを取得するには、
                                                              }
     //依存性注入ファクトリ          MyProxy に元オブジェクトを渡すのみ。
                                                              result /= counts;
     public Func funcFactory(String arg0, boolean             System.out.println(message+
     isProxy){                                                   " average(["+args.toString()+"]) is "+result);
         Object instance = new FuncImpl(arg0);                return result;
         if(isProxy) return                                }
            (Func)MyProxy.getProxyObject(instance);        (※)通常実行部もプロキシ実行部も、ソース記述的には変化がありません。
         return (Func)instance;                              階乗関数や平均関数の実装中には、デバッグ出力処理がありません。
     }




20                                               Android で DIxAOP
DIxAOP機能の内製実験
          テスト実行結果では、階乗関数や平均関数の実装を変えずに、
              外部からのデバッグ出力追加ができています。


      実行結果:
      TEST1 normal factorial(5) is 120
      TEST1 normal average([1, 2, 3, 4, 5]) is 3

      DEBUG   OUT   method start name=factorial, arg[0]=5
      TEST2   AOP   factorial(5) is 120
      DEBUG   OUT   method end name=factorial, return=120, execute time =780361nsec
      DEBUG   OUT   method start name=average, arg[0]=[I@863399
      TEST2   AOP   average([1, 2, 3, 4, 5]) is 3
      DEBUG   OUT   method end name=average, return=3.0, execute time =470793nsec


      AOP的メソッド実行では、前後に
      デバッグ出力が追加されました。


     MyProxy クラスによるAOP機能は、Android アプリ中でも動作することを確認しています。

21                                          Android で DIxAOP
DIxAOPでも設計が大切です
  最後になりましたが、
  DIxAOP を利用すれば、
  共通の実装を変えずに個別の内容(挙動)を変更したり(DI)、
  個別の実装を変えずに共通の処理を一括追加する(AOP)
  ことができます。
     これにより、テストやソースコードの記述と管理のコストが
     低減することになりますが、これは、設計がおろそかでも
     後から対応できることでは、ありません。
         共通部と独立部を明確にするために、
          設計が重要なのは変わりません。

22             Android で DIxAOP
Android で DIxAOP
  




     ご清聴、ありがとうございました。




23        Android で DIxAOP
DIxAOP機能の内製実験ソース
     import java.lang.reflect.Method;
     import java.lang.reflect.Proxy;
     import java.lang.reflect.InvocationHandler;


     public class DIxAOPxTest {
         public static void main(String[] args){
             DIxAOPxTest test = new DIxAOPxTest();
             test.aopTest();
         }

         public void aopTest(){
             //(階乗関数/平均関数)通常の実行
             func = funcFactory("TEST1 normal", false);
             func.factorial(5);
             func.average(new int[]{1, 2, 3, 4, 5});

             System.out.println();

             //AOP的、(階乗関数/平均関数)関心事物追加プロキシ実行
             func = funcFactory("TEST2 AOP", true);
             func.factorial(5);
             func.average(new int[]{1, 2, 3, 4, 5});
         }

         //依存性注入ファクトリ
         public Func funcFactory(String arg0, boolean isProxy){
             Object instance = new FuncImpl(arg0);
             if(isProxy) return (Func)MyProxy.getProxyObject(instance);
             return (Func)instance;
         }
     }




24                                             Android で DIxAOP
DIxAOP機能の内製実験ソース
     //階乗/平均関数インターフェース
     interface Func {
         public int factorial(int in);
         public float average(int[] ins);
     }
     //階乗/平均関数実装
     class FuncImpl implements Func {
         private String message = "";
         public FuncImpl(String message){
             this.message = message;
         }
         public int factorial(int in){
             int arg = in;
             int result = 1;
             for(;in > 0; in--){
                 result *= in;
             }
             System.out.println(message+" factorial("+arg+") is "+result);
             return result;
         }
         public float average(int[] ins){
             StringBuilder args = new StringBuilder();
             String sep = "";
             int counts = ins.length;
             int result = 0;
             for(int in: ins){
                 args.append(sep).append(in); sep=", ";
                 result += in;
             }
             result /= counts;
             System.out.println(message+" average(["+args.toString()+"]) is "+result);
             return result;
         }
     }


25                                             Android で DIxAOP
DIxAOP機能の内製実験ソース
     //汎用プロキシ・オブジェクト取得クラス
     class MyProxy implements InvocationHandler {
         private Object originalObject = null;
         private MyProxy(Object originalObject){
             this.originalObject = originalObject;
         }
         public static Object getProxyObject(Object obj){
             //プロキシ対象のメソッド・インターフェースを取得します。
             Class<?>[] interfaces = obj.getClass().getInterfaces();
             //プロキシ対象でない場合は、元オブジェクトを返します。
             if(interfaces == null || interfaces.length == 0) return obj;
             //プロキシ・オブジェクトを返します。
             MyProxy instance = new MyProxy(obj);
             Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), interfaces, instance);
             return proxy;
         }
         @Override
         public Object invoke(Object interfaceProxy, Method method, Object[] args) throws Throwable {
             long startNanoTime = System.nanoTime();
             StringBuilder sb = new StringBuilder();
             for(int index = 0; args != null && index < args.length; index++){
                 sb.append(", ").append("arg[").append(index).append("]=").append(args[index].toString());
             }
             //メソッド実行前の任意処理
             System.out.println("DEBUG OUT method start name="+method.getName()+sb.toString());
             //メソッド実行
             Object ret = method.invoke(originalObject, args);
             //メソッド実行後の任意処理
             System.out.println("DEBUG OUT method end name="+method.getName()+", return="
                 +((ret==null)?"void or null":ret.toString())
                 +", execute time ="+(System.nanoTime()-startNanoTime)+"nsec");
             return ret;
         }
     }


26                                             Android で DIxAOP

Contenu connexe

Tendances

OpenCV4Androidで画像処理アプリのススメ
OpenCV4Androidで画像処理アプリのススメOpenCV4Androidで画像処理アプリのススメ
OpenCV4Androidで画像処理アプリのススメ
Masaki Otsuki
 
Andoird版OpenCVのJavaサンプルを動かす
Andoird版OpenCVのJavaサンプルを動かすAndoird版OpenCVのJavaサンプルを動かす
Andoird版OpenCVのJavaサンプルを動かす
shobomaru
 
iOS 8 Widget ~ 導入から Tips まで
iOS 8 Widget ~ 導入から Tips までiOS 8 Widget ~ 導入から Tips まで
iOS 8 Widget ~ 導入から Tips まで
Yuki Tanabe
 

Tendances (20)

Androidアプリのストレージ戦略
Androidアプリのストレージ戦略Androidアプリのストレージ戦略
Androidアプリのストレージ戦略
 
Android cleanarchitecture
Android cleanarchitectureAndroid cleanarchitecture
Android cleanarchitecture
 
Osc tokyo 20140301 2
Osc tokyo 20140301 2Osc tokyo 20140301 2
Osc tokyo 20140301 2
 
はじめてのJPA
はじめてのJPAはじめてのJPA
はじめてのJPA
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術
 
多分怖くない, Androidとハードウェア
多分怖くない, Androidとハードウェア多分怖くない, Androidとハードウェア
多分怖くない, Androidとハードウェア
 
Di入門
Di入門Di入門
Di入門
 
Android Studio開発講座
Android Studio開発講座Android Studio開発講座
Android Studio開発講座
 
Windows8でOpenCVを使ったAndroid(MOVERIO)開発体験したい
Windows8でOpenCVを使ったAndroid(MOVERIO)開発体験したいWindows8でOpenCVを使ったAndroid(MOVERIO)開発体験したい
Windows8でOpenCVを使ったAndroid(MOVERIO)開発体験したい
 
Javaにおけるネイティブコード連携の各種手法の紹介
Javaにおけるネイティブコード連携の各種手法の紹介Javaにおけるネイティブコード連携の各種手法の紹介
Javaにおけるネイティブコード連携の各種手法の紹介
 
Androidテスティング実践2 システムテスト編
Androidテスティング実践2 システムテスト編Androidテスティング実践2 システムテスト編
Androidテスティング実践2 システムテスト編
 
OpenCV4Androidで画像処理アプリのススメ
OpenCV4Androidで画像処理アプリのススメOpenCV4Androidで画像処理アプリのススメ
OpenCV4Androidで画像処理アプリのススメ
 
はじめてのAndroid in 高知
はじめてのAndroid in 高知はじめてのAndroid in 高知
はじめてのAndroid in 高知
 
つ部 Android Studio 勉強会 12/7
つ部 Android Studio 勉強会 12/7つ部 Android Studio 勉強会 12/7
つ部 Android Studio 勉強会 12/7
 
Andoird版OpenCVのJavaサンプルを動かす
Andoird版OpenCVのJavaサンプルを動かすAndoird版OpenCVのJavaサンプルを動かす
Andoird版OpenCVのJavaサンプルを動かす
 
iOS 8 Widget ~ 導入から Tips まで
iOS 8 Widget ~ 導入から Tips までiOS 8 Widget ~ 導入から Tips まで
iOS 8 Widget ~ 導入から Tips まで
 
Before lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替えるBefore lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替える
 
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
 
Try_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackTry_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hack
 
HoloLensとWindows Mixed Reality が実現する新しい世界
HoloLensとWindows Mixed Reality が実現する新しい世界HoloLensとWindows Mixed Reality が実現する新しい世界
HoloLensとWindows Mixed Reality が実現する新しい世界
 

En vedette

Eclipseデバッガを活用するための31のtips
Eclipseデバッガを活用するための31のtipsEclipseデバッガを活用するための31のtips
Eclipseデバッガを活用するための31のtips
Hiroki Kondo
 

En vedette (6)

Eclipseを使ったandroid nativeデバッグ
Eclipseを使ったandroid nativeデバッグEclipseを使ったandroid nativeデバッグ
Eclipseを使ったandroid nativeデバッグ
 
Waze Map Editor クイックスタートガイド
Waze Map Editor クイックスタートガイドWaze Map Editor クイックスタートガイド
Waze Map Editor クイックスタートガイド
 
Eclipseデバッガを活用するための31のtips
Eclipseデバッガを活用するための31のtipsEclipseデバッガを活用するための31のtips
Eclipseデバッガを活用するための31のtips
 
The Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsThe Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post Formats
 
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika AldabaLightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving Cars
 

Similaire à AndroidでDIxAOP

NPAPIを使ったandroid標準ブラウザの拡張方法
NPAPIを使ったandroid標準ブラウザの拡張方法NPAPIを使ったandroid標準ブラウザの拡張方法
NPAPIを使ったandroid標準ブラウザの拡張方法
Naruto TAKAHASHI
 
Tech talk salesforce mobile sdk
Tech talk   salesforce mobile sdkTech talk   salesforce mobile sdk
Tech talk salesforce mobile sdk
Kazuki Nakajima
 
勉強会force#3 iOSアプリ開発
勉強会force#3 iOSアプリ開発勉強会force#3 iOSアプリ開発
勉強会force#3 iOSアプリ開発
Kazuki Nakajima
 
20111031 MobileWeb at TDC
20111031 MobileWeb at TDC20111031 MobileWeb at TDC
20111031 MobileWeb at TDC
Nobuhiro Sue
 
Application Architecture for Enterprise Win Store Apps with DDD Pattern
Application Architecture for Enterprise Win Store Apps with DDD PatternApplication Architecture for Enterprise Win Store Apps with DDD Pattern
Application Architecture for Enterprise Win Store Apps with DDD Pattern
Atsushi Kambara
 

Similaire à AndroidでDIxAOP (20)

Visual Studio App Centerを公式サンプルアプリから学ぼうiOS(swift),Android(java)
Visual Studio App Centerを公式サンプルアプリから学ぼうiOS(swift),Android(java)Visual Studio App Centerを公式サンプルアプリから学ぼうiOS(swift),Android(java)
Visual Studio App Centerを公式サンプルアプリから学ぼうiOS(swift),Android(java)
 
LT発表資料
LT発表資料LT発表資料
LT発表資料
 
スマートフォンアプリケーション開発の最新動向
スマートフォンアプリケーション開発の最新動向スマートフォンアプリケーション開発の最新動向
スマートフォンアプリケーション開発の最新動向
 
[DevSummit2013S]Android_Multi-Version_Multi-Device
[DevSummit2013S]Android_Multi-Version_Multi-Device[DevSummit2013S]Android_Multi-Version_Multi-Device
[DevSummit2013S]Android_Multi-Version_Multi-Device
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
 
Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!
 
NPAPIを使ったandroid標準ブラウザの拡張方法
NPAPIを使ったandroid標準ブラウザの拡張方法NPAPIを使ったandroid標準ブラウザの拡張方法
NPAPIを使ったandroid標準ブラウザの拡張方法
 
もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!
 
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
 
Java/Androidセキュアコーディング
Java/AndroidセキュアコーディングJava/Androidセキュアコーディング
Java/Androidセキュアコーディング
 
Tech talk salesforce mobile sdk
Tech talk   salesforce mobile sdkTech talk   salesforce mobile sdk
Tech talk salesforce mobile sdk
 
勉強会force#3 iOSアプリ開発
勉強会force#3 iOSアプリ開発勉強会force#3 iOSアプリ開発
勉強会force#3 iOSアプリ開発
 
Android Studioの魅力
Android Studioの魅力Android Studioの魅力
Android Studioの魅力
 
Adobe XDプラグインをつくってみよう
Adobe XDプラグインをつくってみようAdobe XDプラグインをつくってみよう
Adobe XDプラグインをつくってみよう
 
Android4.2徹底解剖!
Android4.2徹底解剖!Android4.2徹底解剖!
Android4.2徹底解剖!
 
PhoneGapでWebアプリをスマホアプリ化
PhoneGapでWebアプリをスマホアプリ化PhoneGapでWebアプリをスマホアプリ化
PhoneGapでWebアプリをスマホアプリ化
 
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
 
ngCore engine for mobage platform
ngCore engine for mobage platformngCore engine for mobage platform
ngCore engine for mobage platform
 
20111031 MobileWeb at TDC
20111031 MobileWeb at TDC20111031 MobileWeb at TDC
20111031 MobileWeb at TDC
 
Application Architecture for Enterprise Win Store Apps with DDD Pattern
Application Architecture for Enterprise Win Store Apps with DDD PatternApplication Architecture for Enterprise Win Store Apps with DDD Pattern
Application Architecture for Enterprise Win Store Apps with DDD Pattern
 

AndroidでDIxAOP

  • 1. Android で DIxAOP   Android で DIxAOP 1 Android で DIxAOP
  • 2. Android で DIxAOP    自己紹介  ・名前    robo (兼高理恵)  ・お仕事   Java 技術者          設計から実装まで  ・好きなもの  モバイル端末 2 Android で DIxAOP
  • 3. Android を取り巻く環境の変遷 国内携帯電話に占めるスマートフォン率は、 過半数を超えたそうですが、 国内初のAndroid端末販売(2009年7月)から2年が過ぎ、 Android アプリも、 黎明期・普及期から、充実期に至っていると思います。 参考先 2009年夏 docomo PRO/他 series HT-03A (発売日:2009.07.10) http://www.doplaza.jp/products/docomo/ht03a.html 携帯電話販売に占めるスマートフォン比率、初めて5割超に (2011/04/08 記事) http://itpro.nikkeibp.co.jp/article/Research/20110408/359254/ 3 Android で DIxAOP
  • 4. Android アプリ開発もまた… 限られた開発情報から、 少数の先進開発者が 独自に解析や開発を行う時代を経て、 開発情報の蓄積と洗練による、 多数の一般開発者が 参加する時代になりました。 参考先 個人ディベロッパーの時代は終わったのか? iPhoneアプリ業界の現状を追え http://itlifehack.jp/archives/5704588.html 4 Android で DIxAOP
  • 5. Android アプリ開発もまた… アプリ供給が増えたことによる競争力をつけるため、 アプリには、 高度なデザインや性能を豊富に含むことを迫られ、 Android アプリ開発は、 組織的な開発と大規模化の時代を迎えています。 小さくてもOKな例外は、「特定目的のみに特化」したアプリでしょうか。 参考先 個人ディベロッパーの時代は終わったのか? iPhoneアプリ業界の現状を追え http://itlifehack.jp/archives/5704588.html 5 Android で DIxAOP
  • 6. 高機能化・大規模化の波 画面周りでは、 デザイン重視のカスタムViewや、アニメーション表現 機能面では、 各種センサー情報や、Webサービスとの連携強化 実装方式では、 実装への内部規約や設計思想の統一反映要求… 6 Android で DIxAOP
  • 7. 高機能化・大規模化の波 追い討ちをかける、 Android 特有のフラグメンテーション対応 画面サイズや解像度、CPU速度・搭載センサー…  という表面的な違いだけでなく、 端末機種によっては、API挙動の違いまであり、 これに対応するには、 端末ごとの対応(別実装)が必要になります。 参考先 Android 機種互換性問題対応顛末記 http://typea.info/blg/glob/2011/01/android-4.html Androidのカメラアプリは難しい http://www.toyship.org/archives/76 7 Android で DIxAOP
  • 8. DIxAOPフレームワークの登場 Android アプリの高機能化・大規模化に伴い、 開発形態は、多人数のチームが多分野のグループ 下で行うようになりました。 クラス数やソースコード、 画面数や画面挙動パターンが増大するにつれ、 テストやソース・コード管理のコスト(メンテナンスや実装統一)も、 益々増大しています。 8 Android で DIxAOP
  • 9. DIxAOPフレームワークの登場 Java界隈では、 複雑化したJavaEE開発に対応するため、 Android に先んじること数年前(2004年頃)より、 Spring(Spring2)、Seaser(Seaser2)、Guiceなどの DIコンテナやDIxAOPフレームワークが 使われています。 参考先 Spring Frameworkで理解するDI The seaser project (Seaser 本家サイト) http://www.atmarkit.co.jp/fjava/index/index_springdi.html http://www.seasar.org/ このバランス感覚、さすが - GoogleのDIフレームワーク"Guice"を使ってみる http://journal.mycom.co.jp/articles/2007/03/14/googleguice/menu.html 9 Android で DIxAOP
  • 10. DIxAOPについて (DIとは) DI:Dependency Injection 依存性注入 共通に扱いたいコンポーネントに対し、依存関係を 分離して、プログラム実行時に、外部から依存関係を 決定(依存性注入)させるプログラム技巧を表します。 (インターフェースと実装の分離) ※説明を短くするため、一般的な用語解説を意訳しています。 参考先 DI(依存性の注入)×AOP(アスペクト指向)の常識 http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ (書籍)ISBN97804-7973-5340-2 10 Android で DIxAOP
  • 12. DIxAOPについて (DIとは) DI実装例イメージ interface Camera { 端末名により、 public void capture();} Xperia用かIS03用の class XperiaCamera implements Camera { いずれかのインスタンスを public void capture(){//Xperia用の実装};} 返します。 class IS03Camera implements Camera { public void capture(){//IS03用の実装};} /*利用側*/Camera camera = Factory.getCamera(端末名); camera.capture(); (※)挙動を固定化させてしまう、特定クラスを new する実装記述を避けます。 【補足】 依存性注入形式の違い コンポーネントへのインスタンス注入を フレームワークが自動的に行う場合は、DIパターンになり、 利用者側が自発的に行う場合は、Factory パターンになります。 12 Android で DIxAOP
  • 13. DIxAOPについて (AOPとは) AOP:Aspect-Oriented Proguraming アスペクト(局面)指向プログラミング 関心事物中心視点での開発を実現するため、 複数のコンポーネント間で共通に行いたい処理 (関心事物)をひとまとまりの処理で扱えるようにする プログラム技巧です。 ※説明を短くするため、一般的な用語解説を意訳しています。 参考先 DI(依存性の注入)×AOP(アスペクト指向)の常識 http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ (書籍)ISBN97804-7973-5340-2 13 Android で DIxAOP
  • 15. DIxAOPについて (AOPとは) AOPの特色 drawDisplay(View view)、animation(int patternNo)など、 シグニチャの異なるメソッドに対して、実行時の引数と結果 の内容や実行時間のデバッグ出力を後から追加したい場合 でも、一括して共通処理が追加できるのです。 各メソッド実装へのデバッグ出力の追加は、不要です。 参考先 DI(依存性の注入)×AOP(アスペクト指向)の常識 http://www.atmarkit.co.jp/fjava/rensai4/enterprise_jboss03/01.html Java フレームワーク開発入門 著者:木村聡 Chapter 4 DIxAOPを学ぶ (書籍)ISBN97804-7973-5340-2 15 Android で DIxAOP
  • 16. Android 対応のDIコンテナ roboguice RoboGuice は、 Android にシンプルで 簡易な依存性注入(DI)を提供する、 Google Guice Library を用いた (2011/09/09での最新版) DI フレームワークです。 roboguice-1.1.2.jar 102.8 KB (105289 バイト) 参考先 roboguice 本家サイト Android MockとRoboGuiceでTDD http://code.google.com/p/roboguice/ http://d.hatena.ne.jp/thorikawa/20101127/p1 Android、DI、roboguiceなど Unit Testing in Dependency Injection http://d.hatena.ne.jp/akitoh/20101203/1291340779 http://d.hatena.ne.jp/esmasui/20100904/1283617914 16 Android で DIxAOP
  • 17. Android 対応のDIコンテナ Roboguice利用例: Roboguice 利用で、典型的なボイラープレート・コードが不要になります。 テストのMock注入にも有効だそうですが、時間の関係上ここまでとします。 //roboguice 適用前 //roboguice 適用後 class AndroidWay extends Activity { class RoboWay extends GuiceActivity { TextView name; @InjectView(R.id.name) TextView name; ImageView thumbnail; @InjectView(R.id.thumbnail) ImageView thumbnail; LocationManager loc; @InjectResource(R.drawable.icon) Drawable icon; Drawable icon; @InjectResource(R.string.app_name) String myName; String myName; @Inject LocationManager loc; public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); name = (TextView) findViewById(R.id.name); name.setText( "Hello, " + myName ); thumbnail = (ImageView) findViewById(R.id.thumbnail); } loc = (LocationManager) } getSystemService(Activity.LOCATION_SERVICE); icon = getResources().getDrawable(R.drawable.icon); myName = getString(R.string.app_name); name.setText( "Hello, " + myName ); } } (※)onCreateメソッドの中では、典型的な決まりきった記述 (※)各コンポーネントに外部から依存性注入(DI)してもらい (ボイラープレートコード)が行なわれています。 定型的なリソース読込処理の記述が不要になりました。 17 Android で DIxAOP
  • 18. Android における DIxAOP フレームワーク導入の問題 本格的な DIxAOP フレームワークへの取り組みに 積極的になれない理由 設計当初から、採用するDIxAOPフレームワーク対応を考慮する必要がある 各実装者には、採用するDIxAOPフレームワーク規約を学習済な必要がある 携帯端末のリソース制限から、導入(オーバーヘッド)を避けたい心理がある ですが、本格的に取り組みたくない(取り組むリソースがない)場合でも、 デバッグ時の統一的なデバッグログ出力など、DIxAOP機能を一時的・ 仮設的・限定的でも利用したいことはあるので、 簡単なDIxAOP機能は、内製対応できることが必要でしょう。 18 Android で DIxAOP
  • 19. DIxAOP機能の内製実験 簡単なDIxAOP機能の内製対応の実験をしてみます。  依存を分離するために、AOP対象のメソッドは、  インターフェースの定義と実装が必要になっていますが、  funcFactory メソッドで、依存性の注入(DI)を行い、  MyProxyクラスで、共通処理の処理先一括化(AOP)を  行なうことで、  実装内容を変えずに外部からデバッグ出力を追加できる  ようにして、  DIxAOP機能のエッセンスのみを実現してみました。  (※)ソース全体は、資料巻末を御参照ください。  19 Android で DIxAOP
  • 20. DIxAOP機能の内製実験 内製実験として、階乗関数や平均関数の実装を変えずに、 外部からのデバッグ出力を追加してみます。 DIxAOP利用実装部(抜粋) //階乗関数実装 public int factorial(int in){ 階乗関数と平均関数の実装に、 public void aopTest(){ int arg = in; デバッグ出力の処理は、 通常とAOPの違いは、 int result = 1; //依存性注入(DI)オブジェクト 依存性注入 funcFactoryで ありません。 Func func = null; for(;in > 0; in--){ Proxy有無を指定するだけ result *= in; } //(階乗関数/平均関数)通常の実行 System.out.println(message+" factorial("+arg+") is "+result); func = funcFactory("TEST1 normal", false); return result; func.factorial(5); } func.average(new int[]{1, 2, 3, 4, 5}); //平均関数実装 public float average(int[] ins){ System.out.println(); StringBuilder args = new StringBuilder(); String sep = ""; //AOP的、(階乗関数/平均関数)関心事物追加プロキシ実行 int counts = ins.length; func = funcFactory("TEST2 AOP", true); int result = 0; func.factorial(5); for(int in: ins){ func.average(new int[]{1, 2, 3, 4, 5}); args.append(sep).append(in); sep=", "; } result += in; AOP対応のオブジェクトを取得するには、 } //依存性注入ファクトリ MyProxy に元オブジェクトを渡すのみ。 result /= counts; public Func funcFactory(String arg0, boolean System.out.println(message+ isProxy){ " average(["+args.toString()+"]) is "+result); Object instance = new FuncImpl(arg0); return result; if(isProxy) return } (Func)MyProxy.getProxyObject(instance); (※)通常実行部もプロキシ実行部も、ソース記述的には変化がありません。 return (Func)instance; 階乗関数や平均関数の実装中には、デバッグ出力処理がありません。 } 20 Android で DIxAOP
  • 21. DIxAOP機能の内製実験 テスト実行結果では、階乗関数や平均関数の実装を変えずに、 外部からのデバッグ出力追加ができています。 実行結果: TEST1 normal factorial(5) is 120 TEST1 normal average([1, 2, 3, 4, 5]) is 3 DEBUG OUT method start name=factorial, arg[0]=5 TEST2 AOP factorial(5) is 120 DEBUG OUT method end name=factorial, return=120, execute time =780361nsec DEBUG OUT method start name=average, arg[0]=[I@863399 TEST2 AOP average([1, 2, 3, 4, 5]) is 3 DEBUG OUT method end name=average, return=3.0, execute time =470793nsec AOP的メソッド実行では、前後に デバッグ出力が追加されました。 MyProxy クラスによるAOP機能は、Android アプリ中でも動作することを確認しています。 21 Android で DIxAOP
  • 22. DIxAOPでも設計が大切です  最後になりましたが、  DIxAOP を利用すれば、  共通の実装を変えずに個別の内容(挙動)を変更したり(DI)、  個別の実装を変えずに共通の処理を一括追加する(AOP)  ことができます。 これにより、テストやソースコードの記述と管理のコストが 低減することになりますが、これは、設計がおろそかでも 後から対応できることでは、ありません。 共通部と独立部を明確にするために、 設計が重要なのは変わりません。 22 Android で DIxAOP
  • 23. Android で DIxAOP   ご清聴、ありがとうございました。 23 Android で DIxAOP
  • 24. DIxAOP機能の内製実験ソース import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; public class DIxAOPxTest { public static void main(String[] args){ DIxAOPxTest test = new DIxAOPxTest(); test.aopTest(); } public void aopTest(){ //(階乗関数/平均関数)通常の実行 func = funcFactory("TEST1 normal", false); func.factorial(5); func.average(new int[]{1, 2, 3, 4, 5}); System.out.println(); //AOP的、(階乗関数/平均関数)関心事物追加プロキシ実行 func = funcFactory("TEST2 AOP", true); func.factorial(5); func.average(new int[]{1, 2, 3, 4, 5}); } //依存性注入ファクトリ public Func funcFactory(String arg0, boolean isProxy){ Object instance = new FuncImpl(arg0); if(isProxy) return (Func)MyProxy.getProxyObject(instance); return (Func)instance; } } 24 Android で DIxAOP
  • 25. DIxAOP機能の内製実験ソース //階乗/平均関数インターフェース interface Func { public int factorial(int in); public float average(int[] ins); } //階乗/平均関数実装 class FuncImpl implements Func { private String message = ""; public FuncImpl(String message){ this.message = message; } public int factorial(int in){ int arg = in; int result = 1; for(;in > 0; in--){ result *= in; } System.out.println(message+" factorial("+arg+") is "+result); return result; } public float average(int[] ins){ StringBuilder args = new StringBuilder(); String sep = ""; int counts = ins.length; int result = 0; for(int in: ins){ args.append(sep).append(in); sep=", "; result += in; } result /= counts; System.out.println(message+" average(["+args.toString()+"]) is "+result); return result; } } 25 Android で DIxAOP
  • 26. DIxAOP機能の内製実験ソース //汎用プロキシ・オブジェクト取得クラス class MyProxy implements InvocationHandler { private Object originalObject = null; private MyProxy(Object originalObject){ this.originalObject = originalObject; } public static Object getProxyObject(Object obj){ //プロキシ対象のメソッド・インターフェースを取得します。 Class<?>[] interfaces = obj.getClass().getInterfaces(); //プロキシ対象でない場合は、元オブジェクトを返します。 if(interfaces == null || interfaces.length == 0) return obj; //プロキシ・オブジェクトを返します。 MyProxy instance = new MyProxy(obj); Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), interfaces, instance); return proxy; } @Override public Object invoke(Object interfaceProxy, Method method, Object[] args) throws Throwable { long startNanoTime = System.nanoTime(); StringBuilder sb = new StringBuilder(); for(int index = 0; args != null && index < args.length; index++){ sb.append(", ").append("arg[").append(index).append("]=").append(args[index].toString()); } //メソッド実行前の任意処理 System.out.println("DEBUG OUT method start name="+method.getName()+sb.toString()); //メソッド実行 Object ret = method.invoke(originalObject, args); //メソッド実行後の任意処理 System.out.println("DEBUG OUT method end name="+method.getName()+", return=" +((ret==null)?"void or null":ret.toString()) +", execute time ="+(System.nanoTime()-startNanoTime)+"nsec"); return ret; } } 26 Android で DIxAOP