アプリ開発スケジュールの立て方

最近とあるスマートフォンアプリの開発をしていまして、その開発スケジュールを立てることになりました。

ただ開発スケジュールについては今まで立ててもらってばかりで、自分で立てた経験が無いなーと思ったので、立て方について色々と調べたり経験者の方に聞いたりしてみました。

その内容のまとめをちらっと会社の日報に書いていたのですが、あとで見返せるようにブログにおこしておくことにしました。

マイルストーンを明確に設定すること

  • そもそもマイルストーンとは?…
    • 道路に1マイルごとに置かれた標石のこと
    • スケジュール上の「重要な節目」となる日
  • 設定しておくことで…
    • スケジュール遅延を早期に認識することができる
    • 目標が出来ることによるチームメンバーのモチベーション向上

スケジュール、コスト配分の目安

  • 目安となるスケジュール、コストの配分としては、設計:3分の1、開発:3分の1、テスト:3分の1 程度
    • この配分は従来のシステム開発の場合の配分なので、あくまで参考
    • アプリ開発の場合は体系立てて設計やテストの期間をきっちりと取らずに、開発と並行してそこら辺をカバーしていくことも
    • 品質を重視するなら、テストの配分をもっと増やす
  • バッファも含めて余裕のある開発期間を取るよりは、テスト期間やバッファのための期間を作るようがよい

スケジュールの引き方の手順

  1. 大枠のマイルストーンを決める(リリース日など)
  2. 各開発者の稼動日を分かる範囲で明らかにしておく
  3. 必要なタスクを洗い出す
  4. タスクの作業工数を決定する
    • 開発者を含めた複数の人が複数の視点で決定することが望ましい
    • マイルストーンに作業が収まり切らない場合は人員投入や複数人での並行作業も検討
    • 全てのタスクの工数を出した時点で現状の人員で大枠のマイルストーンを達成可能か確認する
  5. タスクの優先度を決める
  6. タスク間の依存関係を明らかにする(あれが終わってないとこれが出来ないとか)
  7. タスクの担当者を決め作業工数を元にスケジュールを引いていく
    • タスクの対応順番は依存関係や優先度を考慮して決める
  8. プロジェクトの重要なポイントとなる節目を決め細かいマイルストーンを追加する(○○機能完成など)
  9. 出来上がったスケジュールを見直し確認する(ウェブ管理の場合はガントチャートを見るとよい)

Backlog や Redmine などの Web ツールを用いる場合もエクセルを用いてスケジュール管理する場合も同様です。

出来上がったスケジュール確認で見るべきポイント

  • スケジュールの実現性や余裕感
    • 多少のことが起きてもリスケしなくても大丈夫なスケジュール
  • 作業間の依存関係が正しいかどうか
  • 担当者が同じ期間に複数の作業をしていないかどうか
  • タスクの人員アサインが最適かどうか
    • タスクの難易度に対しての開発者の技量の考慮
    • 開発者の得意分野の考慮

プロジェクトの中心はやはり人

  • 最も忘れてはならないこと

ついでに最近の創作メモ帳について

開設当初はPHPやウェブ系技術のことばかり書いてたのに、最近は上流工程のことやらMac設定云々の話題やら、幅広くなってます。。

だんだん内容がブログ説明文にそぐわなくなってきて、方向性が迷走してるような気がしますが気にしないことにしますw

たぶんまたPHPに戻りそうなので。たぶん。

2014/11/11: スケジュールの引き方の手順など少し更新しました。

Androidのアドレス帳を読み書きするContactsAPIとは何者か暴く

Android Contacts APIとは、どんなAPIか その可能性

AndroidSDKは端末内部のアドレス帳へアクセスするためのインターフェースとなるContactsAPIを用意しています。

端末内連絡先という重要なリソースへのアクセスを担うContactsAPIはアプリ開発の幅を広げるためには重要なAPIではないでしょうか。

ですが、このAPIの仕様は煩雑で癖が強いです。直感的に欲しいデータにアクセスできませんし、書き込みもできません。

根本的なContactsAPIの概念的な部分を分かっていないとちょっとイライラすると思います。

また、似ているアドレス情報の連絡先を勝手に集約してまとめるような仕組みがAndroidOSレベルで用意されていたりするため開発者の混乱を招く原因になっていたりします。

また、データにアクセスするためのキー項目の特徴を知っていないと思わぬことが起きたりします。

ネット上に散らばっているサンプルソースを取り敢えず動かしてみて「何かよく分からないけど欲しいデータが取れた!」「でもホントはこういうデータを取り出したいんだけどどう書けばいいか分からない」というケースが結構想定されるAPIなのではないかなーと思います。

ContactsAPIについての抑えるべきポイントと概要を説明していきます。

Androidではアドレス帳をどういった形態で保持しているか

Android内部ではSQLiteに連絡先データが保存されているようです。
ただ、そのSQLiteデータベースに直接アクセスすることはできません。危険すぎます。

そこでアクセスインターフェースとしてContactsAPIが用意されています。
ContactsAPIもかなりSQLite側を意識した作りになっているため、
アクセスの仕方自体はほぼ変わりはないです。

アドレス帳データのSQLiteのテーブル設計はどうなっているか

Android内部のDB設計が分かっていないばかりに以前苦労した記憶があります。

まさに「何かよく分からないけど欲しいデータが取れた」状態で使っていましたが、テーブル構成が分かった瞬間にかなり道がひらけました。

これをもっと早く知っていればよかった…と思いましたが、同じ思いをする人が一人でも減ってくれることを願いER図を用意しました。

AndroidContactsAPIのER図

※緑のフィールドは外部キーです。主要なフィールドのみ載せています。

SQLiteは全てのテーブルに_idという一意のサロゲートキーを必ず持ちますが、ContactsAPIにおいてもSQLiteシステムの_idを主キーとして利用しています。

全てのテーブルに_idがあるという点が一つのポイントとなります。

それではテーブルごとに概要を説明していきます。

dataテーブル

上記ER図中では最小単位となるテーブルで、行ごとに電話番号やEメールアドレスといった実データが保存されています。ER図の関係の通り一つのraw_contactsレコードに所属するデータが複数あり、データの数だけdataレコード沢山があります。

そのデータ種別を区別するためにMIMEタイプというフィールドが用意されています。種類についてはContactsContract.CommonDataKindsのリファレンスを参照してください。

また、実データはdata1, data2といったフィールドに格納されています。MIMEタイプごとにそれぞれのdataが何を表すかということが決められています。

例えば電話番号の場合はdata1に電話番号、data2に種別(自宅や勤務先)、data3にラベルが格納されています。MIMEタイプごとのdataフィールド群の対応については、先ほどのContactsContract.CommonDataKindsのリファレンスからたどって調べれば分かると思います。

raw_contactsテーブル

dataテーブルにある一人分の名前や電話番号のデータレコードを一つにまとめます。1レコードで一人分のデータを表現します。直訳で生のコンタクトテーブルになり、後述のコンタクトテーブルよりもより直接的なデータとなります。

アカウント名やアカウントタイプといったフィールドもありますが、これは外部のクラウドストレージサービスの情報になります。例えば自分のGoogleアカウントやDocomoアカウントと紐付けて保存されていたりします。

contactsテーブル

このテーブルがクセモノです。いくつかのraw_contactsテーブルのレコードを更にまとめます。

どういうことかというとAndroidには似ている連絡先情報を自動で集約する仕組みが備わっており、ある基準で似ている連絡先と判断された連絡先を一つにまとめるためにこのテーブルは用意されています。

つまり、いくつかの似ているrow_contactsレコードをひとまとめにしてcontactsレコードを持つことがあるということです。ただ、この集約は恒久的なものではなく自動的に集約が解除されたりもします。

何を持って似ているかという判断基準はOSでちゃんと定められています。例えば姓名がそれぞれ一致したとか、姓だけ一致したら更にうんにゃらとか。興味がある人は調べてみるとよいでしょう。

こういった仕組みが用意されている意味としては、raw_contactsテーブルでは複数のアカウントの情報を持つ関係上、クラウドの連絡先と同期をとった時に似たような同一人物のデータが複数端末内にできてしまうため可能な限りそれを一括りにまとめようというような目的のようです。

一般的にユーザーに連絡先データを表示する場合はcontactsテーブルのレベルで見せるべきです。そのためのビューも提供されています。

自動集約の弊害

普通に考えて一人を特定するためのキーとしてはcontactsテーブルの_id(contacts_id)があればよいこととなります、が、集約機能のための弊害があります。

自動集約でレコードがまとめられる時にcontacts_idが変わってしまうことがあります。なのでcontacts_idをユーザーを特定するための恒久的なキーとして利用すべきではありません。

では、恒久的に1ユーザーを特定するためにはどうするのか。そのためにルックアップキーというものが用意されています。ユーザーへの参照をアプリ内で持っておきたい場合はこのキーを保持しておくのがよいでしょう。ただ、このキーにもデメリットがありますので、次の項の中で解説します。

プログラムコードサンプル

実際にコードサンプルを紹介していきます。

アドレス帳内の全コンタクトにループ処理でアクセスする

ループで全ユーザーにアクセスします。上記ER図でいうところのcontactsテーブルへのアクセスになります。

Cursor c = contentResolver.query(Contacts.CONTENT_URI, new String[] {Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME },null, null, null);
c.moveToPosition(-1);
while (c.moveToNext()) {
    // カーソルからデータ取り出し
    int contactsId = c.getInt(0);
    String lookupKey = c.getString(1);
    String displayName = c.getString(2);
    // ダンプ
    Log.d("contacts", "contactsId" + contactsId);
    Log.d("lookupKey", "lookupKey" + lookupKey);
    Log.d("displayName", "displayName" + displayName);
}

ルックアップキーで特定のユーザーの表示名を取得するコード例

ルックアップキーは基本的に固定の検索キーで、ユーザーを特定するためのキーとしては最適ですが検索キーとしての高速性に欠けます。

以下がルックアップキーのみでUriを作成し名前を取得する例です。ループで大量に処理をしたりしないのであればこの方法でも問題ないでしょう。

Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);

Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, ...);
try {
    c.moveToFirst();
    String displayName = c.getString(0);
} finally {
    c.close();
}

ルックアップキーとコンタクトIDを組み合わせたユーザー検索

contacts_idによる高速な検索とルックアップキーによる確実な検索の2つのメリットを合わせたユーザー検索方法が予め用意されています。

まずcontacts_idでの検索を試みて、失敗した場合はルックアップキーを利用した検索を行なってくれます。

大量にデータを処理する場合はこの方法でUriを作成すべきです。

Uri lookupUri = Contacts.getLookupUri(contactId, lookupKey);

Dataテーブルの実データの取得

contacts_idを元に電話番号を取得してみます。一人に対して複数の電話番号が設定されている場合があるのでカーソルループで取得します。

Dataテーブルには電話番号以外のデータも沢山入っているため、Where句でMIME TYPEで絞り込んでいます。

Cursor cursor = null;
try {
    cursor = contentResolver.query(Data.CONTENT_URI, null,
        Data.CONTACT_ID + " = ? AND " + Data.MIMETYPE + " = ?",
        new String[] { contactsId, Phone.CONTENT_ITEM_TYPE }, null);
    // 電話番号ループ
    cursor.moveToPosition(-1);
    while (cursor.moveToNext()) {
        String tel = cursor.getString(cursor.getColumnIndex(Data.DATA1));
        Log.d("tel", tel);
    }
} finally {
    cursor.close();
}

ContactsAPIまとめ

テーブル構成と自動集約に伴う罠はありますが、逆にいうとそこら辺さえ抑えればさほど難しくないと思います。

テーブル構成さえ分かっていれば上記で載せたサンプルコード以外にも色々と応用したアドレス帳アクセスもできるかと思います。

あと今回はサンプルコードを載せませんでしたが、プロフィール画像についてもDataテーブル内にBlobで直接格納されています。ちょっと探せばサンプルあるはずです。

それではよいContactsAPIライフを。

参考サイト

Mac初心者の私がMacBook Airを買って行った設定まとめ

こんにちは。最近ひそかにはてなブックマークのホットエントリ入りを夢見て目指しているプログラマの山本です。今日はいいネタを仕入れたので記事にしたいと思いますw

WindowからMac OS Xへ

私は今まで15年間ほどWindowsユーザーでした。今でも自宅のデスクトップはWindows7で、メインのパソコンです。

そんな中でスマートフォンアプリ開発に携わる機会も増えてきまして、iPhoneやAndroidのアプリ開発をハイブリットに行うことができるMacBook Air(mid2012)を買ってしまいました!職場の社員の半数がMacbookユーザーという職場にいるのですが、この度やっと仲間入りできましたw

MacBook Air開封写真

いろいろ設定をカスタマイズしてみて数日使ってみたところ、かなりバランスのいいモバイル端末ということがわかりました。デザイン性・モバイル性・性能の3点が高いレベルでまとまっている端末です。

Macbook Airを買った興奮もおさまってきたところで、備忘録的に私が設定した内容を記しておこうと思います。

この記事での設定内容は、いろいろとMacの初期設定をして使ってみた上でここは設定したほうがいいでしょという内容に絞るようにしています。もともと私がWindowsを使っていたということもありWindowsユーザーにも優しい(?)内容になっています。

WindowsからMacへの乗り換えユーザーも、そうでない方も参考にしてもらえると幸いです。

 

初期設定項目の目次

  1. 早めにセキュリティ設定の見直しを行う
  2. トラックパッドの設定を変更する
  3. 仮想デスクトップSpacesの設定をして作業領域を好きなだけ増やす
  4. Dock操作を使いやすくする
  5. ディスプレイの輝度調整機能を無効に
  6. キーボードの操作感をWindowsに近くする
  7. メニューバーの時間表示部分に日付と曜日も表示する
  8. コンピュータ名を設定する
  9. Finderの設定を行う
 

早めにセキュリティ設定の見直しを行う

設定を行うためにまずは「システム環境設定」を開きます。

Macのシステム環境設定を開く

システム環境設定→パーソナル→セキュリティとプライバシー

システム環境設定の項目の中にある「セキュリティとプライバシー」を開きます。

「スリープとスクリーンセーバーでパスワードを要求」の時間を設定します。ちょっとMacから離れる際に自動的にロックをかけセキュリティを確保するための設定です。

私は5分に設定しましたが、明らかに自分しか使わないという人は解除してしまってもいいと思います。

セキュリティ設定のパソコンを離れた際のパスワード要求設定

システム環境設定→パーソナル→ファイアーウォール

デフォルトでは「切」になっているので「入」にして有効にしておきます。

 

トラックパッドの設定を変更する

Macの代表的な入力インターフェースのトラックパッド(タッチパッド)の設定です。マウスには結構こだわりがあって、ロジクールのワイヤレスレーザーマウスを使っていたりしたのですが、Macbook Airではトラックパッドの操作が非常に快適なためマウス要らずです!

トラックパッドの設定に正解はなく、人によって使い方や好みが分かれる部分です。ここでは私が今設定している内容を一例として紹介します。普段の操作性を大きく左右する設定なので、自分で色々試してみてしっくり来る設定を探して見るのもよいかとおもいます。
システム環境設定→ハードウェア→トラックパッド→ポイントとクリック

「軌跡の速さ」を好みに合わせて調整します。早くするとちょっと指を動かすだけでポインタが大きく動きます。ここではちょっと早めに調整しました。
「タップでクリック」はクリックが圧倒的に楽になるので個人的に必須です。
「副ボタンのクリック」とは、いわゆる右クリックです。「二本指でクリックまたはタップ」に設定しました。
「調べる」と「3本指のドラッグ」については、3本指ジェスチャを別なアプリに割り当てたいためチェックを外しています。

トラックパッドのタッチパッド設定

システム環境設定→ハードウェア→トラックパッド→スクロールとズーム

全部チェックを入れました。直感的な操作ができるようになります。どれも便利です。
「スクロールの方向」については人によって設定が結構違う好みが分かれる部分なので、馴染む方にするといいと思います。

タッチパッドのスクロールとズーム設定

システム環境設定→ハードウェア→トラックパッド→その他ジェスチャ

これも全部チェックを入れました。
「フルスクリーンアプリケーションをスワイプ」は「4本指で左右にスワイプ」に。OSに備わっているSpacesという強力な機能で使います。Spacesについては後ほど説明します。
「Mission Control」は「4本指で上にスワイプ」にしました。Alt+Tabのようなアプリ切り替えをタッチパッドで気持よく行える機能です。
「アプリケーションをExpose」は「4本指で下にスワイプ」に。

上記の3つのジェスチャはアプリの切り替えなどで頻繁に利用する操作ですが、4本指で統一されていたほうが使いやすいと思います。

タッチパッドの設定のその他ジェスチャ

 

仮想デスクトップSpacesの設定をして作業領域を好きなだけ増やす

Spacesという仮想デスクトップの仕組みが標準で搭載されています。デスクトップを2枚・3枚・4枚・・・と好きな数だけ増やせます。狭いノートPCの作業領域を効率的に使うことができるようになります。

アプリケーション→Mission Control(四本指で上方向にスワイプ)

ミッションコントロール、かっこいい名前ですね。四本指で上方向にスワイプすると表示される画面です。

デスクトップを一枚追加する場合は、MissionControlを表示した状態で画面の右上にマウスカーソルを合わせて表示される+アイコンをクリックします。

Missionコントロールでデスクトップを追加する+ボタン

また増やしたデスクトップを減らす場合は、上に並んで表示されている小さなデスクトップにカーソルを合わせると右上に×マークアイコンが表示されるのでクリックします。

あとはドラッグすることでデスクトップを並べ替えたり、アプリをデスクトップをまたいで移動出来ます。

デスクトップ数は試しに3つくらいに設定してみると良いのではないでしょうか。後は好みで増やしたりすればいいと思います。

 

Dock操作を使いやすくする

よく使うアプリはDockに登録しましょう。登録したアプリは、アプリを終了した後もDockにアイコンが表示されるようになるので起動する手間が省けて便利です。
登録の仕方はDockに表示されているアプリのアイコンの右クリックメニューのオプションの中に「Dockに追加」にチェックをつければOKです。

Dockに追加

また、先ほどMissionControl上から仮想デスクトップの設定を行いましたが、アプリごとに仮想デスクトップへの割り当て先設定を行うことができます。割り当て先を「このデスクトップ」などに設定することで割り当てできます。

割り当て機能を使うと、例えばデスクトップ1にはFinderを割り当てておいて、デスクトップ2には作業用アプリやその他諸々割り当てておいて、デスクトップ3は資料やビューアを割り当てておく、というような使い方ができたりします。この例の場合だと真ん中のデスクトップ2がメインとなる作業用デスクトップとなり、左右に作業のための補助用デスクトップを配置しているような形です。

システム環境設定→パーソナル→Dock

Dockの動作に関する設定を行います。
ノートパソコンでは特に貴重な作業領域を少しでも確保するために「Dockを自動的に隠す/表示」にチェックを入れることをおすすめします。EclipseXCodeなどのIDE統合開発環境を使う場合は特に画面の作業領域を少しでも確保しておきたいですね。
他には、アプリアイコンにカーソルを合わせた時に拡大するようにしたりDockの位置を変更できます。お好みでどうぞ。

Dockの環境設定

システム環境設定→Mission Control

「最新の使用状況に基づいて操作スペースを自動的に並べ替える」のチェックを外します。
勝手にデスクトップの順番を並べ替えてくれる機能なのですが、ありがた迷惑な一面もあるため外しておきます。
例えば一番右のデスクトップは資料閲覧用デスクトップとして使っていたはずが、勝手に左側に移動されたりして訳が分からなくなります。

 

ディスプレイの輝度調整機能を無効に

システム環境設定→ハードウェア→ディスプレイ

画面のバックライトがちらつくのが嫌なので「輝度を自動調整」を無効にしました。

 

キーボードの操作感をWindowsに近くする

システム環境設定→ハードウェア→キーボード

初期設定のキーリピート感覚(キーボードを押しっぱなしで連続入力される感覚)がWindowsに比べると遅いので「キーリピートの認識感覚」を早くします。Windowsからの乗り換えではない場合にもおすすめの設定です。
「F1、F2などのすべてのキーを標準のファンクションキーとして利用」にチェックを入れます。従来のファンクションキーとしての動作をするようになります。逆にデフォルト動作の画面輝度調整や音量操作を行いたい場合はfnキーを押しながら操作します。

ハードウェアのキーボード設定

システム環境設定→ハードウェア→キーボード→修飾キー

CapsLockキーは左下という非常に押しやすい位置にありながら、存在価値を問われているなんとももったいないキーです。ここではCapsLockをCommandに割り当てました。これでWindowsのようにコピー&ペーストができるようになります。CapsLockキーの押し間違えによってイライラしてしまうこともなくなります。ただ、あんまりオレオレ設定をしすぎると他の人のMacを操作した時にちょっと戸惑うというデメリットもあるので注意してください。

システム環境設定→ハードウェア→キーボード→キーボードショートカット

「フルキーボードアクセス」を「全てのコントロール」に設定します。WindowsのようにTabキーで全てのコントロールにフォーカスが当たるようになります。

 

メニューバーの時間表示部分に日付と曜日も表示する

システム環境設定→システム>日付と時刻

「日付を表示」にチェックを入れます。
「曜日を表示」にチェックを入れます。
この設定によって時間だけではなく、日付と曜日も表示されるようになります。

メニューバーに日付と曜日と時間を表示する

 

コンピュータ名を設定する

日本語版Macを使っているとデフォルトのコンピュータ名は結構な違和感があります。ターミナルを利用する際も表示されるので設定しなおしたほうがいいです。

参考画像ではMBAになっていますが、分かりやすいコンピュータ名をつけてあげます。

Macのコンピュータ名を設定

 

Finderの設定を行う

Finderメニューバー→Finder→環境設定→一般

「デスクトップに表示する項目」で外部ディスクなどを表示するようにします。USBメモリに簡単にアクセスしたり取り外しができたりします。
「新規Finderウィンドウで次を表示」で新規に開いたときユーザー名のフォルダを指定します。

Finderメニューバー→Finder→環境設定→サイドバー

サイドバーに好きなフォルダや項目を表示できます。よく使う項目はチェックを入れておくといいかと思います。

Finderメニューバー→Finder→環境設定→詳細

すべてのファイル名拡張子を表示にチェックをします。

Finderメニューバー→Finder→表示

パスバーを表示します。Explorerのアドレスバーがないのでかわりに表示するイメージです。上のフォルダに簡単にアクセスできます。

あとがき

私がMacbook Airにした設定は以上になります。設定項目はまだまだたくさんあるのですが、ここは見ておいたほうがいいだろうという部分をまとめたつもりですので、ちゃんと設定を見直せた人はだいぶ使いやすくなってきたのではないのでしょうか。

私も探り探りでやっていますので、間違いなどがありましたらコメントに一言いただけますと助かります。ここはもっとこうしたほうがいい!などというご意見もお待ちしています。

この記事の内容は全てOSの設定のみで出来ることですが、更に便利にMacを活用するために便利なソフトウェアがインターネットにはたくさん公開されています。無料で公開されている超便利なフリーソフトもたくさんあるので活用しない手はないです!

いまもリアルタイムで色々インストールして実践して試しているところなので、次回はソフトで更にMacを便利にする記事を書きたいと思います。お楽しみにー。

参考記事