ナカザンドットネット

それって私の感想ですよね

CoronaSDKで無料でストア向けアプリを作れるようになりました

2011年7月に僕がCoronaSDKの入門書を出したのは記憶に新しくないところですが、CoronaLabsのブログで、Corona SDKの料金プランの改定が発表されました。

State of Corona: New Public Release + FREE + Re-imagining Pro | Corona Labs
http://coronalabs.com/blog/2013/04/04/state-of-corona-new-public-release-free-re-imagining-pro/

この記事は、これまでPlay StoreやApp Store向けの公開用アプリをビルドするために最低99ドル/年が必要だった時代が終わり、無料で公開用アプリが作れるようになったことを知らせるものです。
(あとPROライセンスの見直しとか、OpenGL/ES強化の情報とかも載ってますので、興味ある方は元記事を御覧ください)

新料金体系

f:id:Nkzn:20130406134722p:plain
http://coronalabs.com/products/corona-sdk/faqs/

以前の料金体系からINDIESが無くなり、新たにSTARTERが入った形になります。

料金

  PRICE Revenue Limit()
STARTER 無料 10万ドルまで
PRO 599ドル/年 50万ドルまで
ENTERPRISE 999ドル/年 50万ドルまで
  2,499ドル/年 なし

Revenue Limit : 昨事業年度の収入による利用制限。*1

できること

STARTER
  • SDKの安定ビルドをダウンロードできます
  • シミュレータでアプリを作れます
  • アプリ(.apk/.app)をビルドできます(クラウドビルドなのでオンライン時のみ)
  • ビルドしたアプリはPlay StoreやApp Storeで有料/無料問わず公開できます*2
  • アプリに広告を載せることができます(参考:Can I have ads in my apps made with Corona SDK Starter?)
PRO
  • STARTERの機能全て
  • アプリ内行動解析(Corona Cloudの1機能)を利用できます
  • アプリ内課金に類するもの(Premium Manetization Services)が利用できます
  • SDKの最新ビルド(Daily Builds)をダウンロードできます
  • 各種新機能・新サービスのプレリリースが利用できます
  • Project Gluonによって作成された、サードパーティサービス(FacebookやAmazonなど)のプラグインが使用できます
  • 各プラットフォームのAPI(Java/Obj-C)に、Luaからアクセスできます(参考:Android/iOS
  • 有償サポート(参考)
ENTERPRISE
  • PROの機能すべて
  • Coronaの処理系をCやらJavaやらObj-Cで弄れます(参考)
  • オフラインでの、待ち時間無しのビルドができます*3
  • カスタマイズしたCoronaでのビルドをシミュレータから行えるようになります(2,499ドルプランのみ)
  • Corona Labsのエンジニア1名による1時間のQ&Aセッションと、環境構築のサポート(2,499ドルプランのみ)
  • Eメールサポート(2,499ドルプランのみ)

本当に公開できるのん?

僕のサブスクリプションは1年以上前に切れているのでちょうどいいと思い、実際にCoronaのサンプルにあったカメラアプリをPlay Storeに公開してみました

f:id:Nkzn:20130406155141p:plain

お金払ってないのにdebug.keystore以外のkeystoreファイルを使ってちゃんと署名ができました。これは嬉しい。
というか最新のCorona SDKを落とし始めてから公開設定の完了まで30分とかかりませんでした。お手軽感がパないです。

余談

はじめる!CoronaSDKを出した後の僕はと言えば、本を出すだけ出しておいて(転職があってバタバタしていたのもありますが)あまりCoronaの普及活動に精を出していなかったように思っています。

最大の理由は料金体系のしんどさでした。最近の料金体系は追ってなかったのですが、Play StoreかApp Storeのどちらか向けのビルドをするために99ドル、両方だと249ドルとか、初心者にはオススメしづらかったです正直。
もちろん仕事でガッツリ使うツールとしては高くはないですし、作ったアプリでちゃんとビジネスをして稼げれば2万円や3万円は軽く取り返せるでしょう。
ただそれは、割と意識の高いほうの考え方です。世の中の「スマートフォンアプリというものを自分にも作れるなら作ってみたい」みたいな趣味レベルの人たちには、そこまでの意識の高さは求められません。
そういう点で今回の料金改定は、初心者がサクッとスマートフォンプログラミングに触ってみるという点で、物凄くハードルが下がったと感じ、歓迎しています。

// 現実的には、Enterpriseで充分お金が取れるようになったから、
// 裾野を広げるほうの戦略にシフトしてくれたのかなーと思ってます。

*1:どうやって調べるつもりなんだろう・・・?

*2:別途、GoogleへのAndroidデベロッパー登録料25ドル(初回のみ)、または、AppleのiOS Developer Program登録料99ドル(毎年)がかかります。

*3:自動化が捗りますね

An MVP Pattern for Androidを訳してみた

新年あけましておめでとうございます。 ブログで書き初めというのも粋かなと思いまして、仕事でAndroidでのMVPパターンを調べている一環でAn MVP Pattern for Androidを意訳してみました。それではどうぞ。

An MVP Pattern for Android

Separating the presentation of the application's UI from the logic of its UI is usually a good idea. This separation of concerns creates more de-coupled code, which is much cleaner, and even allows for more unit testing coverage. Android bundles the UI and UI logic into the Activity class, which necessitates Instrumentation to test the Activity. Since Instrumentation is introduced, it is much more difficult (or impossible) to properly unit test your UI logic when the dependencies in the code cannot be mocked. However, a simple MVP pattern will help de-couple the UI and UI logic in Android applications.

一般的に、アプリのUIの見た目をロジックから切り離すのは良い考え方です。この関心の分離は、コードを疎結合で簡潔なものにし、ユニットテストカバレッジを改善することもできるでしょう。AndroidのUIとUIロジックはActivityに纏められており、ActivityをテストするにはInstrumentationの利用が必須となっていますが、Instrumentationの仕組みが現れて以来、コードの依存性をモック化できないUIロジックに対して適切なユニットテストを行うことが、非常に困難(または不可能)になっています。しかし、シンプルな MVPパターン を用いることで、Androidアプリケーション内のUIとUIロジックの分離をしやすくなります。

The MVP pattern stands for Model-View-Presenter, and it separates the UI concerns between the data of the UI (Model), the display of the UI (View), and the logic of the UI (Presenter). For Android, the View is the Activity, which will handle gathering user input and updating the display; the Presenter is a class that will handle communication between the Model and View; the Model will handle persisting and retrieving data, along with any business logic that the data must adhere to. Interfaces will be used to de-couple each of these components. A simple Customer View will be used to illustrate how this can be accomplished.

MVPパターンは、 Model-View-Presenter を表しており、UIに出すデータ( Model )、UIの見た目( View )、UIのロジック( Presenter )という、UIに関わる関心ごとを分離しています。Androidにおいては、ユーザーからの入力や画面更新を取りまとめているActivityView 、ModelとViewの間で行われるやりとりを制御するクラスが Presenter 、データの保持や検索など、データに従った形の各種ビジネスロジックを扱うクラスを Model と呼べばよいでしょう。各コンポーネント疎結合に保つための仕組みとしては、インターフェースを使います。シンプルなCustomer Viewを例に挙げて、これらをどの様に実現していくかを説明していきます。

An MVP Pattern for Android - Magenic Blog

First, our CustomerActivity (the View) will have textboxes for the Customer's ID, first name, and last name:

先ず、今回作るCustomerActivity(これが View ですね)は、カスタマーID、名前、名字のテキストボックスを持っています。

private EditText mFirstNameEditText, mLastNameEditText, mIdEditText;

The user will load a customer using the mIdEditText and a Load Button. Likewise, the user will save a customer using a Save Button:

ユーザーはカスタマー情報をmIdEditTextmLoadButtonを使ってロードします。また、同じように、カスタマー情報をmSaveButtonでセーブします。

private Button mSaveButton, mLoadButton;

We must now create a CustomerPresenter with the following methods:

さて、そろそろ以下のメソッドを持つCustomerPresenterクラスを作成しましょう。

public CustomerPresenter(ICustomerView View)
public void saveCustomer (String firstName, String lastName) 
public void loadCustomer (int id)

We then can wire it all up in the CustomerActivity's onCreate method:

ここでCustomerActivity#onCreateに繋いでいきます。

mCustomerPresenter = new CustomerPresenter(this);
mSaveButton.setOnClickListener(this); 
mLoadButton.setOnClickListener(this);

The CustomerActivity class must now implement the interfaces OnClickListener (for handling the Button's OnClickListeners) and ICustomerView (for the CustomerPresenter constructor). The OnClickListener defines the method void onClick(View v), and our method will look like the following:

CustomerActivityクラスにはインターフェースとしてOnClickListener(Button用のリスナ)と、ICustomerView(CustomerPresenterコンストラクタ用)を実装して下さい。また、OnClickListeneronClick(View v)を実装する必要がありますが、下記のようにして下さい。

switch (v.getId()) {
case R.id.saveButton:
    mCustomerPresenter.saveCustomer(mFirstNameEditText.getText().toString(), 
    mLastNameEditText.getText().toString());
    break;
case R.id.loadButton: 
    mCustomerPresenter.loadCustomer(Integer.parseInt(mIdEditText.getText().toString()));
    break;
}

The previous two code sections show that when the Save Button is clicked, the saveCustomer method of our presenter will be called with the Customer's first name and last name information; and when the Load Button is clicked, the loadCustomer method of our presenter will be called.

前2つのコードは、mSaveButtonがクリックされた時に PresentersaveCustomerメソッドが名字と名前を引数として呼ばれるという話と、mLoadButtonがクリックされた時に PresenterloadCustomerメソッドが呼ばれるという話でした。

We haven't defined ICustomerView, so we'll do that now. When loading the customer, the CustomerPresenter will need to be able to update the CustomerActivity's last name, first name, and ID EditTexts, so ICustomerView will look like the following:

まだICustomerViewに手を付けていませんでしたので、そろそろ定義しましょう。カスタマー情報をロードするときには、CustomerActivityの名字、名前、カスタマーIDのEditTextをCustomerPresenterから書き換えられるよう、ICustomerViewを下記のようにしましょう。

void setLastName (String lastName); 
void setFirstName (String firstName);
void setId(int id);

The CustomerActivity's implementation of these methods will set the corresponding EditText to the value of the parameter.

CustomerActivityへの(ICustomerViewの)実装では、各メソッドに対応するEditTextへパラメータをセットしておいてください。

The CustomerPresenter, then, will look like the following:

CustomerPresenterは下記のようになります。

private ICustomerView mCustomerView;
private ICustomerModel mCustomerModel;
public CustomerPresenter(ICustomerView view) {
    mCustomerView = view;
    mCustomerMode = new CustomerModel();
}
@Override
public void saveCustomer(String firstName, String lastName) {
    mCustomerModel.setFirstName(firstName);
    mCustomerModel.setLastName(lastName);
}
@Override
public void loadCustomer(int id) {
    (mCustomerModel.load(id)) 
    {
        mCustomerView.setId(mCustomerModel.getId());
        mCustomerView.setFirstName(mCustomerModel.getFirstName());
        mCustomerView.setLastName(mCustomerModel.getLastName());
    }
}

The implementation of the CustomerModel isn't important for our purposes; we just need to know that it is being saved to a repository of some sort. Furthermore, the CustomerModel is currently tightly-coupled to the CustomerPresenter, which can be remedied by injecting it as a dependency.

CustomerModelの実装は今回の目的から見るとあまり重要ではありません。何らかの保存場所にデータがセーブされていればよいのです。その上、今回のCustomerModelCustomerPresenterと密結合していますので、依存性注入を行う形などで修正したほうがよいでしょう。

The CustomerPresenter allows the CustomerActivity class to be as simple as possible. The activity now only gathers user input for the presenter and provides simple UI update methods for the presenter. Since the CustomerView and CustomerModel implement interfaces and can be injected into the CustomerPresenter, it is not dependent on them. Therefore, they can by mocked, which allows the CustomerPresenter logic to be unit tested.

CustomerPresenterによってCustomerActivityクラスは可能な限り完結になり得ます。今回のActivityPresenter にユーザーからの入力を集め、 Presenter から触るためのシンプルなUI更新メソッドを提供しています。CustomerViewCustomerModelはインターフェースにより実装されているため、CustomerPresenterからのインジェクションができるくらいに依存性がありません。そのため、それぞれのモックさえ作ればCustomerPresenterのロジックはユニットテストが可能になるのです。

After Note: This MVP pattern is sometimes referred to as Passive View, since the view only passes along data, either to or from its presenter. The MVP pattern can also be implemented such that the View knows of the model. The view responds to state changes in the model for simple UI updates, while the presenter handles more complex UI logic. This more complex pattern is sometimes referred to as Supervising Controller.

後記:今回のMVPパターンは、 View が単に Presenter に対して入出力するだけのものなので、Passive Viewパターンとも呼ばれるものになっています。MVPパターン自体は ViewModel にアクセスできる場合にも成り立ちます。 ViewModel の状態の変化に反応して、シンプルなUI更新を行い、複雑なUIロジックが必要な場合に Presenter に投げます。この複雑なパターンのことを特にSupervising Controllerパターンと呼ばれたりします。

In Android, this can be accomplished by the Model using Java's Observable class and the View implementing the Observer interface; when something changes in the Model, it can call the Observable's notifyObservers method. It can also be implemented with Android's Handler class; when something changes in the Model, it can send a message to a handler that the View injects into it.

Androidでは、JavaObservableクラスを用いた Model と、Observerインターフェースを実装した View によってMVPパターンが実現できます。 Model に変更があった時にObservable#notifyObserversを呼び出すのです。また、AndroidHandlerクラスでも同様の実装ができます。 Model に変更があった時に、 View に変更を伝えられるHandlerに対して、メッセージを投げるのです。

An MVP Pattern for Android - Magenic Blog]

訳注

言うとおりに作ったらこうなりました

これからAndroidを始めるヅ大生にオススメしたい7冊の本

ハイ、Aizu Advent Calendar 22日目は、ヅ大最速で卒論テーマにAndroidを選んだ残念な人のわたくしがお送り致します。
僕がAndroidに初めて触れた2009年の夏には、右も左も分からない中で手探りで情報を探すしかない状態でした。しかし2012年の今日ではAndroid+iPhoneによってガラケーが駆逐されかけているという、当時から想像はしていたものの本当にそうなってビックリしているような時代になっています。
そんな状況に比例して、もちろん技術書の数も当時とは比べ物にならないくらいに増えています。というか、増えすぎです。


f:id:Nkzn:20121222004922p:plain


入門書だけで42冊とか何かのジョークやで。
そんなわけで、これからAndroidアプリ開発に手を出したいんだけど、どの本から読んだらいいかさっぱり分からないヅ大生たちに、独断と偏見で選んだ7冊を紹介します。

前略、1次情報を疎かにしてはいけない

Develop | Android Developers
Design | Android Developers

会津の新兵どもへ。貴様らは英語で数学を学び、英語でオートマトンを学び、英語でデータベースを学び、英語でアーキテクチャを学んできた。
今更何を日本語に拘っている! 全ての情報は公式にこそある! 公式を読め!!!

訳:

Androidの公式チュートリアルや公式ドキュメントは、内容だけ見れば大変丁寧で、かつ網羅的であり、更新も頻繁に行われています。また、(技術系の英文全般に言えることですが)日常英会話に比べると、比較的平易な言葉で書かれており、会津大学で数年を過ごした感覚があれば、充分に読解が可能なレベルです。
以降紹介していく「2次情報」としての技術書はしばしば、ページ数の制限などから、重要な点のみに絞って手法の紹介を行なっており、読み進めていく中で疑問に思う点がいくつか出てくるかと思います。そんなときには、公式ドキュメントを紐解き、疑問を解決するのが最も確実な方法でしょう。


それでは、気を取り直して一冊目の紹介に参ります。

自分でプログラムを組むの自体が初めての貴方へ

楽しみながら作ってみよう! はじめてのAndroidアプリプログラミング

楽しみながら作ってみよう! はじめてのAndroidアプリプログラミング

id:gabuchan が書いた、まさしく初心者のための本です。
ちょっと派手な電卓アプリを完成させることをゴールにしており、初心者を一歩一歩確実に導いてくれます。
初心者向けではありますが、Android 3.0で登場した画面分割と再利用を容易にした概念"Fragment"や、横フリックで画面切り替えを行う標準コンポーネント"ViewPager"を積極的に利用するなど、イマドキな開発の基本もしっかり抑えている良著です。
値段も2,310円と、技術書の中では割とお安いのも嬉しいところ。

慣れてきたぞ!と思ったときに手元に置いておきたい

Google Androidプログラミング入門 改訂2版

Google Androidプログラミング入門 改訂2版

!!!!WARNING!!!!
入門と銘打っていますが、この本を1番最初に買ってはいけません。心が折れます。

Androidアプリ開発でハマりがちなカユいところに手が届く、必携の一冊です。いつも手の届くところに置いておいて、「あれ?」と思った時に公式リファレンスよりも先に読むと疑問が解けるかも知れません。
ただし、全体的にエッセンスの紹介が中心であり、1から10まで教えてくれるようなゆとり仕様ではないので、「onClickってどうやると実装できるんだっけ・・・?」とかいうレベルの人がこの本を読むと高確率で死にます
2冊目くらいに買っておいて、末永く垢がつくほど読み込むのが正しい読み方です。

Android SDK開発のレシピ

Android SDK開発のレシピ

垢がつくほど読み込んで欲しい本その2。
この本は名前そのまま、「ちょっとこんなことしたいんだけどどうしたらいいだろう」に応えてくれるレシピ本です。
がぶちゃん2冊目だけど別に回し者ではないよ!! #がぶちゃん奢って
130個の収録レシピは、きっと小さなたくさんの「困った」を解決してくれるはず!
買ったらとりあえず目次だけひと通り読んで、興味のあるページだけ流し読んだら、あとは本棚で出番待ちをさせてあげてください。たぶんある程度の規模のアプリを作ろうとすると、常に手元にないと心細くなる時期があるくらいに役立つ本です。

アプリ開発の腕を洗練したくなったら

「アプリをもっと気持ちよくしたい!」と思った時に読んで欲しいのがこの3冊。

Androidプログラミング上達読本

Androidプログラミング上達読本

まずは、コード側が原因で起こっていた『モッサリ感』を解消するための一冊。
アプリの操作中になんの前触れもなく、いつ復帰するかも分からないまま画面が数秒フリーズしたら誰でも嫌ですよね。そんな嫌さを解消するためのノウハウを初めとして、Java側?からアプリを気持ちよくする方法が詰まった一冊です。

Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術

Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術

次はレイアウトXML側からアプリを気持ちよくするお話。
あなたがアプリを作るとき、InstagramPathのように、全てのコンポーネント(ボタンやチェックボックスなど)を自作しない限りは、標準コンポーネントのお世話になることになります。
標準コンポーネントにはどのような種類があり、どんな風にカスタマイズや配置を行えば綺麗に見えるようになるのか、それにより見えてくる「Androidらしさ」とはどんなものなのか。
奇をてらった独自UIを作る前に、1度読んで欲しい一冊です。

アプリの気持ちよさを求めたくなったら

iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン

iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン

原著の名前は"Tapworthy"、直訳すると「タップする価値のある」という形容詞(造語?)です。別名@fladdict本。
全体的に読み物と呼ばれるジャンルで、プログラムの話は全くと言っていいくらい出てきません。
この本に出てくるのは、iOSの名作における「気持ちよさ」や「タップしたくなるボタン」はどんなものに由来していて、我々がアプリを作る際にはどんなところに心血を注がなければならないか。何を目指し、何をするべきで、何をしてはいけないか。そんなことを教えてくれる本です。
1度ひと通り読んでフムフムと頷いてから、アプリを1本仕上げ、そのあとでもう一度読みたくなるような、そんな本だと思います。

スマートフォンデザイン見本帳

スマートフォンデザイン見本帳

最後の一冊は来週発売なのでオススメもクソもないのですが、simejiのデザイン担当にしてAndroid女子部の部長にしてデザインのカリスマ、矢野さんが実例を上げながらスマートフォンデザインのパターンと在り方について語る本とか、良著の匂いしかしないのです。
単純にいろんなアプリのデザインを見るだけでもたぶん価値のある一冊。

最後に

Androidを真面目にやろうとすると、多様な画面サイズ&縦横比、進化を続けるチップセット、一向に互換性を持たないカメラとGPS、などなどの特異性に頭を抱えることになりますので、できれば手を出すな。どうしてもスマホアプリ開発がしたかったらiOSから入りなさい。(台無し)
それでもなお、Androidからこの魔法の世界に入門したいというのなら、今回紹介した本など読みながら、迷子にならないように気をつけて歩んでいって下さい。
Androidは開発者からすると、まあ、ちょっとクセのあるダメな子な部分はありますけど、なかなか可愛いやつなんです。こういうことを言うようになると、だいたいもう手遅れなので、皆さんはこうなる前にiOSなりWindows Phone 8に退避したほうがいいかもしれません。
それでは皆さん、よいAndroid開発ライフを。


明日は@先生です。よろしく。

テストコード付きのFizzBuzz

なるほど。
「あるint型の数値を渡すとfizz, buzz, fizzbuzz, 数値の文字列のいずれかを返す関数」のテストをJUnit4で書いてみた。

package net.nkzn.fizzbuzz;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class FizzBuzzTest {

  @Test
  public void testFizzBuzz() {
    
    for(int i=0; i < 1000000; i++) {
      
      String value = FizzBuzz.eval(i);
      
      if (i % 3 == 0 && i % 5 == 0) {
        assertThat(value, is("fizzbuzz"));
      } else if (i % 3 == 0) {
        assertThat(value, is("fizz"));
      } else if (i % 5 == 0) {
        assertThat(value, is("buzz"));
      } else {
        assertThat(value, is(String.valueOf(i)));
      }
      
    }
  }
}

どうせなのでワンライナー実装もしてみたけど上手くできなかった・・・。

package net.nkzn.fizzbuzz;

public class FizzBuzz {

  public static String eval(int n) {
    return ""+((n%3==0)?"fizz"+((n%5==0)?"buzz":""):(n%5==0)?"buzz":n);
  }
  
}

感想

  1. テストと実装を両方とも自分でやると条件判定を二種類考えないといけなくてダルいので、人にやらせる場合はテストだけ書かせれば充分やな感ある
  2. 事実上テストと実装で同じ条件判定してるので、このテストでFizzBuzzの正しさを証明できているかというと割と自信ない(;´Д`)

Galaxy Nexusで起きた、画像についてのおかしな出来事

ある画像について、ギャラリーの「詳細情報」で見たファイルサイズと、Javaコード内でFile#length()したときのファイルサイズが大きく異なるという事象に遭遇したので、ひとまず現象だけ覚書。

ギャラリーで詳細情報を見た時のファイルサイズ

f:id:Nkzn:20120715223602p:image:w320

1.04MB。

File#length()したときのファイルサイズ

検証コード@gist
↑インテントでギャラリー呼んで、選んだ画像のファイルパスを手に入れるだけのコードです。

f:id:Nkzn:20120715223828p:image:w320

1965307Byte≒1.87MB。

ギャラリーに表示されているものの倍近いサイズです。なんぞ。

Dropbox経由で引っ張りだしてMac側で見た時のサイズ

f:id:Nkzn:20120715224225p:plain

1965307バイト。File#length()と同じ結果ですね。
んん? なんでギャラリーでは小さく表示されるんだろう?

Android File Transferで見た時のサイズ

Android File Transferとは、端末をマスストレージモードにしなくてもExternal Storage領域のデータをやりとりできる、Mac10.5&Honeycomb以上限定の素敵かどうかと言われると微妙なツールなのである!

ということで何となくこのツールでもファイルを見てみた。

f:id:Nkzn:20120715224427p:plain

1.0MB・・・?

流石に不審です。ドラッグアンドドロップでファイルを引きずり出してみましょう。

f:id:Nkzn:20120715224553p:plain


えっ

Android File Transfer経由で引っ張りだしてMac側で見た時のサイズ

f:id:Nkzn:20120715225233p:plain

サイズとかそういう次元じゃなかった。なんか欠損してる。
1095414Byte≒1.04MBなので、当初のギャラリーでの表示とは辻褄が合ってる。

考察

GNのファイルシステムがサイズの計算間違えてる感じなんだろうか。

  1. 何故かファイルシステムはこの画像を1.04MBだと思っている(というのがたぶんメタ情報として入っちゃってる)
  2. ギャラリーはイチイチ画像とか直接読んでられないので、たぶんメタ情報だけを見て1.04MBだって言ってる
  3. 本当は1.87MBある画像ファイルをFile Transferで取り出そうとすると、1.04/1.87MB分しか転送しない
    • なのでMacに転送されたものには欠損が起こる(別に端末内で欠損が起こってるわけではないたぶん)
  • DropboxやFile#length()はファイルシステム上どうかに関係なく実際のファイル全体を読んだり送ったりしているために影響を受けていないのでは
  • この現象が起きるファイルと起きないファイルがあるが、条件はよく分からない

感想&まとめ

むーん・・・。なんなんだろうこれ。
ひとまずFile#length()で読んでくる値は正しい感じがするから、仕事で詰まってた部分に関しては問題ないかな・・・。

うちにあるGN以外では試してないので、他所でも起きる現象なのかどうかは分かりませんが、とりあえずこんなことがありましたということで。

「ブログを書くまでが勉強会です」を実践して来なかったことへの懺悔

6月もそろそろ終わりますね。
このブログを見てくださってる方々は「なかざん、ブログ書く頻度多くになったなあ」とか思っていただいているかと思います。
それもそのはず。今月は密かに「”ブログを書くまでが勉強会です”実践月間」と位置づけて、できる限り、勉強会に出たことや、日頃調べたりしたことをブログにまとめるように心がけていました。

この記事で今月10個目。6月はあと1週間近くありますから、その間にもう2つほど記事を書けば、月間の記事数は人生トップになります。おそらく、現時点でも記事の文章量だけで言えば人生初の分量を書いていることでしょう。

「”ブログを書くまでが勉強会です”実践月間」は、大成功に終わりそうです。

今月参加した勉強会の記事

2つだけといえば2つだけなんですが、Niigata.pmの記事にスターが沢山ついていることからも分かるように、当日参加した方々から読んでいただいたり、Twitterでシェアしたりしていただけました。

参加者同士がレポ記事を書くことでさらに繋がっていく。勉強会当日に気付けなかったことが、さらに深みを増して自分の糧となる。「ブログを書くまでが勉強会です」という言葉の意味と意義を、初めて実感しています。

自分がやってきた勉強会はどうだったろう

日本Androidの会 新潟支部とか、Corona SDK方面とか、この2年間、ちょこちょことイベントは開いてきましたが、そのレポ記事を書いたことは、ほとんどありませんでした。
主催者がこのザマなので、参加者の方々もブログで感想を書いてくれることは稀でしたし、意義を理解できていなかった僕は呼びかけることすらしたことがありませんでした。

言っちゃえば、僕がブログでレポ記事を書かないということが、きっと僕がやってきた勉強会をインスタントに消費される勉強会に貶めてしまっていたのではないかなと思うのです。楽しさも、熱気も、そのときその場所にいた人たちだけで消費しきってしまう。外にも後にも残る記録がない。記憶の中にしか残らない。そして記憶に残っているだけの情報は、そうそう外には伝わらないし、いつかは薄れていってしまう。
もちろん、参加しなかった人が記事を読んだからって当日の臨場感を体験できるわけではありませんが、それでも伝わるものはあるはずです。そして逆に、参加した人であれば、記事を読んで当日の臨場感を鮮明に思い出すことで、楽しさや熱気を追体験できるのでは。

これまで、たくさんのイベントを終わらせてあげられなかった。正直、後悔してます。

これからの僕が(そして僕らが)やるべきこと

イベントをやったら、楽しさを、熱気を、ブログ記事として「形にして残す」。
主催者はもちろん主催者視点での記事を残すべきだし、参加者にも参加者視点での記事を残してもらえるように呼びかける。


まずは、来月のJSON日の金曜日半分ジョークで企画した勉強会でしたが、思った以上にガチなものになりそうです。
自分で勉強会を企画するのは、たぶん去年の11月以来です。今回からは、レポート記事を書いて、自分が主催する勉強会たちに引導を渡してやります。


ブログを書くまでが、勉強会です。

新潟のRubyistの飲み会(+勉強会)に紛れ込んできました【勉強会編】

新潟の Rubyist で集まりましょう! Ruby に興味があるという方もご参加ください!
新潟の Rubyist が集まるイベント : ATND

これね。
「とりあえず新潟って最近Rubyな人の集まりが全然ないよね。どんな人がいるのか知りたいね」ということで id:jewel12 先生が企画してくれました。

普段から「勉強会の本番は懇親会」論を唱える側の僕ですが、今回は本当に飲み会のほうが本番です。
ただ、初心者が多いということで、昼間にギークハウス新潟で初心者向けの「かんたん♪Ruby講習会」が行われました。

各種資料

こちら→ https://github.com/jewel12/ruby_lecture/

環境

OS 自由
Rubyバージョン 1.9系推奨

OSはWindowsやLinuxが多数派で、珍しいことにMac持ってきてるのが僕だけでした。
Linux使ってた id:saisa6153 先生が「MBPにコーヒーこぼして壊したから今Retina MBP待ちなんですよ!!」とか主張しててマジウケた(外道)

内容

  • 何故、Rubyを使うのか?
  • Rubyの基本的な使い方を写経しながら知る
    • 文法とかの話は少なめ
    • 他の言語で例えるともっと理解が深まりそうな場面も多々あった
    • 知っている言語が少ない人にとってはちょうど良かったかも
  • SinatraHamlでWebプログラミング
    • Hamlはインデントで階層構造を表現する
    • HamlコードをコンパイルするとHTMLになる素敵言語
    • PDF見ながら写経していた俺大勝利
    • 出席簿アプリ作りました

始まる前までの僕が持っていたRubyに関する知識

  • Matzさんが作った
  • 島根がゴリ押ししてる
    • Ruby合宿とか講師陣がガチすぎてやばい
  • RubyVM上で動作する言語
  • 全ての値はオブジェクトである
    • Javaのboolean, char, byte, short, int, long, float, doubleのようなプリミティブ型は存在しない
    • なので「1」のような数値は「数値(1ならInteger)クラスのオブジェクト」であり、「1.to_s」のようなメソッドを持つ
  • 実は新潟で一度盛り上がりそうになったけど立ち消えた歴史がある(後述)
  • 僕が書いたCorona本*1でお世話になっている達人出版会の高橋さんが会長をやっている日本Rubyの会というのがある。
    • RubyKaigi 2011の会期とCorona本の発売日をぶつけちゃって高橋さんには正直スマンカッタと思っている
    • 2011年にITコミュニティではなく一般社団法人として再スタートを切ったらしい

勉強会パートでは1つもこの辺の話が出てこなかったので、僕が知っていたRubyの知識は本当にRubyに関するものだったのか不安になりながら過ごしていました。

新潟とRuby

今、僕がいる会社は新潟産業創造機構(NICO)のお世話になっているわけなんですが、NICOの人から「何年か前に新潟でもRubyの勉強会がちょこちょことあったんだけどね」みたいな話を聞いたことがあって、当時の参加者達はコミュニティ活動もせずにどこへ消えてしまったんだろうという疑問がありました。
ということで、新潟とRubyのキーワードで引っかかる、過去のイベントをピックアップ。

2007/12/01 Ruby勉強会@新潟 第1回のお知らせ *2
2007/12/05 Rubyビジネスセミナー@新潟(Matzさん来てた)
2008/03/15 Ruby勉強会@新潟 第2回のお知らせ
2008/04/19 イケテルrails勉強会@新潟第1回について
2009/01/10 第2回NDS(第1回イケテルRails勉強会@長岡)参加したよ
2009/03/07 朱鷺メッセで「Ruby勉強会@新潟」が開催

簡単に探してみて出てきたのはこれだけ。多いかどうかはわからないけど、けっして少なくはないと思う。2007年末から2009年初めにかけて、新潟ではRubyのセミナーがそれなりに流行っていた、とは言えそう。
そして調べてみると飲み会にいた「いたさん」が当時のRuby振興にかなり貢献していたのがじわじわ見えてくる。あの人只者じゃないと思ってたけど本当に只者じゃなかった・・・!
いたさんみたいな方がいても続かなかったあたり、やっぱり技術者コミュニティを続けていくのって大変なんだなあ、とも思ったりした。

ということで、漏れがあるかも知れませんが今回のが概ね3年ぶりくらいのパブリックなRubyの勉強会になったようです。

今回の勉強会で分かったこと

  • なんか「スクリプト言語的なゆるふわさ」と「Java的なキッチリさ」の間を上手いこと取っている感じの言語なんだなあと思った
    • Luaっぽい文法あるなあと何度か思ったり
    • 隣の id:aokcub さんは「ここPerlっぽい」と何度か言ってた
    • 色んな言語のいいとこもらってきてるんだろうなあ感
  • 数値リテラルから直接メソッド叩くの楽しい
  • シンタックスシュガーに気をつけないと最悪の場合死に至る

勉強会中の疑問点1

「+記号で文字列結合するって話だけど、数値同士を文字列結合したい場合ってどうすんの?」
PerlPHPLuaなどの場合は、加算と文字列結合の演算子を別に用意しているので、この疑問は出てこないんですよね。

# Perlの場合
my $a = 1;
my $b = 2;
print($a.$b); # 12
print($a+$b); # 3
-- Luaの場合
local a = 1
local b = 2
print(a..b) -- 12
print(a+b)  -- 3

Rubyの場合は、+演算子文字列同士なら結合、数値同士なら加算と、ハッキリと役割が分けられています。
(今考えるとRubyの場合は普通の「演算子」だと思っていたこと自体が間違っていた*3のですが・・・)
それまで習っていた内容から僕が出した答えはこれ。

a = 1
b = 2
puts "#{a}#{b}" #=> 12
puts a+b #=> 3

ダサすぎて死にたくなりました。

まさか天下のRuby様が数値の文字列結合ごときにこんなダッサいソリューションしか用意してないわけないので、 id:jewel12 先生に質問してみました。答えはこれ。

a = 1
b = 2
puts a.to_s + b.to_s #=> 12
puts a+b #=> 3

「ダサい版より文字数増えてんじゃん・・・駄目じゃね・・・?」と最初は思ったものでしたが、『数値型もオブジェクト』という文化をまだちゃんと理解しきれていなかった自分を再確認できました。
ちなみにこのあと、飲み会でこの話題になったときに色々と意見を聞いて、ああ、これはこれで正しいんだ、と頷くことになりました。

わかったこと

Rubyは「何」と「何」を+で繋ごうとしているのかを考えることを僕らに強要してくれているのです。
変数に型を指定しない以上、その変数の中身が数値なのか文字列なのか他の何かなのか、実行するまで僕らには分かりません。
例えば、Luaには暗黙の型変換がないので、以下の様なことが起こりえます。(かなりアホな例ですが)

local number1 = 1
local number2 = "two"
-- +してはいけないのに変数名が紛らわしいので間違えて+しちゃう
print(number1 + number2) -- エラー:attempt to perform arithmetic on local 'number2' (a string value)

Rubyでも暗黙の型変換は原則行われないらしいので似たようなことは起こりうるのですが、文字列結合専用の演算子を用意しないことで「2つのオペランドが数値同士か文字列同士だと確実にわかっているとき以外の文字列結合では、to_sメソッドで両方のオペランドを文字列にしてから+しろよ」という文化を生み出しているようです。
Rubyよくできてんな。

勉強会中の疑問点2

よく出てくる|hoge|ってなんぞ
こういうコードですね。

5.times do |i|
    puts i
end

id:jewel12 先生に「この縦棒で囲まれてる変数って何なん?」と質問したら、なんだか実例を色々と見せていただけましたが、途中でlambdaとか使った実例も出てきて、まあみんな白目でしたよね。*4

lambda { |n| n ** 2 } # こんなん

最終的には「イテレータの中身を順次受け取る変数」みたいな理解をしましたが、さて、結局勉強会の中ではこの変数を何と呼ぶのか、名前が出てきませんでした。
名前が無いものを覚えるのはちょっと難しいので、名前を探してみましたよっと。

自分で定義したブロック付きメソッドでブロックを呼び出すときに使います。 yield に渡された値はブロック記法において | と | の間にはさまれた 変数(ブロックパラメータ)に代入されます。
メソッド呼び出し(super・ブロック付き・yield

ブロックパラメータというらしいです。
よし、これで覚えやすくなった(気がする)。

その他気づいて調べたこと

Rubyには、演算子扱いされているが実はメソッドだったりする演算子がある

プログラミングの利便のために一部のメソッド呼び出しと制御構造は演算子形 式をとります。Rubyには以下にあげる演算子があります。
演算子式

Ruby演算子オーバーロードができる」という話を聞いて、「あれ、それってScalaと同じじゃん? ってことは?」と思ってirbを叩いてみました。

1.+(2) #=> 3

なるほどできた。
ついでにもう一つ。

1.methods
# => [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :integer?, :upto, :downto, :times, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, :singleton_method_added, :coerce, :i, :+@, :eql?, :quo, :remainder, :real?, :nonzero?, :step, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, :between?, :nil?, :=~, :!~, :hash, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] 

うん、四則演算の演算子やらなんやらが、メソッドとして定義されているようですね。
このへん、ググっても決定的なのが出て来なかったんだけど、以下の2つのルールがシンタックスシュガーとして設定されていそう。

  1. 括弧を省略してもよい*5
    • a.b(c, d)を a.b c, d と書いてもいいらしい
    • 引数がない場合の空括弧()を省略していいのも似たような話かなたぶん
  2. メソッド呼び出しの際にドット(.)を省略してもよいものもある*6

誰か実際のところどうなのか教えてください。

まとめ

LL言語に手を出すのは1年前のLua以来なので、色々と新鮮な部分もあり、これまで学んできた内容が助けてくれるところもありと、かなり楽しい感じでした。
Haskellと並行になっちゃうけど、Railsか何かに取り組んでみようかなあ。

たのしいRuby 第3版
たのしいRuby 第3版
posted with amazlet at 12.06.24
高橋 征義 後藤 裕蔵
ソフトバンククリエイティブ
売り上げランキング: 5902

*1:いい加減書き直したいなあ

*2:協力のとこに@masuidriveさんがいる…だと…

*3:RubyScalaとかと同じで「+」もメソッド名

*4:「ラムダってなんだ・・・すごいH本とか読めば分かるのか・・・?」という極論まで出てましたね

*5:コメント欄の情報を受けて修正しました

*6:二項演算子限定ルールかも