2012年3月13日火曜日

GAE勉強会 2012/02/25 -- GAEをはじめよう~今更って言わないで~

yuka2py です。こんにちわ。2/26、大阪堂島のサントリー様にて行われた、神戸GTUGによる Google App Engine 勉強会のレポートです。今回は、GAE 上で利用できる3つの言語を比較して、コーディング方法がどのように変わるのかを確認することを通じて、初心者の方には GAE 利用のヒントやきっかけになること、また既に個別の言語などで利用されている方には、他言語への興味や可能性に繋がればということで開催されました。

開催日時:
2012年2月26日 土曜日
14:00~18:00

講師:
takagig さん(@takagig)Java
下田さん(@kuri65536)Python
ちいといつ さん(@titoi2)Go

 本稿の目次:

ところで、この日は開始前からハプニングです。Python の解説をしていただく下田さんが、突然のご病気で自宅から出れないとのこと。しかしそこは GTUG です。下田さんには、自宅から Google+ Hangouts で解説!してもらうことになりました。すごい! さてどうなることか。

また、開始前にちょっとしたアンケートを取りました。「GAE するにあたって、使ってみたい言語は?」結果、Java が多勢、Python 少々(2〜3人?)、Go ゼロということで、さすが Go 言語。ニューフェースだけに人気薄。講師のちいといつさんも苦笑いです♪






Java で GAE


まずは Javaです。講師の takagig さんから、スライドを見ながら、GAEの概要説明。昨今色々な Cloud 環境が出て来ていますし、GAE についても色々な議論があるようですが、やはり魅力的な環境であることに違いは無いかと思います。個人的には、なんとなく玄人っぽくて、かなり好きな方です♪

スライド:
http://www.slideshare.net/takagig/kobegtug-gaejava


環境構築:
それから Java/GAE の環境構築。ごくごく簡単に書くと、Java/GAE の環境構築は次の手順になります(詳しくはコチラで):
  1. GAE サイトで、Eclipse プラグインの url を見つけて
  2. Help > Install New Software から、
  3. 1で調べた url を追加して、Select All でインストール!
あと、JDK のインストールも忘れずに(僕は忘れてた)。 で、まー簡単。サクッと入る筈なんですが、なかなかどうして、環境構築ってハマりがちですよね。アチコチで苦悩のうめき声があがります♪(ちなみに僕もJDK入れ忘れてて、かつネットが遅くて「あと5時間です」って言われて Java のサンプル動かすのオワタのは内緒ですww)。さてさて、今回テーマにしたサンプルの動作は次のような感じです:

サンプルの概要(各言語共通):
サンプル実行画面
  1. Datastore からデータを取得して、一覧表示
  2. フォームからメッセージを投稿し、Datastore へ保存
シンプルですね! 今日はこれがどのように各言語で異なるか見ていきます。

皆さん環境構築やら、takagig さんから配布されたサンプルコードの動作を試す傍ら、サンプルの動作や仕組みについて takagig さんからスライドを用いて解説…ですが、実は僕は環境構築にアタフタしててあまり解説を聞けてなかったです…。すみません! …そんな感じでとても申し訳ないですが、僕が感じた Java/GAE に関する感想は次の通り:

Java/GAE 環境の特徴:
  • サーブレット標準やJDOが使えるし、Javaer には馴染みがある筈(当たり前か)
  • 当然というか、他の言語に比べ、ファイル数やコード量は多い(Javaだしネ!)
  • そしてコードもどうしても冗長
  • でも、Eclipse を使えば、高度なサポートがあって魅力
  • Datastore のアクセスに Low-Level API とかある(Pythonには無いですよね?)。難しいと思ってたけど、PHPで pg_xxxx 使うのと似てる。これ使える♪
  • Slim3 などの優れた MVC フレームワークも存在しているし、標準のサーブレットを構成するより、そっちの方が良いらしい(今回のサンプルは違うけど)
それでは、雰囲気を見てもらうためのサンプルです。なお以下に掲載するコードは、実際に勉強会で用いられたサンプルとは異なります。3言語を比較しやすくする為、なるべくシンプルに共通の構成に編集したものです。実際に勉強会で使われたサンプルは、もっと色々と各言語の特徴と、講師陣の個性が現れておりますので、興味をもたれた方はそちらも是非参考にしてください。

サンプルコード(Datastore周りまとめ版):
//モデルの定義(JDO使用)
@PersistenceCapable
public class Post {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    private String message;

    @Persistent
    private Date date;

    public Post(String message, Date date) {
        this.message = message;
        this.date = date;
    }
    public Key getKey() {
        return key;
    }
    public String getMessage() {
        return this.message;
    }
    public Date getDate() {
        return this.date;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public void setDate(Date date) {
        this.date = date;
    }
}

//リクエストハンドラ
@SuppressWarnings("serial")
public class SampleServlet extends HttpServlet {

    //メッセージ一覧と投稿フォームの表示
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setContentType("text/html");
        PrintWriter w = resp.getWriter();
        w.println("<html><head><title>Java</title><body>");
        
        //メッセージ一覧の取得と表示
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Query query = pm.newQuery(Post.class);
        query.setOrdering("date desc"); //日付降順でソート
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(
                    "yyyy-MM-dd hh:mm:ss ");
            @SuppressWarnings("unchecked")
            List<Post> posts = (List<Post>) query.execute();
            if (!posts.isEmpty()) {
                for (Post p : posts) {
                    w.print(dateFormat.format(p.getDate()));
                    w.print(p.getMessage());
                    w.println("<br />");
                }
            }
        } finally {
            query.closeAll();
        }

        //投稿フォームの表示
        w.println("<form method='post'>");
        w.println("<div><textarea name='message' rows='3' cols='60'></textarea></div>");
        w.println("<div><input type='submit' value='Send'></div>");
        w.println("</form>");
        w.println("</body></html>");
    }
    
    //投稿処理
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String message = req.getParameter("message");
        Post post = new Post(message, new Date());
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            pm.makePersistent(post);
        } finally {
            pm.close();
        }
        resp.sendRedirect("/");  //一覧画面へリダイレクト
    }

}
サンプルコード(勉強会使用分の一部):
http://code.google.com/p/kobe-samples/source/browse/trunk/GoogleAppEngineSample001/SampleServlet.java
  • Datesotre Low-Level API を利用
  • テンプレートに JSP の利用


Python で GAE

少しの休憩をはさんで、まだ Java 熱冷めやらぬ中、そろそろ Python… の声があがって下田さんの登場です。急病で自宅から Google+ Hangouts での解説です。すごい執念です。takagig さんが Hangouts のセットアップをして…ぉお、下田さんの声が聞こえます。やや小さいか…。まぁ、突然のことなので仕方ないですね (; ^ω^)。

スライド:
http://gtugdemo.pysandboxjp.appspot.com/html/Handson-kobegtug-gaepython-120225.html

環境構築:
まず環境構築。Python の環境構築は OS によってかなり異なるようです。下田さんの解説は Linux でしたが、会場は Windows or Mac ばかりです。僕は Mac でしたが、SDKをダウンロードしたらアプリが一つ出て来て、[Run] ボタン押してフニフニしてたら実行できました。パスを通すとか、SDK展開してモリモリとか無かったです。Windows も似たものらしいです。Linux もアーカイブを解凍するだけでだいたい OK みたいですが、パスとか通したらいいかも。まあ、Linux 使う方は大丈夫ですね♪ …とにかくいずれもそんなに難しくないということで、SDKは以下からダウンロードできます!(…と、内容薄くてすみません! 詳しくはコチラで)

Python環境の特徴:
Python はデータ型などの初歩から解説して頂きました。Python ユーザーは少ないだけにありがたい配慮ですね! Python 基礎を一通りさらってから、サンプルアプリの解説。下田さんのサンプルは、Google 認証なども取り込んで、ややリッチな仕上がりになっていたと思います。Google 認証について詳しくは解説のスライドをご覧ください。
  • Pythonらしく直感的でシンプルな記述ができる
  • 標準でシンプルな webapp フレームワークや、Django などの高級な WebApplicationフレームワークもそのまま使える
  • 扱いやすく、バリデーションの機能なども備えたモデルが使える
  • Java に比べると Spin-up が早い(らしい。slim3 と比べたらどうだろ?)
  • Eclipse でも PyDev などで開発は可能。ただし動的言語だし、Javaほど優れたサポートは無い

サンプルコード(会場使用分):
https://bitbucket.org/kuri65536/kobegtug1/get/tip.zip
  • Google Users API の利用
  • Django テンプレートの利用


サンプルコード(Datastore周りまとめ版):
#モデルの定義
class Post(db.Model):
    message = db.StringProperty()
    date = db.DateTimeProperty()

#リクエストハンドラ
class PostAction(webapp.RequestHandler):
    #投稿一覧と投稿フォームの表示
    def get(self):
        out = self.response.out.write
        out("<html><head></head><body>")

    #メッセージ一覧の取得と表示
        posts = Post.all()
        posts.order("-date") #日付降順でソート
        for post in posts:
            out(post.date.strftime("%Y-%m-%d %H:%M:%S: "))
            out(post.message)
            out('<br />')

        #投稿フォームの表示
        out('<form method="post">')
        out('<div><textarea name="message" rows="3" cols="60"></textarea></div>')
        out('<div><input type="submit" value="Send"></div>')
        out('</form>')
        out('</body></html>')
 
      
    #投稿処理
    def post( self ):
        post = Post()
        post.date = datetime.today()
        post.message = self.request.get('content')
        post.put()
        self.redirect('/')  //一覧画面へリダイレクト



Go で GAE

ちょっと押し気味で Go 言語開始。プロペラブのちいといつさん登場です。いつも通りの軽妙トークでサクサクと進行して頂きました。まずは環境構築。まだ Windows 用の環境は無いため、Windows の方は VM 使ったりして取り組んでおられたみたいです。手順はざっと次の通り:

環境構築:
  1. GAE サイトで、自分の環境にあったSDKをダウンロード:
    http://code.google.com/intl/en/appengine/downloads.html#Google_App_Engine_SDK_for_Go
  2. 適当な場所に展開して、SDK のトップディレクトリに PATH を通す。
たぶん Python の Linux 環境とほぼ同じ手順ですね(詳しくはコチラで)。特に難しいところは無い筈ですが、僕自身は GAE の開発サーバーを起動する時に、Python 環境のサーバーと被ったりしててしばらく上手く行かなかったです。結局、サーバースクリプトをフルパスで起動したら動きました。パス周りは後で整理しなきゃ、です。さて、Go/GAE 環境についての僕なりの感想は次のような感じです:

Go環境の特徴:
  • Javaに比べるとシンプルな記述
  • APIもシンプルに出来ているみたい(まだ整備されていないだけか?)
  • たぶん手頃なWebアプリケーションフレームワークもまだ出て来ていない?(どなたかご存知ならコメントください)
  • Go 言語については、コチラの記事もどうぞーです。
今回のサンプルの範囲では、Go 言語の特徴的な点があまり発揮されない感じだったですね。Go 言語が一体どういった利用シーンに向いているのか、また近いうちに ちいといつさんに聞いてみたいです。会場で使用したスライドやソースコードは、次に置いてあります:

スライド & 会場使用分のサンプルコード:
https://docs.google.com/#folders/0Bxy7Z3pBFtUONkhDLUNQdmVSZ21YNWsxTXZ5ZHowdw

サンプルコード(Datastore周りまとめ版):
//モデルの定義
type Post struct {
    Message  string //型は後ろに書く。先頭大文字がpublic
    Date datastore.Time
}       

//メッセージ一覧と投稿フォームの表示
func getList(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    w.Write([]byte(`<html><head><title>Go</title></head><body>`))

    //メッセージ一覧の取得と表示
    c := appengine.NewContext(r)
    q := datastore.NewQuery("Posts")
    q.Order("-Date") //日付降順でソート
    count, err := q.Count(c) //Goは関数が複数値を返せる
    if err != nil { }
    posts := make([]Post, 0, count) //Goのデータ型の1つ、slice の初期化
    _, err = q.GetAll(c, &posts)
    if err != nil { }
    for _, post := range posts {
        date := time.SecondsToLocalTime(int64(post.Date) / 1000000)
        datestr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d",
            date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second)
        wk := fmt.Sprintf("%s: %s<br />", datestr, post.Message)
        w.Write([]byte(wk))
    }

    //投稿フォームの表示
    w.Write([]byte(`<form action="register" method="post">`))
    w.Write([]byte(`<div><textarea name="message" rows="3" cols="60"></textarea></div>`))
    w.Write([]byte(`<div><input type="submit" value="Send"></div>`))
    w.Write([]byte(`</form>`))
    w.Write([]byte(`</body></html>`))
}       

//投稿処理
func putPost(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    var post Post
    post.Message = r.FormValue("message") 
    post.Date = datastore.SecondsToTime(time.Seconds())
    _, err := datastore.Put(c, datastore.NewIncompleteKey(c, "Posts", nil), &post)
    if err != nil { }
    http.Redirect(w, r, "/", http.StatusFound) //一覧画面へリダイレクト
}
ところで、ちいといつさんご用意ので、サンプルプログラムを実行するとコンパイルエラー。ちいといつさんに伺うと、なんでも理解を深めるために意図的に仕組んだそうで...ww Σ(゚Д゚;)!イジワル… 



[LT] シーケンサーを作ってみた!

飛び込み?で @esperia09 さんが GAE と HTML5 を駆使した Web シーケンサーを紹介して頂きました。確かお風呂で思いつかれて半日で作られたとか。スゴスです。機能を簡単に紹介すると次のような感じになります。
  • リズムシーケンサーみたいな画面
  • マトリックスをクリックしてドットを置くと、音が鳴る
  • ドラムパターンを作ったら、共有ボタンで世界に共有!
  • Java/GAE + Slim3 を利用
  • Web Audio API を利用
  • 半日で作った!



まとめ、気づいたこと、雑感

個人的な感想になってしまいますが、自分自身が Python を GAE で覚えたため、一番 Python をひいき目に見てしまいまして、やっぱり簡単に小さなものを作るのなら、Python かなーと思いました。ただ、大きなアプリケーションになるのであれば、Java で Slim3 などの Web Application Framework を利用するのがやっぱり良さそうにも思います。Eclipse 上でのコーディングを考えるなら、やっぱり Java が一番楽を出来そうに思うもので。Go言語は「これからの言語」には違いないかと思いますが、たぶん、ちゃんと組めれば、最も GAE 環境の恩恵を享受できる言語なんじゃないかと思っています。例えば小さなリクエストを大量に処理するとか、得意そうですよね。ということで、それぞれの環境について、誤解を恐れずに(あるいは誤解が含まれていることを恐れずに)僕の感想をまとめると、次のようになりました:
  • Java -- 小〜大まで、Javaらしくキッチリとアプリを作れるゾ!
  • Python -- 小さめのアプリならスピーディーに作れるゾ!
  • Go -- ちゃんと作れたら最速だゾ!これからのHTML5的なWebApp向き?
(めっさ乱暴ですみません (^_^;A


その他、参加者の皆さんの感想やコメントを以下にまとめてみました:
  • Cloud SQL って何だ?(takagig さんがしきりに言ってた)
  • Java/GAE の開発環境構築は、Eclipse の Install New Software から超ー簡単にできる!
  • Eclipse にプラグインインストールしたら再起動しておかないとw
  • EclipseはSDKをインストールしたら再起動が重要!
  • Eclipse で Javaの時、別のWebアプリ実行する場合は、一度サーバー停止しないとNG。Eclipse のコンソールの右上の方に赤い四角い停止ボタンがあるよ♪
  • Go言語構造体のメンバ編集は、大文字から始めたら public!! なんて不思議な!
  • Python と Goの GAE 開発環境は共存させるのには工夫が要りそう!


§ 謝辞

最後になりましたが、 本勉強会に会場をご提供いただいたサントリーさま、本当にありがとうございました!



6 件のコメント:

  1. ゆぅか@神戸GTUGさま

    ブログの編集ありがとうございます。
    見栄え良く、綺麗な仕上がりですね。
    さすがデザイナーさん、センスがいい!

    By hana

    返信削除
    返信
    1. いえいえ。とんでもない・・・。ブログの編集わ、思うようにならなくて苦手ですわ♪

      削除
  2. Go言語...初めて見ましたがこれはすごいですなw
    pythonばっかり触ってるんで新たな興奮を覚えました。

    返信削除
    返信
    1. はいー。面白そうですよねー♪
      わたしもちびっと興味がありますわー。

      削除
  3. おー。すごいキレイにまとまってますね!
    わかりやすいです!

    そうそう。僕も試行錯誤してやっと分かったのですが、
    「追記の区切りを挿入」(半分にギザギザで分かれた白いアイコン)を使うと
    「続きを読む」が表示されて記事が折りたためるので、
    スッキリ感が出るかもしれません。オススメです。

    返信削除
    返信
    1. 「続きを読む」入れときましたー。アドバイスサンクスです!

      削除