涼風コンピュータblog

涼風 ・Rubyist, RubyやRuby on Railsに詳しくなっていきたいです

「まつもとゆきひろ 言語のしくみ」を読んで

Rubyのパパであるまつもとゆきひろさんの「まつもとゆきひろ 言語のしくみ」を献本していただきましたので感想を書きたいと思います。

この本は、コンピュータ言語を作成するための設計にはどのようなことを考えたらよいかをまつもとさんが新しく作成したstreemと呼ばれる言語を開発しながら日経Linuxに連載した記事をまとめたものです。

ハッシュテーブル、スタック、リンクリストなどのコンピュータに関する基礎的な知識は必要です。streemの実装はC言語で書かれており、コードも紙面に記述されているので、C言語の知識はあったほうがよいでしょう。

言語設計にあたり、古い言語であるLispだったり、新しい言語swifなどいろいろな言語の文法や実装を参考にしているところが、漠然と考えるのではなく、いろいろな言語を調査して、いいところや悪いところを勘案して、言語を設計してます。

新しい並列プログラム言語streemを題材に本内容は進みます。 unixのパイプラインに着想を得ています。

以下は標準入力の内容を標準出力に渡す文法です。

stdin | stdout

前にした処理のデータを|で次に渡します。streemは並列プログラムに特化しているため、並列プログラムをしやすいように値がかわらないimmutableを採用しています。

まず、並列プログラムしやいように文法を考えて、文法チェッカーをまず作り、それから実際に動作するように作っていきます。

実装面では浮動小数点のNaN(数字でな)領域にいろいろなデータを埋め込むNaN Boxingやガーベージコレクションの仕組みを解説がためになりました。

新しい言語を作ってみたい、言語に興味がある、streemに興味がある方は是非読んでみると良いと思います。

AndroidでToDoアプリを作ってみた

はじめに

Yarulist for Todo.lyはAndroid版のTodo管理アプリです。Todo.lyはTodo管理するサービスです。Todo.lyはWeb,iOSアプリ,Androidアプリ(非公式)があります。また、Web APIが公開されており、アプリからWeb API経由でTodoを閲覧、追加、更新、削除等を行うことができます。

つまり、Yarulist for TodolyはTodo.lyのWeb APIを使用したAndroidアプリです。また、ソースはGitHubここにあります。

アカウント作成

Todo.lyのWebページからe-mail,フルネイム,パスワードを入力し、アカウント作成していください。

ビルド

JDK 1.7, Android Studio 1.0以上が必要になります。ビルドツールにはgradleを使用しています。インストールするAndroid端末をMacにつなげ、ターミナルから次のコマンド実行してください。

$ ./gradlew installDebug

ビルド後、Android端末にインストールします。

ログイン

アプリを起動するとemailとパスワード入力画面になります。emailとパスワードを入力後、ログインボタンをタップして下さい。認証が完了するとやることが表示されます。

f:id:suzukaze7:20151012180100p:plain

やることの閲覧

Todo(やること)はプロジェクト毎に管理されています。タブでプロジェクトを切り替えることができます。完了したやることはチェックボックをタッチすることにより、完了することができます。 また、「完了したやることを表示」により完了したやることを表示することもできます。

f:id:suzukaze7:20151012172639p:plain

やることの追加

画面上部のやることをタップします。ソフトキーボードからやることを入力し、エンターをタップするとやることが選択中のプロジェクトに追加されます。

やることの編集

やること一覧から編集するやることをタップします。編集画面に遷移します。例えば、トマトをタップするとトマトの名称を編集することができます。

f:id:suzukaze7:20151012193649p:plain

プロジェクトの追加

画面上部の[+]アイコンをタップします。プロジェクト追加画面に遷移します。プロジェクトの追加は、Webサーバにプロジェクトの追加を通知し、プロジェクトを追加します。

同期

画面右上の同期アイコンをタップします。アプリとサーバのデータを同期します。内部では、やることの操作を変更履歴として管理し、同期時に変更履歴をWebサーバに通知後、やること情報を再度取得します。

使用ライブラリ

使用しているライブラリについて説明します。

  • OkHttp HTTPの通信に使用しています。
  • Retorofit REST操作に使用しています。
  • RxJava 通信などの非同期処理に使用しています。
  • ButterKnife Viewのインスタンスの割当に使用しています。
  • Gson JSONへの符号化と復号化をします。
  • Material-design-icon アイコンに使用しています。

終わりに

Todo.lyにはプロジェクト以外に本日、週などフィルター、期限設定などの項目があります。これらの実装していない機能をYarulist for Todo.lyに拡充していけたらと思います。

[翻訳] Android開発におけるベストプラクティス

[翻訳] Android開発におけるベストプラクティス

本稿はBest practices in Android development(fork)を翻訳したものです。 オリジナルはBest practices in Android developmentです。

要約

GradleとGradleで推奨されたプロジェクト構造を使用する

gradle.propertiesにパスワードと機密データを記述する

独自にHTTPクライントを実装せずに,VolleyまたはOkHttpライブラリを使用する

JSONデータの解析には、Jacksonライブラリを使用する

65,000メソッド制限のために,Guavaの使用を避け,2,3のライブラリのみを使用する

UI画面を表現するにはFragmentを使用する

Fragmentの管理のためだけにActivityを使用する

レイアウトXMLはコードであり,うまく整理する

レイアウトXMLではattributeの重複は避け,styleを使用する

一つの巨大なファイルは避け,複数のstyleファイルを使用する

colors.xmlは短く,DRYに保ち、パレットとしてのみ定義する

dimens.xmlもDRYに保ち, 一般的な定数を定義する

ViewGroupの階層を深くしない

WebViewでのクライアントサイドでの処理は避け,メモリリークに気をつける

ユニットテストにRobolectricを使用し, 接続(UI)テストにはRobotiumを使用する

エミュレータにはGenymotionを使用する

常にProGuardまたはDexGuardを使用する


Android SDK

Android SDKはホームディレクトリまたは他のアプリケーションに依存しない場所のどこかに置きましょう。インストール時にIDESDKを含んでいる場合は、IDEと同じディレクトリ配下にSDKがあるかもしれません。IDEをアップグレード(または再インストール)する時,またはIDEを変更する時にこれはよくないです。IDEルート権限下ではなく,ユーザー権限下で実行している場合は,sudoパーミッションが必要な別システムレベルのディレクトリに置くことも避けるべきです。

ビルドシステム

デフォルトのビルドはGradleにすべきです。AntはGradleに比べてかなり制限があり,冗長です。Gradleでは,次のように簡単です。

  • アプリのバリアントまたは異なったフレイバーをビルドする
  • 簡単なスクリプトのようなタスクを作る
  • 依存の管理とダウンロード
  • キーストアをカスタマイズする
  • 以上

AndroidのGradleのプラグインも積極的に新しい標準ビルドシステムとしてGoogleによって開発されています。

プロジェクト構造

2つの人気の選択肢があります。: 古いAnt&Eclipse ADTプロジェクト構造と新しいGradle&Android Studioプロジェクト構造です。新しいプロジェクト構造を選ぶべきです。古い構造を使用する場合は,それはレガシーと考え,新しい構造に移植を始めましょう。

古い構造:

old-structure
├─ assets
├─ libs
├─ res
├─ src
│  └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro

新しい構造:

new-structure
├─ library-foobar
├─ app
│  ├─ libs
│  ├─ src
│  │  ├─ androidTest
│  │  │  └─ java
│  │  │     └─ com/futurice/project
│  │  └─ main
│  │     ├─ java
│  │     │  └─ com/futurice/project
│  │     ├─ res
│  │     └─ AndroidManifest.xml
│  ├─ build.gradle
│  └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle

主な違いは新しい構造が明確にGradleから'ソースのセット' (main, androidTest)と概念を分けていることです。例えば, アプリのpaidとfreeフレイバー用のソースコードを持つ'paid'と'free'のソースセットを追加したとしましょう。

トップレベルのappは アプリを参照している他のライブラリ(例:library-foobar)からアプリを区別することに役立ちます。それから,settings.gradleapp/build.gradleが参照することができるライブラリプロジェクトを参照を保持します。

Gradle 設定

一般的な構造 Google's guide on Gradle for Androidを参照してください。

小さなtask (shell, Python, Perlなど)スクリプトのかわりにGradle上でtaskを作成することができます。詳しくは,Gradle's documentationを参照してください。

パスワード アプリのbuild.gradleに, リリースビルド用にsigningConfigsを定義する必要があります。

以下のようにしないでください。これはバージョンコントロールシステムに出てきます。

signingConfigs {
    release {
        storeFile file("myapp.keystore")
        storePassword "password123"
        keyAlias "thekey"
        keyPassword "password789"
    }
}

かわりに, バージョンコントロールシステムに追加すべきでないgradle.propertiesファイルを作成します。

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

このファイルはgradleによって,自動的にインポートされます。それから, 次のようなにbuild.gradleでパスワードを使用できます。

signingConfigs {
    release {
        try {
            storeFile file("myapp.keystore")
            storePassword KEYSTORE_PASSWORD
            keyAlias "thekey"
            keyPassword KEY_PASSWORD
        }
        catch (ex) {
            throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
        }
    }
}

jarファイルをインポートする代わりに, Mavenの依存解決が好ましい 明らかにプロジェクトにjarファイルを含めている場合は, jarは2.1.1のような指定された固定バージョンになるでしょう。jarファイルのダウンロードし, 更新処理することは面倒です。これはMavenが適切に解決する問題で, Android Gradleビルドでも推奨されています。2.1.+のようにバージョンの範囲を指定することができ, Mavenは自動的にパターンマッチングを行い,最新バージョンへの自動更新を取り扱います。

dependencies {
    compile 'com.netflix.rxjava:rxjava-core:0.19.+'
    compile 'com.netflix.rxjava:rxjava-android:0.19.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
}

IDEテキストエディタエディタ

どんなエディタを使用しても,プロジェクトの構造とうまく連携しなければならりません エディタは個人的な選択で,エディタがプロジェクト構造とビルドシステムによって機能するかはあなたの責任です。

現時点で最も推奨されるIDEAndroid Studioです。なぜなら,Android StudioGoogleによって開発されていて,Gradleに最も近く,デフォルトで新しい構造を使用しており,ベータ版の最終段階で,Android開発用だからです。

Eclipse ADTを望むなら,使用することができますが,古いプロジェクト構造でありAntビルドであることが想定されるので,Eclipse ADTを設定する必要があります。Vim,Sublime Tex,Emacsのような平文テキストエディタも使用することができます。この場合では,コマンドラインからGradleとadbを使用する必要があります。Gradleを使用したEclipseのインテグレーションが機能しない場合は,ビルドするためにコマンドラインを使用するか, Android Studioに移行してください。

何を使用するであれ,Gradleと新しいプロジェクト構造がアプリをビルドする公式的な方法のままであることを確認し,バージョンコントロールシステムにエディタ指定の設定を追加することは避けましょう。例えば,Ant build.xmlファイルを追加することは避けましょう。特に,Antでビルド設定を変更している場合は,build.gradleを最新に維持し,機能するようにすることを忘れてはいけません。また,他の開発者に親切にし,他の開発者にツールの好みを強制することも避けましょう。

ライブラリ

JacksonはオブジェクトからJSONの変換と逆変換するJavaライブラリです。Gsonはこの問題を解決するために人気の選択肢です。しかしながら, JSONを処理するのに別な方法(ストリーミング,インメモリtreeモデルと伝統的なJSON-POJOデータバインディング)をサポートしているので,Jacksonはよりパフォーマンスがよいです。JacksonはGSONより大きなライブラリですが場合によって6,5000メソッド制限を避けるためGSONを好むことをもよいかもしれません。他の代替はJson-smartBoon JSONです。

ネットワーク,キャッシュ,画像 あなた自身のクライアントに実装するか考慮すべきバックエンドサーバにリクエストする2つの実証済みの解決方法があります。VolleyまたはRetrofitを使用しましょう。Retrofitを選択する場合は,画像のロードとキャッシュにはPicasso,効率的なHTTPリクエストにはOkHttpを考えましょう。すべての3つのRetrofit,Picasso,OkHttpは同じ会社によって作成されていますので,3つのライブラリはお互いうまく補完しています。OkHttpも Volleyと接続して使用できます。

RxJavaはReactiveプログラミングのためのライブラリです。言い換えると,非同期イベントを処理するためのライブラリです。強力かつ有望なパラダイムで,だいぶ異なるので混乱することもあります。すべてのアプリケーションに構築する前にこのライブラリを使用する前に注意することをおすすめします。私たちによってRxJavaを使用し完了したいくつかのプロジェクトがあります。もしあなたが次の人々(Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen)の一人の間助言が必要なら。私たちは次のブログにブログを書いています。: [1], [2], [3], [4]

以前Rxの経験が全くなければ, APIからのレスポンスだけにRxを適用することから始めましょう。あるいは,クリックイベントや検索領域でのタイピングイベントのような簡単なUIイベント処理にRxを適用することから始めましょう。あなたがRxスキルに自身を持っていてすべてのアーキテクチャに適用したいならすべてのトリック部分をJavadocに書きましょう。

RetrolambdaAndroidと他のJDK8以前のプラットフォームでラムダ表現シンタックスを使用するためのライブラリです。このライブラリは特にRxJavaのような関数スタイルを使用する場合に,コードを頑丈かつ読みやすくします。このライブラリはを使用するためにJDK8をインストールし,Android Studioプロジェクト構造ダイアログでSDK LocationとしJDK8を設定し, JAVA8_HOMEJAVA7_HOME環境変数を設定し, それからプロジェクトルートでbuild.gradleを次のようにしてください。

dependencies {
    classpath 'me.tatarka:gradle-retrolambda:2.4.+'
}

各々のモジュール build.gradleに次のように追加してください。

apply plugin: 'retrolambda'

android {
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

retrolambda {
    jdk System.getenv("JAVA8_HOME")
    oldJdk System.getenv("JAVA7_HOME")
    javaVersion JavaVersion.VERSION_1_7
}

Android StudioはJava8ラムダに関するコードアシスタントサポートを提供します。あなたがラムダを初めて使用する場合は,始めるために次を使用してください。

  • ただひとつのメソッドを持つインタフェースはラムダフレンドリーで,より狭いシンタックスに折りたたむことができます。

  • パラメータに疑いがある場合, 通常の匿名インナークラスを書き, Android Studioがあなたのためにそれをラムダに折りたたみます。

dexメソッド制限に気をつけ, 多くのライブラリを使用することは避けましょう。 Androidアプリはdexファイルとしてパッケージされているとき, 65535個のリファレンスメソッド([1] [2] [3])の厳しい制限があります。制限を超えている場合,コンパイル時に致命的なエラーに遭遇するでしょう。そのため,最小限のライブラリを使用し,制限下でどのライブラリセットを使用できるか決定するdex-method-countsツールを使用しましょう。特にGuavaライブラリを使用することは避けましょう。なぜなら,Guavaライブラリは13,000以上のメソッドを含んでいるからです。

ActivityとFragment

FragmentAndroidでUI画面を実装するためのデフォルトの選択肢とすべきです。ユーザーインタフェース画面を表現するactivityの代わりにfragmentを使用することを推奨します。ここにいくつかの理由を示します。

  • multi-paneレイアウトのための解決方法 携帯電話アプリケーションをタブレット画面に拡張するために主目的に導入されましたので,タブレット画面でpane AまたBのどちらかがすべての携帯電話画面を占有している時, pane AとBの両方を持つことができます。あなたのアプリケーションがはじめからFragmentで実装されている場合,あたなのアプリケーションをことなったフォームファクタに適用することはあとで簡単になります。

  • 画面間の通信 AndroidAPIはあるActivityから別なActivityへの複雑なデータ(例: いくつかのJavaオブジェクト)を送信する適切な方法を提供していません。しかしながら,Fragmentとでは,子Fragmentとの間で通信のチャンネルとしてActvityのインスタンスを使用することができます。たとえ,これはActivityからActivityへの通信より良いとしても,あなたはより明瞭な方法として,イベントバスアーキテクチャ(例: Ottoまたはgreenrobot EventBus)を考慮したいかもしれません。あなたがさらもう一つのライブラリを追加することを避ける場合に,RxJavaはイベントバスを実装するために使用することもできます。

  • FragmentはUIだけでなく一般的に十分です。 UIなしのfragmentActivity用にバックグランドワーカーとして機能します。あなたはActivityにロジックを持つ代わりに, fragment to contain the logic for changing fragmentsを生成するという考え方を持つことができます。

  • ActionBarはFragment内で管理することができます。 ActionBarを管理する目的のみでUIなしの1つのFragmentを持つか, 各々の見えているFragmentが親ActivityのActionBarに自身のアクションアイテムを追加するかを選択することができます。詳細はここ.

そうはいっても, 私たちは広範囲に入れ子のfragmentを使用するように助言しません。なぜなら,matryoshka bugsが起こりうるからです。入れ子のfragmentは理にかなっているとき(例: Fragmentのような画面内に水平スライディングViewPagerないのFragmentだけ),または十分な情報での決断の場合です。

アーキテクチャレベルでは, あなたのアプリは多くのビジネス関するFragmentを含んでいるトップレベルのActivityを持つべきです。メインActivityとの通信が単純でIntent.setData()) または Intent.setAction())が制限されるかまたは類似の場合に限り,他の支援するActivityも持つことができます。

Javaパッケージアーキテクチャ

Androidに関するJavaアーキテクチャはおおよそModel-View-Controllerに近いです。AndroidではFragmentとActivityは実際にはコントローラークラスです。 一方, FragmentとActivityは明示的にユーザーインターフェースの部分ですから,Viewでもあります。

このため, Fragment(またはActivity)を厳密にコントローラーとビューに分類することは難しいです。Fragmentはfragmentsパッケージに置くことがより良いです。前のセクションに従う限りは,Activityはトップレベルに置くことができます。2つまたは3つ以上のActivityを持つ予定なら,activitiesパッケージも作成しましょう。

そうでなければ,アーキテクチャAPIレスポンスでJSONパーサーを通して入ったPOJOを含むmodels, あなたのカスタムView, 通知, action bar view, widgetなどを含むviewを持った典型的なMVCのように見えることができます。 Adapterはグレー要素で, データとViewの間に存在します。しかしながら, それらは典型的にgetView()経由で外出しする必要があるので, あなたはviews内のサブパッケージにadaptersを含むことができます。

いくつかのコントローラークラスはアプリケーション全体であり,Androidシステムに近いです。それらはmanagersパッケージに置くことができます。「DateUtils」のような雑多なデータ処理クラスはutilsパッケージに置きます。バックエンドで通信する役割のクラスはnetworkパッケージに置きます。

All in all, ordered from the closest-to-backend to the closest-to-the-user:

com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
   ├─ adapters
   ├─ actionbar
   ├─ widgets
   └─ notifications

リソース

名前付け type_foo_bar.xmlのように接頭語に型を付ける慣例に従いましょう。例 : fragment_contact_details.xml, view_primary_button.xml, activity_main.xml.

layout XMLを整理する レイアウトXMLの書式化する方法に自信がなければ, 次の慣例が役に立つかもしれません。

  • 一行につき一つの属性で, 4つの空白のインデントにします。
  • はじめの属性はいつもandroid:idにします。
  • android:layout_****属性は上部に置きます。
  • style属性は下部に置きます。
  • 属性の順序の入れ替えと追加を容易にするために, 単独の行に閉じタグ/>を置きます。
  • android:textにハードコーディングするよりむしろ, Android Studioで使用できるDesigntime attributesを使用することを考えてください。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="@string/name"
        style="@style/FancyText"
        />

    <include layout="@layout/reusable_part" />

</LinearLayout>

大体, android:layout_****属性はレイアウトXMLに定義すべきで,一方他のandroid:****属性はスタイルXMLに定義すべきです。このルールには例外があるが, 一般的にはうまく機能します。この考えはレイアウトファイルにレイアウト(位置, マージン, サイズ)とコンテンツ属性だけを置き, 一方スタイルファイルにすべての見た目の詳細(色, パディング, フォント)を置きます。

例外は

  • android:idは明らかにレイアウトファイルに置くべきです。
  • LinearLayout用のandroid:orientationは通常レイアウトファイルに置くことが理にかなっています。
  • android:textはレイアウトファイルに置くべきです。なぜならそれはコンテンツを定義するからです。
  • ときどきデフォルトでandroid:layout_widthandroid:layout_heightはレイアウトファイルにあるべきですが, 一般的なスタイルがandroid:layout_widthandroid:layout_heightを定義することは理にかなっているでしょう。

スタイルを使用する。 ほとんどのプロジェクト毎に適切なスタイルが必要になります。なぜなら、ビューに関して繰り返しの外観を持つことはとても一般的であるからです。少なくとも、アプリケーションで最も多いテキストコンテンツに関する共通スタイルを持つべきです。たとえば

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

TexTiewに適用します。

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

あなたはたぶん,ボタンに関して同じことをするでしょう。しかし,そこではまだしません。そこを通り越して、関係しているグループと繰り返されるandroid:****属性は共通スタイルに移動させましょう。ビルドシステムにおいていくつかの意味を持つリソースディレクトリ名とは異なり,res/valuesにあるファイル名は任意にすることができます。

大きなスタイルファイルは他のファイルに分けましょう。 一つのstyles.xmlにする必要はありません。Android SDKは形にとらわれない他のファイルをサポートしています。stylesに関して魔法は何もありません。肝心なところはファイル内のXMLタグ<style>です。したがって、あなたはstyles.xml, styles_home.xml, styles_item_details.xml, styles_forms.xmlを持つことができます。

colors.xmlはカラーパレットです。 colors.xmlでカラー名とRGBA値にマッピング以外に他になにかあってはならいです。違ったタイプのボタンに関してRGBA値を定義するcolors.xmlを使用することは止めましょう。

このようにはしない:

<resources>
    <color name="button_foreground">#FFFFFF</color>
    <color name="button_background">#2A91BD</color>
    <color name="comment_background_inactive">#5F5F5F</color>
    <color name="comment_background_active">#939393</color>
    <color name="comment_foreground">#FFFFFF</color>
    <color name="comment_foreground_important">#FF9D2F</color>
    ...
    <color name="comment_shadow">#323232</color>
  • 代わりにこのようにします:
<resources>

    <!-- grayscale -->
    <color name="white"     >#FFFFFF</color>
    <color name="gray_light">#DBDBDB</color>
    <color name="gray"      >#939393</color>
    <color name="gray_dark" >#5F5F5F</color>
    <color name="black"     >#323232</color>

    <!-- basic colors -->
    <color name="green">#27D34D</color>
    <color name="blue">#2A91BD</color>
    <color name="orange">#FF9D2F</color>
    <color name="red">#FF432F</color>

</resources>

このパレットはアプリケーションのデザイナーにお願いしましょう。この名前は"green", "blue"などのようなカラー名は必要ありません。"brand_primary", "brand_secondary", "brand_negative"のような名前も完全に許容可能です。色をフォーマットすることはそれ自体,色を変更またはリファクタしやすく, どのくらい違った色が使用されているかが明白になるでしょう。通常,美しいUIのためには、さまざまな色が使用されることを減らすことが重要です。

colors.xmlのようにdimens.xmlを扱う。 あなたは色の場合と基本的に同じ目的のために, 典型的な空白とフォントサイズの"パレット"も定義すべきです。dimensファイルのよい例は:

<resources>

    <!-- font sizes -->
    <dimen name="font_larger">22sp</dimen>
    <dimen name="font_large">18sp</dimen>
    <dimen name="font_normal">15sp</dimen>
    <dimen name="font_small">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_huge">40dp</dimen>
    <dimen name="spacing_large">24dp</dimen>
    <dimen name="spacing_normal">14dp</dimen>
    <dimen name="spacing_small">10dp</dimen>
    <dimen name="spacing_tiny">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_tall">60dp</dimen>
    <dimen name="button_height_normal">40dp</dimen>
    <dimen name="button_height_short">32dp</dimen>

</resources>

あなたは文字列を通常扱うように, 値をハードコーディングする代わりにマージンとパディングでレイアウトのspacing_**** の大きさをを使用すべきです。これは一貫性のあるルック&フィールを与えると同時にスタイルとレイアウトを整理や変更使用すくなります。

viewsの深い階層を避ける。 ときどきあなたはビューを整理するために,ただ,さらにもう一つのレイアウトを追加したくなるかもしれません。この主の状況は起こるかもしれません:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <RelativeLayout
        ...
        >

        <LinearLayout
            ...
            >

            <LinearLayout
                ...
                >

                <LinearLayout
                    ...
                    >
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

たとえあなたはレイアウトファイルで明示的にこれを目撃しないとしても,あなたが他のビューの中にビューを(Javaで)追加するならそれは起こって終わるかもしれません。

2つの問題が起こるかもしれません。あなたは性能問題を経験するかもしれません。プロセッサは制御が必要な複雑なUIツリーがあるからです。もう一つの深刻な問題はStackOverflowErrorの可能性です。

それゆえ, できる限りビュー階層を平らに維持しましょう: RelativeLayoutを使用する方法, optimize your layoutsする方法と<merge> tagを使用することを学びましょう。

WebViewに関する問題について注意しましょう。 例えば,ニュース記事のようなWebページを表示しなければならないとき,クライアント側がHTMLをきれいにする処理をするうことは避け, むしろバックエンドプログラマー純粋なHTMLを要求しましょう。ApplicationContextにバインドされる代わりに,WebViewがActivityの参照を保持するとき,WebViews can also leak memory。簡単なテキストまたはボタンのためのWebViewを使用することを避け, TextViewまたはButtonを使用しましょう。

テストフレームワーク

Android SDKのテストフレームワークはまだ幼児です。特にUIテストに関するものがそうなります。Android Gradleは現在作成したJUnitテストを実行するconnectedAndroidTestと呼ばれるテストタスクを実装しています。また,extension of JUnit with helpers for Androidを使用しています。これはデバイスまたはエミュレータに接続してテストを実行する必要があることを意味しています。テストに関する公式ガイド[1] [2]に従いましょう。

ViewではなくユニットテストだけにRobolectricを使用する。 Robolectricは開発スピードのために"デバイスに接続していない"テストを提供しようとするテストフレームワークです。特にモデルとビューモデル上のユニットテストに適しています。しかしながら, Robolectric下でのテストはUIに関して不正確で不完全です。あなたはダイアログ,アニメーションなどに関するUI要素をテストする問題を持っているでしょう。これはあたなが「暗闇の中を歩いている。」(制御される画面を見ることなくテストすること)という事実によって複雑になるでしょう。

RobotiumはUIテストを記述することを簡単にします。 あなたはUIケースの接続テストを実行するためにRobotiumは必要ありませんが, それはビューの取得または分析と画面制御する多くのヘルパーがあるため,たぶんあなたに利益をもたらします。テストケースは次のように簡単です:

solo.sendKey(Solo.MENU);
solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
solo.clickOnText("Preferences");
solo.clickOnText("Edit File Extensions");
Assert.assertTrue(solo.searchText("rtf"));

エミュレータ

あなたがAndroidアプリをプロとして開発する場合は,Genymotion emulatorのライセンスを購入しましょう。 Genymotionエミュレータは典型的なAVDエミュレータより毎秒フレームレートが速く実行します。それらはアプリをデモするまたはネットワーク接続品質とGPS位置のエミュレートするなどのツールを持っています。それらは接続テストにも最適です。あなたは多くの(全てではなく)異なったデバイスにアクセスするので, Genymotionのライセンスの費用は複数の実デバイスを買うより実際はかなり安いです。

注意事項: GenymotionエミュレータGoogle PlayストアとMapsのような全てのGoogleサービスを提供するわけではありません。あなたはサムスン仕様のAPIをテストするかもしれません。そのときはリアルサムスンデバイスを所有する必要があります。

Proguard構成

ProGuardは通常パッケージ化されたコードを縮小し,難読化するためにAndroidプロジェクト上で使用されます。

あなたがProGuardを使用するかしないはあなたのプロジェクト構成に依存します。通常,リリースapkをビルドするときProGuardを使用しするようにgradleを構成するでしょう。

buildTypes {
    debug {
        runProguard false
    }
    release {
        signingConfig signingConfigs.release
        runProguard true
        proguardFiles 'proguard-rules.pro'
    }
}

どのコードが予約されなけらばならないか,どこのコードが捨てるかまたは難読化されるかを決定するために, あなたはコードに1つ以上エントリーポイントを指定しなければなりません。それらのエントリーポイントは典型的な主なmethod, applet, midlet, activityなどを含むクラスです。 AndroidフレームワークSDK_HOME/tools/proguard/proguard-android.txtに記述されたデフォルト構成を使用します。カスタムプロジェクト指定proguardルールは(my-project/app/proguard-rules.proに定義されるような)デフォルト構成に追加されます。

ProGuardに関係した共通問題はClassNotFoundException, NoSuchFieldExceptionまたはそれに似たもので始まるアプリケーションクラッシュを見ることです。たとえ,ビルドコマンド(例 assembleRelease)が警告なしに成功しても見ましょう。 これは2つのうちのいずれかを意味します:

  1. ProGuardは必要ないと考えられるクラス, 列挙(enum), メソッド, フィールドまたはannotationは削除します。
  2. ProGuardはクラス, 列挙(enum)またフィールド名は難読化(リネイム)されますが, それは元の名前たとえばJavaリフレクションをによって間接的に使われています。

問題のオブジェクトが難読化されているを確かめるためにはapp/build/outputs/proguard/release/usage.txtを調べてください。

ProGuardが必要なクラスまたはクラスメンバを取り除くことを防ぐためには, あんたのproguard設定にkeepオプションを追加します:

-keep class com.futurice.project.MyClass { *; }

ProGuardがクラスまたはクラスメンバを難読化することを防ぐにはkeepnamesを追加します:

-keepnames class com.futurice.project.MyClass { *; }

例はthis template's ProGuard configを調べてください。

例はさらにProguardを参照してください。

Tip。 あなたがユーザーに公表しているリリース毎のmapping.txtファイルを保存します。各リリースビルド用のmapping.txtファイルのコピーを保持することにより, ユーザーがバグに遭遇し, 難読化されたスタックトレースを送信するなら, あなたはあなたが問題をデバッグすることがでることを保証します。

DexGuard。 もしあなたが最適化されたハードコアツールと特別な難読化リリースコードが必要なら, ProGuardをビルドする同じチームが作成した商用ソフトウェアであるDexGuardを考慮してください。それは65000メソッド制限を解決するためにDexファイルを簡単に分割することもできます。

謝辞

Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton とAndroid開発に関する知識を共有するう他のFuturice開発者に感謝します。

ライセンス

Futurice Oy Creative Commons Attribution 4.0 International (CC BY 4.0)

Jun Hiroe Creative Commons Attribution 4.0 International (CC BY 4.0)

railsチュートリアルをやってみた

はじめに

railsチュートリアルをやってみました。rails4.0とrails3.2がありますが、本文に初心者はrails3.2がよいとあったので、3.2にしました

http://railstutorial.jp/?version=3.2#top

気づいたところや、つまずいたところを書きたいと思います

第1章

  • herokuでpostgresを使用するとエラーになる

Gemfileに以下を設定してPostgresを本番環境で使用できるようにします

group :production do
  gem 'pg', '0.12.2'
end

git push heroku masterでエラーになる場合にpostgresをherokuサーバーに準備する

$ heroku addons:add heroku-postgresql
$ heroku config

herokuについて

知っておきたい!Herokuを使う上では当たり前?の16の常識

このblogで1ヶ月1アプリ1dynoは750時間まで無料ということをしりました 750 / 24 = 31なので、1アプリで1dynoなら無料で使えますね。ただし、1アプリで2dynoだと2倍の時間が消費されるので、気をつけましょう

終わりに

現在、第3章目の途中です。気づいた点があったら、また書きます

Web(Rails),iOS(Objective-C),Android(Java)で動作するCI(Continuous Integration)を探す

はじめに

Web(Rails),iOS(Objective-C),Android(Java)で動作するCI(Continuous Integration)を探しました

調査したCI

以下のCIを調査しました。ruby, iOS, Androidに対応していないものは除外しました

  • wercker

http://wercker.com/

無料

対応言語(http://devcenter.wercker.com/articles/languages/)

PHP
Python
Ruby(Sinatra/Rails and Heroku/Rails4 project)
Node.js
Go
java:android(Android application using android studio version 0.4.3)
  • Circle CI

https://circleci.com/

対応言語(https://circleci.com/docs)

Ruby/Rails
Python
Node.js
PHP
Java(Oracle JDK 7, using Java 1.7.0_21ほか)
Haskel
  • Mangnum CI

https://magnum-ci.com/

対応言語(https://magnum-ci.com/docs)

Ruby
Node.js
Go
PHP

プライベートレポジトリ無料

  • Drone.io

https://drone.io/

対応言語(http://docs.drone.io/)

C / C++
Dart
Go
Haskel(New)
Groovy
Java(OpenJDK 6, OpenJDK 7, Sun JDK 8)
Node.js
PHP(Beta)
Python(Beta)
Ruby(Beta)
Scala

25$/月 5プライベートレポ

  • CODESHIP

https://www.codeship.io/

対応言語

Ruby
NodeJS
Python
Dart
PHP
Java(Java 7)
Scala
Groovy
Clojure
Go

https://travis-ci.com/

$129/月 プライベートレポ

オープンソース(完全無料) パブリックレポ

対応言語(http://docs.travis-ci.com/)

 C
 C++
 CLOJURE
 ERLANG
 GO
 GROOVY
 HASKELL
 JAVA (Androidの設定例あり)
 JAVASCRIPT(WITH NODE.JS)
 OBJECTIVE-C
 PERL
 PHP
 PYTHON
 RUBY
 SCALA

http://www.cloudbees.com/

3user 無料 100分/month

5user $60/month

対応フレームワーク(https://wiki.cloudbees.com/bin/view/RUN/WebHome)

Grails
Raio
Rub on Rails(ただし、JRuby)
Clojure/Leinigen
Playframework
SBT(scala)
PHP
Drupal

MOBILE対応(http://www.cloudbees.com/mobile)

iOS
Android
  • Shippable

https://www.shippable.com/

5プライベートレポ 無料/月

10プライベートレポ 10$/月

対応言語(http://docs.shippable.com/en/latest/)

Ruby
Python
Node.js
Java
Scala
PHP
  • Semaphore

https://semaphoreapp.com/

1プロジェクト $14/月

5プロジェクト $39/月

対応言語

Ruby
Node.js
Clojure
Elixir
Erlang
Go
Java
Perl
Python

Java

CIにはJavaとあって、Open SDK, Oracle SDKと記述されているが、Androidについて記述がない場合はできるかわからないので、Androidできるところから除外しています

Rails, iOS, Androidが使用できるCI

$129/月 プライベートレポ

オープンソース(完全無料) パブリックレポ

iOS, Androidが使用できるCI

3user 無料 100分/month

5user $60/month

Rails, Androidが使用できるCI

  • wercker

無料

Androidandroid studio version 0.4.3となっているので、android studioのプロジェクトが必要なのでしょう

まとめ

(1) 複数のCIを使用する Cloud Bees (Jenkinsのクラウド版)でiOS, AndroidのCIを行い、werckerでrailsのCIが行うのが良いのではないでしょうか。 ただし、Cloud Beesは無料にするにはテスト時間を100分/月にしなければなりません

また、実際に使用できるかまでは確認していません。webページの仕様を確認しただけです

(2) Travis CIを使用する

参考

iOSテストフレームワーク比較 XCTest vs GHUnit

はじめに

iOSで簡単なテストをするために、XCTestとGHUnitを比較します。XCTestはXCode 5.0に統合されているテストフレームワークです。

比較表

項目 XCTest GHUnit
Xcodeによるサポート あり なし
実行UI XCode GUI
setup/tearDown あり あり
テスト範囲 ロジックテスト, 非同期,UIViewなど ロジックテスト, 非同期,UIViewなど
導入のしやすさ 簡単 やや難
CI CI依存 CI依存

※ GHUnitついてはGHUnitを用いた単体テストを参考にしています

※ CIはいろいろあるので、CIが対応していれば可能です

終わりに

iOSで簡単なテストするには、どちらでもできるでしょう。導入が容易なXCTestをおすすめします。あとは、選ぶ条件としてはCIが対応しているかでしょうかね

iOSテストフレームワーク(XCTest)を試してみた

はじめに

iOSテストフレームワークでXCTestを試してみました。環境はMac OS X 10.9.2, Xcode 5.1で行いました。XCodeに統合されており、XCodeから実行できます

XCTest

Xcodeユニットテスト ガイドを参考にしました

ロジックテストとアプリケーションテスト

ロジックテストは、各コンポーネントが正常に動作するかを確認するユニットテストです。シュミレータ上でしかできません。

アプリケーションテストは、Xcodeユニットテスト ガイドによると

このテストは、アプリケーションのコンテキストでコードのユニット
をチェックします。アプリケーションテストを使用して、ユーザインターフェイスコントロール
の接続(接続口とアクション)が適切であることと、コントロールとコントローラオブジェクト
が、アプリケーションに適用したオブジェクトモデルに基づいて正しく動作することを保証でき
ます。このテストを使用して、アプリケーションが動作しているデバイスの位置を取得するな
ど、ハードウェアのテストも実行できます。

今回は、アプリケーションテストで試しました

ユニットテストターゲットをプロジェクトに追加

  1. アプリケーションテストするプロジェクトを開きます
  2. File > New > Targetをクリックします
  3. iOSのother > Cocoa touch Unit testing Bundleを選択し、nextをクリックします
  4. ProductNameに「XXXTests」(末尾をTestsにする), Company Identfierを適当に(例:jp.co.xyz)入れ, TypeをXCTestを選択し、Finishをクリックします
  5. 左側のフォルダ表示にProductNameに設定した「XXXTests」フォルダが作成され、XXXTests.mがデフォルトのユニットテストのファイルになります

XXXTests.m

#import <XCTest/XCTest.h>

@interface XXXTests : XCTestCase

@end

@implementation XXXTests

- (void)setUp
{
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown
{
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample
{
    XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}

@end

setUpメソッドが各テストのはじめに呼ばれます。tearDownメソッドが各テストの終わりに呼ばれます。testで始まるメソッドがテスト対象のメソッドです。デフォルトではtestExampleメソッドが定義されており、必ず失敗するXCTFail()関数が呼ばれています

アプリケーションテストの設定

  1. 左側のフォルダ表示で、プロジェクトを選択します。Targetから先ほど追加した「XXXTests」を選択します。次に「Build Setting」を選択します
  2. 「Build Setting」の「All」をクリックします
  3. 「Bundle Loader」を以下のように設定します
iOS: $(BUILT_PRODUCTS_DIR)/<app_name>.app/<app_name>

この値はDebugとReleaseに設定されます 4. 「Test Host」を以下のように設定します

$(BUNDLE_LOADER)
  1. 停止ボタンの右のプロジェクト名をクリックし、scheme editをクリックします
  2. 左のTestを選択します。テスト用のターゲットを選択します。画面下の[+]をクリックし、先ほど追加した「XXXTests」のテストターゲットを追加します

テストの確認

  1. メニューから「Product」> 「Test」を実行します
  2. メニューから「View」> 「Navigators」> 「Show Log Navigator」をクリックします。左から実行したテストを選択すると、右側に結果が表示されます。現在、testExampleメソッドが必ず失敗します

テストの記述

1.テスト対象となるクラスを追加します。アプリ本体のターゲットに、Utilクラスを追加します

Util.h

#import <Foundation/Foundation.h>

@interface Util : NSObject

+ (BOOL)isMutipleOf3:(NSInteger)num;

@end

Util.m

#import "Util.h"

@implementation Util

+ (BOOL)isMutipleOf3:(NSInteger)num
{
    if (num % 3 == 0) {
        return YES;
    }
    else {
        return NO;
    }
}

@end

Util.isMutipleOf3メソッドは、整数が3の倍数であるとき真、そうではないとき偽を返します

2.テストを記述します。先頭に#import "Util.h"を追加し、testExampleを以下のように書き換えます

XXXTests.m

#import <XCTest/XCTest.h>
#import "Util.h"

@interface XXXTests : XCTestCase

@end

@implementation XXXTests

- (void)setUp
{
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown
{
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample
{
    XCTAssertTrue([Util isMutipleOf3:9], "3の倍数ではありません");
}

@end

3.メニューから「Product」 > 「Test」でテストします。テスト失敗にならなければ成功です

4.テストマクロ

いくつかテストマクロを紹介します。詳しくはXcodeユニットテスト ガイドの「ユニットテスト結果用マクロのリファレン」を参照してください

4.1 nilテスト

  • XCTAssertNil
  • XCTAssertNotNil

4.2 trueテスト

  • XCTAssertTrue

4.3 falseテスト

  • XCTAssertFalse

4.4 等価テスト

  • XCTAssertEqualObjects
  • XCTAssertNotEqualObjects
  • XCTAssertEqual
  • XCTAssertNotEqual

4.5 例外テスト

  • XCTAssertThrows

非同期

確認していませんが、XCTestで非同期ブロックのテストを書くで非同期処理のテストも書けるようです

おわりに

Travis CIでXCTestを実行できるようです

Travis CI で XCode プロジェクトを自動テストする方法

XCTestはXCodeに統合されているので、導入が簡単で、XCodeから実行できるところがいいところだと思います。

GHUnitについてはGHUnitを用いた単体テストが参考になると思います