2011年6月29日水曜日

Googleからどどーん

Google+
http://gplusproject.appspot.com/static/ja.html
Googleの新たなSNSって感じで結構満を持して出したって感じがします。
Facebookとの違いはFacebookは友達にはすべて平等に公開ですが、
Google+では「サークル」という概念がありその中でのコミュニケーションといった感じでしょうか。
GoogleのSNSはダメというジンクスと、Facebookの牙城を切り崩せるのかというところがポイントですね。

Swiffy
http://googlecode.blogspot.com/2011/06/swiffy-convert-swf-files-to-html5.html
FlashをHTML5に変換するサービスです。
どこまで完成度が高いのかはGoogle labなのでよくわかりませんが、
Flashの終焉も刻々と近付いている感じがします。

Google Developer Day 2011 Japan
http://googledevjp.blogspot.com/2011/06/google-developer-day-2011-japan.html
GDD2011が11月1日@パシフィコ横浜で開催されます。
今年も参加するにはクイズに正解しないといけないみたいなのでがんばらないとです。

2011年6月19日日曜日

Objective-Cで気をつけるべき点

C++やJavaからObjective-Cを使うにあたって間違いやすい点や異なる点です。

同じオブジェクト指向言語といっても、言語によって慣習や考え方はかなり異なることがあります。
他の言語の慣習や考え方を持ち込むのは可読性を損ねるだけでなく、一貫性も損ねることとなるので言語の考え方や慣習はきちんと学ぶべきだと思います。


インスタンス変数はデフォルトはprotected
@privateを使うことでprivateにすることができます。publicも同様にできますが、カプセル化を阻害するのでもちろん推奨されていません。


メソッドはすべてpublic
ヘッダーファイルでプロトタイプ宣言してなくても、メッセージを送ると呼び出せますので、.mファイル側にだけ宣言していたとしてもprivateになったわけではありません。
Objective-C 2.0(iOS)であればクラスエクステンションを使うことで、ヘッダーファイルのほうにプロトタイプ宣言をしなくて済むのとクラスエクステンションを見るとどれがprivateメソッドなのか判定することができます。
privateメソッドに接頭語を付けて見分けるというのも合わせて使ったほうがいいかもしれません。
Extensions(The Objective-C Programming Language)

propertyのデフォルトはatomic
propertyはデフォルトはatomicになっているので無駄に排他制御がかかり性能に影響します。排他不要の場合はnonatomicを必ず書きましょう。

initでインスタンス変数はすべて0で初期化される
Javaと同様に初期化が自動でされるので、C++のようにコンストラクタで0で初期化する必要はありません。
Allocating and Initializing Objects(The Objective-C Programming Language)

nilのオブジェクトにメッセージを送っても無視されるだけでクラッシュはしない
C++のようにクラッシュ回避という意味でのnilチェックは不要です。nilチェックは通常ケースのハンドリングで使います。
Sending message to nil(The Objective-C Programming Language)

BOOLのYESは1とは限らないので、if文内での判定には使わないようにする。
BOOLはunsigned charと同じなので1以外の数が返ってくる恐れもあります。 == YES は避けたほうがよいです。

NSString,NSColor,NSURLはretainではなくcopyを使う
NSStringなどといった value objectsとよばれるオブジェクトにはcopyをつかったほうがよいそうです。
copyとして保持したり返したりするので不変であることが保証できるからのようです。
Value Objects and Copying(Memory Management Programming Guide)

string = value;
self.string = value;
は別物
全者は単なる代入ですが、後者はpropertyによって作られたアクセッサを使っています。後者だとpropertyの宣言によってただの代入だったりretainやcopyされたり排他がかかったりと動作が異なります。

delegateはretainしない
巡回参照による無限ループにはまらないようにdelegateはretainせず、参照だけを保持する。
Weak References to Objects(Memory Management Programming Guide)

メソッド名に接頭語は使わない。
doやdoesをつけるのも意味的な問題で推奨されていません。getも付けないのが慣習です。
General Rules(Coding Guidelines for Cocoa)

引数にキーワードをつける。
キーワードなしでもメソッドの宣言はできますが、キーワードをつける。
General Rules(Coding Guidelines for Cocoa)

プライベートメソッドは独自の接頭語をつけたほうがよい
知らないうちにオーバーライドしてしまうことを防ぐためと、プライベートメソッドを見分けやすくするために、接頭語をつける。ただしアンダーバーはAppleが使っているので独自のものを用意する。例えばBF_addObjectなど
Private Methods(Coding Guidelines for Cocoa)
Typographic Conventions(Coding Guidelines for Cocoa)

#defineは使わずenumもしくはconstを使う
C++と同じで#defineだとプリプロセッサで数値に置き換えられてしまうので、enum,constを使う。
Other types of constants(Coding Guidelines for Cocoa)

通常ケースのハンドリングでは例外は使わない。
JavaではFileNotFoundなど通常のハンドリングにも例外を使いますが、Objective-Cでは、配列外アクセスなどクラッシュするような場合など本当に例外な場合にのみ使います。
そのため、例外はテストなどのデバッグ期間でしか発生しないものでなければなりません。
Exceptions and Errors(Coding Guidelines for Cocoa)

名前空間はない
C++やJavaのように名前空間はありません。NSとか接頭語がついているのもそのためです。

ヘッダーファイルでの2重インクルードの防止は不要
CやC++ではヘッダーファイルの2重インクルードを避けるために#ifdefをヘッダーファイルにつけるのが慣習ですが、Objective-Cでは#importを使えば不要です。


余談ですが、Googleのガイドラインを見るとかなりがっちり決まってたので驚きました。
Objective-Cはフリーダムにかける方だと思うので複数人での開発であれば、Googleのように厳密に決めてやったほうがいいと思います。しかし、性能などとのトレードオフもあるので他のガイドラインをまるパクりではなく、プロジェクトにあったものを選択して採用すべきです。

参考資料
Cording Guidelines for Cocoa
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html

The Objective-C Programming Language
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html

Memory Management Programming Guide


Google Objective-C スタイルガイド(日本語訳)

2011年6月13日月曜日

HPとRIMのタブレット

webOS,BlackBerryと新たなプラットフォームを要したタブレットがいよいよ登場。

HP、PalmのwebOS搭載タブレット「HP TouchPad」を7月に発売http://www.itmedia.co.jp/news/articles/1106/10/news020.html

RIM、タブレット端末「BlackBerry PlayBook」を世界展開、16カ国・地域で発売へhttp://itpro.nikkeibp.co.jp/article/NEWS/20110613/361295/

これでタブレットの役者はほぼ揃いました。
Windowsはかなり遅れをとってますね・・

といってもただ出揃っただけで、やはりどれもiPadを照準としてつくっていたのは明らかで
残念ながらiPad2が出てしまった今では、比較すると見劣り感がいなめなく、かなり不利な状況ではないでしょうか。

Objective-Cの性能・フットプリント

Objectiv-CではC++と比べて、開発者が楽になるようにいくつか仕組みが入っています。
それを効果的に使うことによって開発の生産性をあげることが可能ですが、よく知らずにつかっていると、性能を劣化させたり、フットプリントが大きくなり無駄に大きいアプリになってしまう恐れがあります。

このような問題が発生しやすいポイントについて記載します。

プロパティ
Objective-Cでは、アクセッサ、いわゆるただ値をインスタンス変数に読み書きするだけのGet/Setメソッドを開発者が記載する手間を省くのを手助けしてくれます。
それがプロパティです。

・プロパティを使わない場合

@interface ClassA : NSObject {
NSArray* array;
}
- (NSArray*)getArray;
- (void)setArray:(NSArray*)inArray;
@end
@implementation ClassA
- (NSArray*)getArray
{
return array;
}
- (void)setArray:(NSArray*)inArray
{
if ( array != inArray ) {
[array release];
array = [inArray retain]; }
}
@end

・プロパティを使った場合

@interface ClassA : NSObject {
    NSArray* array;
}
@property (nonatomic, retain) NSArray* array;
@end
@implementation ClassA
@synthesize array;
@end

という風に見れば一目ですが、プロパティのほうが書くコーディングの量が全然違ってきますし、retainとかcopyとか指定すればそのとおりに実現してくれるので大変楽なので使ったほうがよいです。

しかし、プログラムの書く量が少ないからといって、プログラム自体(実行ファイル)が小さくなるわけではありません
プロパティを使ったとしても実際にコンパイルすると、プロパティを使わない場合と同等の量の実行ファイルが生成されることになります。

逆にGet/Setの片方しか使わない場合は、プロパティを使わないほうが小さいプログラムとなります。
ですので、なんでもかんでもインスタンス変数をプロパティにしてしまうのはプログラムサイズとしてはよくありません。

また、性能面でも少し影響がでる場合があります。

自分のクラスのインスタンス変数にアクセスする場合、以下の2パターンあります。
(arrayはプロパティとして宣言されてる場合です)

・①

array = [NSArray new];
・②

self.array=[NSArray new];


①と②は、C++をやっていた人にはこれは同じに見えますが、これは別物です

①は単純な代入ですが、②はアクセッサをつかって代入をしています。
プロパティでassignだったら結果は同じですが、retainなどをしていると②のほうはretainされます。

ですので、retainするために、②を使うのは正しいですが、単に代入するのに②を使うと①に比べて関数を呼び出す分だけオーバーヘッドが生じます。

ひとつひとつではたいしたオーバーヘッドではありませんが、大きいプログラムとなると小さな積み重ねも大きくなることもあるので、そのことを理解しておく必要はあると思います。

Autorelease
つぎにAutoreleaseです。
Autoreleaseはガベージコレクション(GC)みたいで楽なイメージがするかもしれませんが、もちろんGCとは全然違います。

最も気にすべき違いはメモリを開放するタイミングです。

GCは実装によって様々あるので、特に触れませんが、Objective-CのAutoreleaseがメモリを開放するタイミングは、GUIからのイベントを受け取る実行ループでAutoreleaseプールがあるので、一回の実行ループ毎にAutoreleaseプールは開放されます。

つまりひとつのイベント処理が止まるまでAutoreleaseしたメモリは消されずにひたすら溜まりっぱなしということになります。
ですので、ひとつのイベント処理でメモリを大量に使うようなプログラムでAutoreleaseばっかり使っているとメモリ不足になる危険性があります。

これを回避するにはAutoreleaseの使用をできるだけ避けてreleaseで開放するか、独自のAutoreleaseプールを作成して、それを適宜開放するかです。

Autoreleaseは使わざるを得ない場合もあり、完全に回避することは難しいので、両方使うのが望ましいと思います。

-----------------------------------------------------------------------------------------------------------
嘘とか間違いなど指摘していただけると幸いです。

Objective-Cの理解に役立つ本

Objective-Cの言語の本はこれしか読んだことがないので・・。

2011年5月28日土曜日

Objective-Cのメモリ管理はそんなに難しくはない(理論編)

Objective-C(非GCの場合)のメモリ管理は癖があってわかりづらいと聞いていたのですが、
実際にiOS開発でやってみたところ特にそうは感じず、むしろCとかC++よりは親切にすら感じました。

自分の理解の範疇でObjective-Cのメモリ管理について説明してみます。

ここでは一貫性を持たせるためにオブジェクトではなく、クラスオブジェクトとしてインスタンスという言葉で統一して使います。
また、allocを伴わない生成、autoreleaseについてはここでは触れず別途実践編で触れていきたいと思います。

インスタンスの生成・削除は基本的には全く同じ

・C++の場合
生成・・・new
削除・・・delete

・Objective-Cの場合
生成・・・alloc して init(またはnew)
削除・・・release (厳密にはreleaseの中でdeallocが呼ばれます※)
※なぜdeallocじゃないのかは後ほど説明します。

Objective-Cではallocではインスタンスを生成するだけで、初期化はinitでやるという点が違うくらいでほぼ一緒です。

ただし、実際にインスタンスが削除されるのはreleaseを呼んだ時点とは限らないというところがポイントになります。
これが混乱を巻き起こしていると思われます。
これを理解するには、なんでそんな作りになってるのということを理解する必要があるかと。

なぜObjective-Cでは、C/C++と同じやり方ではなく、後ほど説明する「retainカウント」という独自の方法をとったのでしょうか。

C/C++におけるメモリ管理の問題

まずはC/C++のメモリ管理のやり方ではどこがまずいのかを考えてみます。
  • 確保したメモリをどこが開放すべきなのか不明確である
これが一番の問題だと思っています。
インスタンスを生成した場合に、生成した人(クラス)が削除すれば問題ないわけですが、大抵の場合そうではなく、クラスのインスタンスのポインタをたらい回しにしているうちに、あれ、これってどこで削除するんだっけということになり、削除し忘れが起こったり、複数の箇所で削除しようとして落ちるといったメモリ関連の不具合が発生します。

これを解決するには、生成したものをどこで削除するかといったことの「決め事」を作る必要があります。そのやり方は様々あり、プログラムに求められる性能とかにもよるのでプロジェクトによって違います。
共通していることは、決め事は「プロジェクト毎に決める」ということで「言語仕様としては決められていない」という点にあります。

よく言うと柔軟な言語仕様ですが、悪く言うと無法地帯を産み出しているとも言えます。

Objective-Cのメモリ管理

そこで、Objective-Cではインスタンスの生成・削除の責任をはっきりさせるために、「オーナーシップ」という考え方のもと設計されています。

Objective-Cのオーナーシップとは、簡単に言うと、所有者が責任を持って削除するということです。

このオーナーシップを実現するために「retain」と「release」が存在します。

「retain」は、このインスタンスを所有しますという宣言みたいなもので、retainを呼ぶことにより、所有者となります。
また、インスタンスの生成であるallocしたときは自動的にretainされるので、allocを呼ぶことでも所有者になります。
所有者が「release」することにより事実上削除したことになります

インスタンスを所有している人がだれもいなくなったら、ようやくその時になって初めてインスタンスは実際に削除されます。(上で事実上と書いたのはこのためです)
ここが実際にインスタンスが削除されるのはreleaseを呼んだ時点とは限らないわけになります。
なのでreleaseでなく、いきなりdeallocを呼んでしまうとまだ削除できる状態でないのに、deallocの終了処理が動いてしまうという問題があるので、deallocは使ってはいけません。

オーナーシップでは、所有者、つまりはinitした人とretainした人は、かならずreleaseしなければなりません。もしそうしなければretainとreleaseの対応関係が崩れてしまい、メモリリークや不正メモリアクセスが発生します。

Objective-Cでのこのオーナーシップの実装は「retainカウント」という方法で実現されています。
インスタンス毎にretainカウントというカウンタを持っていて、alloc時に1になり、retainされたら1を加算して、releaseされたら1を減算し、0になったら削除するという単純なものです。セマフォみたいなものです。

オーナーシップの副作用

オーナーシップにより、メモリの確保・開放が明確になり、素晴らしいことでありますが、もちろんこれによる副作用もあります。

それは主にプログラムの速度に影響します。

retainカウンタというのを制御しているので、C++に比べると余計な処理をやっていることとなります。retain,releaseの呼び出しによる余計なオーバーヘッドももちろんありますので、retainカウンタ有り無しでは性能に違いが現れます。

オーナーシップはあくまでポリシーでしかない

前述で「所有者、つまりはallocした人とretainした人は、かならずreleaseしなければなりません。」と書きましたが、これはあくまで「ポリシー」でしかありません。

つまり、initした人とretainした人がreleaseを呼ばなくてもコンパイル時にエラーになったりはしません。
プログラムの書き方次第では、

ClassA* objA = [[ClassA alloc] init];
ClassB* objB = [[ClassB alloc] init];
[objA send:objB];//ClassAのsendメソッド内で引数のobjBをretainする.
[objB release];//ClassAでretainしたのをここでrelease.
[objB release];
[objA release];

なんてことも動きさえすれば、平気でできてしまいます。

なので、いくらObjective-Cでオーナーシップの仕組みを提供していても、プログラマがちゃんと理解せずに使っていると、ただの読みづらいコードやカオスなコードになります。
そういう使い方をするのであれば、retain、releaseを使うのは放棄し、alloc,deallocでどうにかすべきだと思います。(ライブラリを使うことも放棄することになりますが・・)
まぁそれだったらCで書いたほうがいいですね。。

Objective-Cのメモリ管理がどうのこうのと文句を言っている人がいたら、これに当てはまっている危険性があるのでよくコードを見てあげたほうがいいと思います。


つまりはどんな道具(言語)も使い方次第です。
是非Objective-Cユーザーはオーナーシップを理解し、よいコードを書いていきましょう。

-----------------------------------------------------------------------------------------------------------
嘘とか間違いなど指摘していただけると幸いです。

Objective-Cの理解に役立つ本

11章にObjective-Cの設計者との談話が載っています。



Objective-Cの言語の本はこれしか読んだことがないので・・。

2011年5月27日金曜日

アジャイル

MIT Media Labの新所長になられた伊藤穰一さん(@joi)とアジャイルで開発しているPivotalのCEOのIan McFarlandさんのアジャイルスタートアップについての講演に参加してきました。
伊藤穰一とPivotalのIan McFarlandが語る「アジャイルスタートアップ」
http://www.ustream.tv/recorded/14985986

感想

現状のWeb界隈のスピードの速さを見るとアジャイル開発の重要性は明らかに感じられます。これまでの1年かかるようなものづくりのやり方では絶対勝てません。
ただペアプログラミングまで必要かは議論がわかれるとは思いますが、ストーリーベースでテストを行いContinuous Releasabilityを確保するのは必須だと思います。

アジャイルといっても今よりずっと前から言われていますが、うまく普及していないのは、これまでの考え方を捨てて、発想を転換しなければならないということだと思っています。
特に経営レベルでは、これまでの仕様と納期ありきから脱却しなければならないわけですから。エンジニアを信用して投資するなんてことは、リスクの高い責任を背負うことになるので到底今の日本の大企業ではできないでしょう。
アジャイルを本気でやるにはトップダウンで決定し、宗教的に信じこんでやるのが一番な気がします。そういう点でPivotalはうまくいっているんだろうなと。

また我々組み込み業界だと度々ソフトを更新ってわけにもいかないわけで、この先生き残っていくには、「ソフトの更新がバリバリできる環境」をつくることが肝なのではないかと思います。国としてもものづくり日本とか言っているのであれば、こういったところのインフラを作ってほしいものです。

メモ

・アジャイルは元々は日本の製造業のやり方から来ている
・基本的な方向性は決めるが最終目的をあまり決めず、数日から2週間のスプリント毎にユーザのフィードバックももとに、なにをやるか見直す
・例えばYouTubeはもともと出会い系の動画サイトを目指していたり、Flickerはもともとはゲームだったりとやっているうちにゴールは大きく変わっている
・プロセスは、ストーリー単位(ストーリーは文書で書きだす)⇒テストを書く⇒コーディングする⇒テストをパスする
・ソースコード:テストコードの割合は1:1.5くらい
・朝きてストーリーカードをみてみんなでどれをやるか決める
・PMはいらない
・いつまでに何をではなく、このスピードでいけばここまでできるというスタイル
・締切りに向かってガッとやるのではなく無理のないペースで
・4〜6人のチームで必ずペアプログラミング
・プログラミングのうち8割くらいは悩んでたりするので2人でやったほうが効率的
・技もコードも覚えられるので新しい人が入ってきた場合にも育てやすく入れやすい、新人を入れるサイクルを回せる
・コードはシンプルに書く。コードでイノベーションを起こそうとしてはならない。それはストーリーでやるべき
・絶対にプロトタイプは製品化しない。つくり直す
・テストドリブンで常にリリースできるものをつくり、短いサイクルでストーリーを実現していくので、常に新しいものがリアルタイムに出すことができる
・FacebookやTwitterは大きい会社になってもほぼ毎週のようにころころ機能が変わっているので、うまくプロセスをまわしている。
・ソースコードや特許はアジャイルにとっては負債。捨て難いから。
・プロセスの一員としてデザイナーを入れる。デザインもカリスマデザイナーが作ったものをそのまま作るようなやり方ではなく、常に仮説としてユーザーの意見を取り入れて変更する。
・日本のモノづくりは仕様を決めてから作り始めできあがるのに1年くらいかかるが、それでは遅い。世の中は毎日めまぐるしく変わっているのに1年後にユーザーが何がほしいのかはわからない。
・経営レベルで発想を変えないといけない。その点ではベンチャーのほうがやりやすい。
・アメリカではとてもデータドリブン。ユーザの動きといったデータを細かく分析して仮説を検証している。
・データに頼りすぎてもだめだが、データを無視して同じ失敗を繰り返すのもだめ。そのバランスが重要

その他

講演とは関係ないですがアジャイルつながりで。

今日見つけた記事でScrumやXPなどのアジャイルプラクティスをミックスしてやるといったことについて書かれています。

アジャイル・ブッフェへのいざない(MSのエバンジェリストの長沢さん)

本では、こちらの本の前半部分にアジャイルプラクティス(extreme programing)の説明がわかりやすく書いてあります。

2011年5月14日土曜日

ブラウザでAngry Birds

iPhoneやAndroidアプリで有名なAngryBirdsがブラウザ上でもプレイできるようになりました。

http://chrome.angrybirds.com/

ただしまだβ版なのでバグは結構ありそうです。
私も試してみましたが、
2011/5/14現在でChrome11だと2-9がプレイできないのとHD版も動きません。