エンジニアtypeさんの連載:ギークな女子会 acotie編の原稿について補足と私信

http://engineer.typemag.jp/brightw/2011/07/-acotie.php の補足と私信です。
思いのほか長くなってしまったので、一部の方以外はスルーしてください><

今回のエントリーを書くに至った経緯、ごく一部の方に誤解を招くような表現

エンジニアtypeさんで座談会企画をさせて頂いた内容ですが、実際に私がドワンゴで働いていなかったような表現になっているのは事実です。

時間の制約がある中で、私が元ドワンゴ社員ということは自己紹介の際にも、取材中にも編集部の方にも何度もお伝えしましたし
実際には全面的にドワンゴの開発部の内情を知った上でつっ込んだ内容の話や質問もしていました。*1

しかし編集の方が必要ないと判断されたのか内容がバッサリ消されていたり、編集部の方が質問した内容が私が言ったようにすり変えられていました。
結果的にできあがった原稿全体の流れとして、非常によそよそしい内容となってしまいました。

あとはコンテンツの強調するポイントにもすこし疑問を感じる部分もありますが、編集部の方もお仕事でPVを稼ぐコンテンツとして必要な要素であり
多少の文章の改変や誇張は必要なのがメディアというものなのかなと思い、表向きには今まで特になにも言及せずにいました*2


そして先日お会いした方々に「エンジニアtypeの記事に対して、あたかもacotieがドワンゴで働いていなかったことになっているので、元上司が心を痛めていた」という旨を伝えられ、なんだか複雑な心境になりました。
すぐに今回の経緯と感謝の気持ちを改めて伝えようと、このエントリーを書くことを決意しました。

ドワンゴ在籍時の振り返り

わたしは2008年の初旬に元上司とネット上で知り合い、偶然にもnipotan niteの二次会で初めてお会いし
2008年5月にいろいろあって気持ちがどん底になりながら転職を探している際にTwitter経由でドワンゴに誘って頂きました。
在籍中は本当にずっとお世話になりっぱなしでしたし、今では考えられないほど自己中心的とも言えるような行動を会社でしていました。
非常識極まりない行動に対しても特に怒られなかったですし、むしろ気持ちを理解しようと一生懸命努力し、いつも笑顔と寛大な心で受け入れてくれました。
当時はきっと上司の優しさにどこまでも甘えていたのだと思います。思いますというより周囲にも自分にも甘えていました。


退職後、迷惑ばかりかけた上にろくに成果も出さずに辞めたことを後悔することが多々ありました。
今でも元上司には顔向けできないですし、申し訳ない気持ちでいっぱいです。


1年と数ヶ月間という短い間でしたが、たくさんの方々にお世話になり、私にとって本当にかけがえのない時間です。
特に今でも元上司のことは尊敬していますし、優秀な方々と一緒に働けて本当に光栄でした。
すこしだけ成長できたのもドワンゴという会社、上司や同僚のおかげですし、本当にすごく感謝しています。
これは後からとってつけたフォローではなく、今までずっと言葉にしてこなかった本心です。

あくまでも私信

ぜんぜん知らない第三者が記事を見る上では、全くドワンゴを知らないふりをして質問している形にして頂いても構わないのですが
一部のお世話になった方々に対して誤解を招くような結果となってしまいましたので、このような拙い文章を書きました。


けっして企画のあり方や編集の仕方についての提言をしているわけではありません。事前に原稿も確認した上で了承しています。
重ねて言いますが、今回の記事の内容が全体的によそよそしい内容になってしまったということに関して、誤解を解きたいと考えています。

不特定多数の方が閲覧ができるウェブの媒体で、特定の方・お世話になった方が心を痛めることは不本意であり残念で悲しいです。
今回の件は、私がもうすこし原稿確認の段階で配慮するべきであったと反省しております。

今後の活動を通してなにか還元できるように、前向きに行動し、地に足をつけながら毎日楽しくプログラミングをして過ごしています。
すこし過去を振り返ってみても、現在まわりを見回しても、やはり人とのご縁にだけは本当に恵まれでいるとしか言いようがありません。
このようなオープンな形式でしか伝えられませんでしたが、もしいつか謝罪と感謝の気持ちを直接述べる機会を頂けるようであれば、私は非常に嬉しく思います。

*1:佐々木さんや韓さんに聞いて頂ければわかると思います。

*2:あとから細かいですが、実際には「開発環境をデコる」とか誰も一言も言っていないとか、やたらピンクの文字とかを強調するとか、そういう見出しの内容について気になる程度です。

エンジニアtypeさんで連載:ギークな女子会が公開になりました(すこし裏話

本日付けでエンジニアtypeさんでの連載記事が公開になりました。


先日、開発者としてエンジョイされている@shokosこと佐々木 抄子(ささき しょうこ)さんと@purewishこと韓 松熙(はん そんひ)さんと一緒にお話しさせて頂く機会がありました。

担当の1回目というのもあり、面識があるお二人しかいない!*1と思って、ドキドキしながら声をかけさせて頂きました。(元同僚・Perlつながりメソッド)

佐々木さん、韓さんの印象

間違いなくお二人とも意識的なレベルも高く、問題をいかにクリアするか、いかに学習できるかということを常に考え、楽しくお仕事をされているといった印象を受けました。

現在の会社の働く環境(まわりの人達、開発環境、社風など)がいかに恵まれているか、といえばそれに集約されるのかもしれませんが

その言葉だけでは片付けられないような上手くいく発想、取り組み方といった秘訣も多々あり、すごく勉強になりました。*2

モチベーションとなっているもの

こういう取材的なものが得意ではないのですが、もっとがんばってる人が前に出て評価される業界であってほしいということと

わりとストイックな感じのエンジニアもいるんだねーという印象づけをすることによって

もっともっとネット上のおもしろい人達がカジュアルに前に出やすくなるようなきっかけになれば幸いです。


どうでもいいですが、カップルでエンジニアというのもちょっとだけうらやましいですね。
それから、みんな白い服なのはドレスコードだからです(ウソ


今後も「ギークなお姉さん」こと、べにぢょさん(@lovecallさん)と交互に公開されていきますので、楽しみにしてくださいね!

下記のリンクから過去のアーカイブが見れます。
べにぢょ&acotieとギークな女子会❤ | 輝け!女子部 | エンジニアtype - エンジニアのシゴト人生を考えるWebマガジン べにぢょ&acotieとギークな女子会❤ | 輝け!女子部 | エンジニアtype - エンジニアのシゴト人生を考えるWebマガジン このエントリーをはてなブックマークに追加

*1:ついでにしょっぴーはとってもカワイイし、ハンさんはホントにキレイだし、2人共バリバリの技術者でリア充なイメージもあるので!

*2:コードが書くのが本当に楽しい!といった職人肌なお二人とお話しをしていると、自然と正直私はそこまで楽しめているのかな?という疑問が浮かびました>< 最近、もしかしたらどこか自分の中で義務感で仕事をしている部分も多少あるのかもしれません。

Smiley Hackathon#10のお知らせ

またしても告知です。苦手な方はスルーしてください!

おかげさまで日本で一番ゆるいイベントとなりつつある Smiley Hackathonも10回目になりました!

エンジニアの為のスキル向上の為の不定期もくもくイベントです。

ハッカソンというと非常にとっつきにくいイメージですが、ルールや言語のしばりは一切ありません。

プログラミングが好きな方、これから勉強しようと思っている方、興味があれば全然OKです。

今回も株式会社ガイアックス様に会場を提供して頂ける事になりました。心からお礼を申し上げます。

smiley hackathon#10

2011/7/2(土) 13:00〜20:00 @ガイアックスさん


↓ ご応募はatndにて受け付けています! ↓

Smiley Hackathon#10 : ATND Smiley Hackathon#10 : ATND

過去の実績や振り返り

もとはといえば私がガリガリとコードを書きたい!という自己中的な発想のもと始めたイベントですが、
それなりに過去にちゃんとアウトプットされていらっしゃる参加者も多いです。

過去に発表されたもの

iPhoneアプリchromeエクステンション、Cでコンパイラや処理系のライブラリ、LispRubyPerlPythonPHPwebサービス、ライブラリの開発、
Flexでアプリ、お仕事のコードを書かれている方、原稿やドキュメント・発表するスライドを書かれている方....ect。

それなりに時間のかかる構想のものもありますし、アウトプットを強制する雰囲気はよくないと思っているので、好きな方だけして頂いています。
アプリ単位でなくても工夫した点をコードレビューだけという方もいらっしゃいます。

エンジニア同士で意気投合して集まったり、転職をされる方も

実際にすきな共通のプログラミング言語で仲良くなって、個別に集まって勉強をされたり、ハッカソンきっかけで転職されたりというパターンがありました。

きっとSmiley Hackathonじゃなくても知り合っていたでしょうし、ドヤ顔をするつもりもありませんが、そういうことを間近で見ていて非常に嬉しく思えます。

実際に参加された方の声

これは去年の#9の時にg177564さんがつぶやかれてたpostのようです。
そこまでビックリするくらい、ゆるーーーーーーーくアピールしたつもりはないのですが、たしかに毎回雑な終わり方で反省しています><

http://twitter.com/g177564/statuses/21127146102


今年の4月頃?にid:sugyan氏がつぶやかれていたpostのようです。ぐぐって知りました。
色んな言語好きな方がいらっしゃると勉強になるのは事実です。意図するところが同じでうれしいですw

すぎゃーん💯 on Twitter: "個人的にSmiley Hackathonはすごい良いなーと思っていて、言語やレベル問わずコード書きたいヒトが集まって好き勝手書きながら分からないこととか周りで訊けるヒトいれば訊いて、と。…そういうのがもっと頻繁に色んなところで開催されるようになればいいなと思ってる"

もういちど

atndだけでなく、めんどくさかったらIRCのacotieかtwitter@acotie宛まで声かけてくださいね!

Smiley Hackathon#10 : ATND Smiley Hackathon#10 : ATND

2011/06/25 追記

いつの間にか定員超えていました。どうもありがとうございます!
会場のキャパ的には全然オーバーしても大丈夫ですので、興味のある方はぜひ参加してみてくださいね^^;

IBM DB2の記事が公開になりました

こんにちは!やたら多い転職回数を活かして、未経験者にweb系エンジニアへの転職アドバイス的なボランティアもしているacotieです。

実は東日本大震災以前にほぼ完了しておりました、IBM DB2はてブPR記事が2011年5月23日付けで公開されています。

今回は、個人としても尊敬している株式会社はてなの中の方に声を掛けて頂いたというのも非常に感慨深いです。


Perl好きの女性Webエンジニア二人がIBM DB2を試してみた - はてなブックマークニュース Perl好きの女性Webエンジニア二人がIBM DB2を試してみた - はてなブックマークニュース

意外とちがったIBM社の雰囲気

DB2スペシャリストの方々に直接レクチャーして頂く機会というのは、なかなか経験できない貴重なものです。

もちろん台本もなく、話の内容とマッチするのか非常にドキドキしていましたが

非常に丁寧に進めて頂いたり教えて頂いたおかげで、終始和やかな雰囲気であっという間に時間が過ぎました。

事前にDB2 Express-CをMacにインストールし、DB2 9.7 エバリュエーション・ガイドブックを献本頂き、勉強する期間がありました。

DB2 9.7 エバリュエーション・ガイドブックには概念的からDB2 Express-Cのインストール、pureXMLとよばれるXMLデータを取り扱う機能についてや

ハイブリッド・データベースと呼ばれる事柄について詳しく説明があり、すんなりと理解することができました。

DB2 9.7 エバリュエーション・ガイドブック

DB2 9.7 エバリュエーション・ガイドブック

レクチャーの内容も無料でDB2がインストールができること、XQueryと呼ばれるXPathを使ったSQL文でアクセスしてみたり、自動チューニングの箇所、個人でのチューニング方法であったり、初めて知ったことが沢山ありました。

DB管理者必見の本が好評発売中

また記事の中で登場される下佐粉昭さんは、著書の「即戦力のDB2管理術 〜仕組みからわかる効率的管理のノウハウ」という本が4月8日に発売されたばかりです!

エキスパートな方から見た実践的なDB2の管理方法や、具体的な方法論やTipsが満載で必見です。

  • DBのバックアップの方法
  • プロセス/メモリ/ディスク監視方法
  • トランザクションなどのパフォーマンス監視
  • 実際に起こり得るトラブル解決の為の対処法
  • パフォーマンスチューニング
  • ベンチマーク
  • アクセスプランの確認
  • メモリ関連のパラメータの調整方法
  • ディスクアクセス自体の高速化など

個人的に第4部 (P.264〜P.409) のパフォーマンスチューニングの章は分かりやすく勉強になりますし、
DB2ではなくてもDB全般の教科書として使えるような内容で感動しました。

即戦力のDB2管理術 ?仕組みからわかる効率的管理のノウハウ

即戦力のDB2管理術 ?仕組みからわかる効率的管理のノウハウ


またIBMの方々も技術者とコミュニケーションを欲していること(全然ツンではない)、定期的にClub DB2という勉強会を開催されていること

有効な広告宣伝として "はてな"という広告媒体を選択されたこと、歴史ある有名な企業もソーシャルな広告の方にシフトされているんだなぁ、と色々と印象的でした。

id:aomushi510さん、はてなid:mtakanoさん、id:rikoさん、IBMさんの中林紀彦さん、下佐粉昭さん、IBMさんの関連の方々、このような機会を頂きまして本当にありがとうございます。

近況とゆるやかな募集

あと全然関係ないですが、横山と仕事してやってもいいよ!という会社さんをすごくゆるやかに募集しています。

有難いことに複数の会社の方に声を掛けて頂いてはいるものの、諸事情の関係上まだお会いして具体的な話はしていない状況です。

ご挨拶ができていない方も多いのですが、昨年の年明けからフリーランスとしてお仕事させて頂いております。

ここ2年間ほど大きな飲み会やオフ会などに全く参加しなくなった為、疎遠になっていると感じられている方も多いかもしれません。

というのも昔からメールやDM不精かつ自分からメールや連絡をあまりしないタイプで受身な人間な為
反省し言い訳をなくすために色々と行動を変えようとしている最中です。

お世話になった方や挨拶をしたい方も沢山います。

お世話になった方々にひとりひとり何かおいしいゴハンでもご馳走させてほしいです。そして次は奢ってほしいですw


直近ではNDAの関係で言えませんが、Perlを使った大手のwebサービスの開発をしたりしています。

個人では、AIR for Androidで軽くAndroidアプリ作ったり、iPhoneアプリもTitaniumとかUnity3dやcocos2dとか超入門中の身です。

Smiley Hackathonwebrick cafeについては、近日中にまたよいご報告ができるかと思います。

都内近郊であれば、仕事じゃなくても軽くランチやお茶したい!とかお話ししてみたい!という方も声掛けてくださるとうれしいです^^;

WEB+DB PRESS Vol.61のPerl Hacker Hub 第7回 「新人さんのための仕事で使えるPerl基礎知識」を寄稿しました

WEB+DB PRESS Vol.61 / Perl Hacker Hub

2011/2/24より技術評論社さんから発売される、WEB+DB PRESS Vol.61Perlリレー連載のPerl Hacker Hub第7回、「新人さんのための仕事で使えるPerl基礎知識」を寄稿しました。

ざっくり内容

前半はPerlの世界でデファクトスタンダーとになりつつある最新の環境構築について、cpanm + perlbrewを紹介させて頂きました。
後半はPerlをはじめて今まで、個人的に苦手だった箇所・つまづきやすい部分などを中心に書きました。

どうしてこのテーマだったのか

きっと同じようにつまずいている方や苦手意識を持っている方は本当に沢山いらっしゃると思いますし、実際によく質問されたりする箇所でもあります。
この連載自体が錚々たる顔ぶれの中、恐れ多くも内容について真剣に考えた結果、オリジナリティあふれる独自の内容になったように思います。

ぜひこれからPerlをはじめたいと思われている方や、今も勉強されている方などに読んで頂きたいです!!*1

主な内容は以下の通りです :D

  • 今どきのCPAN環境構築術
    • cpanコマンド
      • cpanコマンドの確認
      • cpanコマンドの使い方
    • cpanmコマンド
      • cpanmコマンドのインストール
      • cpanmコマンドの使い方
      • 新たにCPANの環境を移行する
      • 環境変数の設定
    • cpan-outdatedを使い全モジュールのアップデートを行う
    • perlbrewコマンド
      • perlbrewコマンドのインストール
      • perlbrewコマンドの使い方
      • 環境変数の設定
  • 変数
    • use strictとuse warnings
      • use strict
      • use warnings
    • スコープ制御
      • レキシカルスコープ宣言とグローバル宣言
      • my
      • local
      • our
    • よく使われる特殊変数
      • $_
      • @_
      • $@
      • 擬似シグナル
  • リファレンス/デリファレンス
  • おわりに

さいごに

編集長をはじめ、編集部の方々、牧さん、大沢さん、アドバイスやご指摘など、ご協力頂きましてありがとうございます。
そして今後ともよろしくお願い致します。

Twitterハッシュタグは#wdpressです!


Amazon

WEB+DB PRESS Vol.61

WEB+DB PRESS Vol.61

楽天ブックス
[rakuten:book:14327074:detail]

*1:特集のTitaniumでiPhone&Androidアプリ開発やRails3テストの特集もだいぶ熱いテーマですので、開発者は特に必見です!

AKB48のメンバー情報を取得するスクリプト

WEB::Scraperを使い、各チームのメンバーの一覧の名前、写真、詳細ページURLが取ってみました。
Acme::AKB48みたいに、リンクをたどって常に最新データを動的に作れるようになれるようにしたいなと思います。
2010年の年末から研究生が昇格して56人なんですけどねー。

#!/opt/local/bin/perl
use strict;
use Web::Scraper;
use URI;
use yaml;

my $uri = URI->new("http://www.dmm.com/akb48/-/akb48member/");
my $scraper = scraper {
    process '/html/body/table/tr/td[2]/div/div[4]/a', 'TeamA[]' => scraper{
        process "img", name => '@alt', image => ['@src', sub{ $_->as_string}];
        process "a", link => [ '@href', sub{ $_->as_string}];
    };
    process '/html/body/table/tr/td[2]/div/div[7]/a', 'TeamK[]' => scraper{
        process "img", name => '@alt', image => ['@src', sub{ $_->as_string}];
        process "a", link => [ '@href', sub{ $_->as_string}];
    };
    process '/html/body/table/tr/td[2]/div/div[10]/a', 'TeamB[]' => scraper{
        process "img", name => '@alt', image => ['@src', sub{ $_->as_string}];
        process "a", link => [ '@href', sub{ $_->as_string}];
    };
    process '/html/body/table/tr/td[2]/div/div[13]/a', 'Kenkyusei[]' => scraper{
        process "img", name => '@alt', image => ['@src', sub{ $_->as_string}];
        process "a", link => [ '@href', sub{ $_->as_string}];
};


};
my $result = $scraper->scrape($uri);

output

---
TeamA:
  - image: http://pics.dmm.com/digital/akb48/list/iwasa_misaki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=49/ch_navi=akb48member/sort=date/
    name: 岩佐美咲
  - image: http://pics.dmm.com/digital/akb48/list/oota_aika.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=17/ch_navi=akb48member/sort=date/
    name: 多田愛佳
  - image: http://pics.dmm.com/digital/akb48/list/ooya_sizuka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=51/ch_navi=akb48member/sort=date/
    name: 大家志津香
  - image: http://pics.dmm.com/digital/akb48/list/katayama_haruka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=19/ch_navi=akb48member/sort=date/
    name: 片山陽加
  - image: http://pics.dmm.com/digital/akb48/list/kuramoti_asuka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=38/ch_navi=akb48member/sort=date/
    name: 倉持明日香
  - image: http://pics.dmm.com/digital/akb48/list/kozima_haruna.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=5/ch_navi=akb48member/sort=date/
    name: 小嶋陽菜
  - image: http://pics.dmm.com/digital/akb48/list/sasihara_rino.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=22/ch_navi=akb48member/sort=date/
    name: 指原莉乃
  - image: http://pics.dmm.com/digital/akb48/list/sinoda_mariko.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=8/ch_navi=akb48member/sort=date/
    name: 篠田麻里子
  - image: http://pics.dmm.com/digital/akb48/list/takazyou_aki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=9/ch_navi=akb48member/sort=date/
    name: 高城亜樹
  - image: http://pics.dmm.com/digital/akb48/list/takahasi_minami.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=10/ch_navi=akb48member/sort=date/
    name: 高橋みなみ
  - image: http://pics.dmm.com/digital/akb48/list/nakagawa_haruka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=24/ch_navi=akb48member/sort=date/
    name: 仲川遥香
  - image: http://pics.dmm.com/digital/akb48/list/nakata_tisato.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=11/ch_navi=akb48member/sort=date/
    name: 中田ちさと
  - image: http://pics.dmm.com/digital/akb48/list/nakaya_sayaka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=26/ch_navi=akb48member/sort=date/
    name: 仲谷明香
  - image: http://pics.dmm.com/digital/akb48/list/maeda_atuko.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=13/ch_navi=akb48member/sort=date/
    name: 前田敦子
  - image: http://pics.dmm.com/digital/akb48/list/maeda_ami.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=62/ch_navi=akb48member/sort=date/
    name: 前田亜美
  - image: http://pics.dmm.com/digital/akb48/list/matubara_natumi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=45/ch_navi=akb48member/sort=date/
    name: 松原夏海
TeamB:
  - image: http://pics.dmm.com/digital/akb48/list/isida_haruka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=47/ch_navi=akb48member/sort=date/
    name: 石田晴香
  - image: http://pics.dmm.com/digital/akb48/list/oku_manami.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=35/ch_navi=akb48member/sort=date/
    name: 奥真奈美
  - image: http://pics.dmm.com/digital/akb48/list/kasai_tomomi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=37/ch_navi=akb48member/sort=date/
    name: 河西智美
  - image: http://pics.dmm.com/digital/akb48/list/kasiwagi_yuki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=18/ch_navi=akb48member/sort=date/
    name: 柏木由紀
  - image: http://pics.dmm.com/digital/akb48/list/kitahara_rie.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=4/ch_navi=akb48member/sort=date/
    name: 北原里英
  - image: http://pics.dmm.com/digital/akb48/list/kobayasi_kana.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=39/ch_navi=akb48member/sort=date/
    name: 小林香菜
  - image: http://pics.dmm.com/digital/akb48/list/komori_mika.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=54/ch_navi=akb48member/sort=date/
    name: 小森美果
  - image: http://pics.dmm.com/digital/akb48/list/satou_amina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=6/ch_navi=akb48member/sort=date/
    name: 佐藤亜美菜
  - image: http://pics.dmm.com/digital/akb48/list/satou_sumire.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=56/ch_navi=akb48member/sort=date/
    name: 佐藤すみれ
  - image: http://pics.dmm.com/digital/akb48/list/satou_natuki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=40/ch_navi=akb48member/sort=date/
    name: 佐藤夏希
  - image: http://pics.dmm.com/digital/akb48/list/suzuki_mariya.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=58/ch_navi=akb48member/sort=date/
    name: 鈴木まりや
  - image: http://pics.dmm.com/digital/akb48/list/tikano_rina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=59/ch_navi=akb48member/sort=date/
    name: 近野莉菜
  - image: http://pics.dmm.com/digital/akb48/list/hirazima_natumi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=28/ch_navi=akb48member/sort=date/
    name: 平嶋夏海
  - image: http://pics.dmm.com/digital/akb48/list/masuda_yuka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=44/ch_navi=akb48member/sort=date/
    name: 増田有華
  - image: http://pics.dmm.com/digital/akb48/list/miyazaki_miho.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=15/ch_navi=akb48member/sort=date/
    name: 宮崎美穂
  - image: http://pics.dmm.com/digital/akb48/list/watanabe_mayu.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=30/ch_navi=akb48member/sort=date/
    name: 渡辺麻友
TeamK:
  - image: http://pics.dmm.com/digital/akb48/list/akimoto_sayaka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=31/ch_navi=akb48member/sort=date/
    name: 秋元才加
  - image: http://pics.dmm.com/digital/akb48/list/itano_tomomi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=1/ch_navi=akb48member/sort=date/
    name: 板野友美
  - image: http://pics.dmm.com/digital/akb48/list/utida_mayumi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=48/ch_navi=akb48member/sort=date/
    name: 内田眞由美
  - image: http://pics.dmm.com/digital/akb48/list/umeda_ayaka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=32/ch_navi=akb48member/sort=date/
    name: 梅田彩佳
  - image: http://pics.dmm.com/digital/akb48/list/oosima_yuuko.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=33/ch_navi=akb48member/sort=date/
    name: 大島優子
  - image: http://pics.dmm.com/digital/akb48/list/kikuti_ayaka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=53/ch_navi=akb48member/sort=date/
    name: 菊地あやか
  - image: http://pics.dmm.com/digital/akb48/list/tanabe_miku.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=23/ch_navi=akb48member/sort=date/
    name: 田名部生来
  - image: http://pics.dmm.com/digital/akb48/list/nakatuka_tomomi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=25/ch_navi=akb48member/sort=date/
    name: 中塚智実
  - image: http://pics.dmm.com/digital/akb48/list/nitou_moeno.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=27/ch_navi=akb48member/sort=date/
    name: 仁藤萌乃
  - image: http://pics.dmm.com/digital/akb48/list/nonaka_misato.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=60/ch_navi=akb48member/sort=date/
    name: 野中美郷
  - image: http://pics.dmm.com/digital/akb48/list/huzie_reina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=12/ch_navi=akb48member/sort=date/
    name: 藤江れいな
  - image: http://pics.dmm.com/digital/akb48/list/matui_sakiko.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=63/ch_navi=akb48member/sort=date/
    name: 松井咲子
  - image: http://pics.dmm.com/digital/akb48/list/minegisi_minami.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=14/ch_navi=akb48member/sort=date/
    name: 峯岸みなみ
  - image: http://pics.dmm.com/digital/akb48/list/miyazawa_sae.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=46/ch_navi=akb48member/sort=date/
    name: 宮澤佐江
  - image: http://pics.dmm.com/digital/akb48/list/yokoyama_yui.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=136/ch_navi=akb48member/sort=date/
    name: 横山由依
  - image: http://pics.dmm.com/digital/akb48/list/yonezawa_rumi.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=29/ch_navi=akb48member/sort=date/
    name: 米沢瑠美
Kenkyusei:
  - image: http://pics.dmm.com/digital/akb48/list/abe_maria.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=150/ch_navi=akb48member/sort=date/
    name: 阿部マリア
  - image: http://pics.dmm.com/digital/akb48/list/izuta_rina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=151/ch_navi=akb48member/sort=date/
    name: 伊豆田莉奈
  - image: http://pics.dmm.com/digital/akb48/list/itikawa_miori.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=152/ch_navi=akb48member/sort=date/
    name: 市川美織
  - image: http://pics.dmm.com/digital/akb48/list/iriyama_anna.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=153/ch_navi=akb48member/sort=date/
    name: 入山杏奈
  - image: http://pics.dmm.com/digital/akb48/list/usikubo_sara.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=160/ch_navi=akb48member/sort=date/
    name: 牛窪紗良
  - image: http://pics.dmm.com/digital/akb48/list/ooba_mina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=126/ch_navi=akb48member/sort=date/
    name: 大場美奈
  - image: http://pics.dmm.com/digital/akb48/list/katou_rena.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=155/ch_navi=akb48member/sort=date/
    name: 加藤玲奈
  - image: http://pics.dmm.com/digital/akb48/list/kanazawa_yuuki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=156/ch_navi=akb48member/sort=date/
    name: 金沢有希
  - image: http://pics.dmm.com/digital/akb48/list/kawaei_rina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=161/ch_navi=akb48member/sort=date/
    name: 川栄李奈
  - image: http://pics.dmm.com/digital/akb48/list/kozima_natuki.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=162/ch_navi=akb48member/sort=date/
    name: 小嶋菜月
  - image: http://pics.dmm.com/digital/akb48/list/kobayasi_marina.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=157/ch_navi=akb48member/sort=date/
    name: 小林茉里奈
  - image: http://pics.dmm.com/digital/akb48/list/simazaki_haruka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=128/ch_navi=akb48member/sort=date/
    name: 島崎遥香
  - image: http://pics.dmm.com/digital/akb48/list/simada_haruka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=137/ch_navi=akb48member/sort=date/
    name: 島田晴香
  - image: http://pics.dmm.com/digital/akb48/list/suzuki_sihori.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=57/ch_navi=akb48member/sort=date/
    name: 鈴木紫帆里
  - image: http://pics.dmm.com/digital/akb48/list/takeuti_miyu.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=130/ch_navi=akb48member/sort=date/
    name: 竹内美宥
  - image: http://pics.dmm.com/digital/akb48/list/nakamata_siori.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=158/ch_navi=akb48member/sort=date/
    name: 仲俣汐里
  - image: http://pics.dmm.com/digital/akb48/list/nakamura_mariko.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=132/ch_navi=akb48member/sort=date/
    name: 中村麻里子
  - image: http://pics.dmm.com/digital/akb48/list/nagao_mariya.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=131/ch_navi=akb48member/sort=date/
    name: 永尾まりや
  - image: http://pics.dmm.com/digital/akb48/list/natori_wakana.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=163/ch_navi=akb48member/sort=date/
    name: 名取稚菜
  - image: http://pics.dmm.com/digital/akb48/list/huzita_nana.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=159/ch_navi=akb48member/sort=date/
    name: 藤田奈那
  - image: http://pics.dmm.com/digital/akb48/list/mori_anna.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=134/ch_navi=akb48member/sort=date/
    name: 森杏奈
  - image: http://pics.dmm.com/digital/akb48/list/morikawa_ayaka.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=164/ch_navi=akb48member/sort=date/
    name: 森川彩香
  - image: http://pics.dmm.com/digital/akb48/list/yamauti_suzuran.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=135/ch_navi=akb48member/sort=date/
    name: 山内鈴蘭
  - image: http://pics.dmm.com/digital/akb48/list/yamaguti_nau.jpg
    link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=165/ch_navi=akb48member/sort=date/
    name: 山口菜有

Mashup Award6で小飼弾さんの 404 API Not Found賞を授賞しました

codetype.org

先日作ったPythonのFlask製アプリ、オンラインコード共有ツール codetype.orgが審査員特別賞を授賞しました。
授賞作品の中では一番地味だと言えるサービスです。
TwitterのOAuthを利用してログインをし、プログラミングのコードを貼り付けてオンライン上で実行結果がわかる・共有できるというものです。

もともと9月に女性エンジニアとしてMashup Caravan Girls Talkでプレゼンをさせて頂いたのですが
そのデモアプリとして動く物を1週間くらいでざっくり作ったのがきっかけです。

その当時は弾さんのAPIは提供企業として正式なものではありませんでした。
それがプレゼンから1ヶ月後くらいの10月半ばに、弾さんのAPIが特別審査員として正式に提供することになったようです。
真面目に授賞できるだなんて思っていなくて、私自身でもすごくビックリしていますし、嬉しいのと恥ずかしいのが入り交じっている感覚です。


弾さんから弾さんの著書 & 弾言に弾さんのサインも頂きました。あリがとうございます!!


授賞式の様子。恐縮しすぎて笑顔がおかしい。
ma6
source: http://weekly.ascii.jp/elem/000/000/029/29236/


システム的にも雑な部分がたくさんあります。
さくらの500円サーバーでマルチドメインとして動いているため、全然費用がかかっていないです。
弾さんのllevalのAPIから返ってくるレスポンスをごそっとjson形式のままDBに保存しています。

制作/開発時間

今回のサービスは学習込みで全部で30時間くらいかけて作りました。

  • ざっくりとしたサンプルベースの雛形5時間
  • OAuth対応、lleval対応、ユーザ登録、syntax highlight対応、 10時間
  • テンプレート化 10時間
  • fork機能、レイアウト微調整、Twitterにpost機能、バナー作成、その他細かいところ 5時間

開発・公開環境

  • さくらの共有サーバー (月500円のライトプラン)
  • Python 2.6.2
  • Flask 0.6
  • Flask OAuth 0.9
  • SQLite 3.6.14.2

codetypeの主な機能

  • Twitterのアカウントでログインができる
  • コードが貼りつけて公開できる
  • 実行した結果がオンライン上で確認できる
  • http://codetype.org/aNfJJREpTu などオリジナルのURLでシェアできる
  • コメントができる
  • 既存のコードをベースにフォークできる
  • ユーザ名は非公開

あたらしいことにチャレンジしたこと

  1. Pythonでなにか作りたい
  2. OAuthの仕組みを利用してなにか作りたい
  3. 個人ではじめてきちんとサービスとして公開した
  4. コンテスト的なものに初めて応募

コードも晒します

create_table.sql

CREATE TABLE users (
  id integer primary key autoincrement,
  twitter_id int not null,
  name string not null,
  oauth_token string not null,
  oauth_secret string not null,
  date string null
);

CREATE TABLE entries (
  id integer primary key autoincrement,
  title string null,
  text string not null,
  author string not null,
  hash string not null,
  tag string null,
  lang string null,
  date string null,
  dan string null
);

CREATE TABLE comments (
  id integer primary key autoincrement,
  text string not null,
  entry_id int null,
  user_id int null,
  date string null
);


~/src/flaskr/flaskr.py

# -*- coding: utf-8 -*-
"""
    Flaskr
    ~~~~~~

    A microblog example application written as Flask tutorial with
    Flask and sqlite3.

    :copyright: (c) 2010 by Armin Ronacher.
    :license: BSD, see LICENSE for more details.
"""
from __future__ import with_statement
import sqlite3
from contextlib import closing
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash, escape
from flaskext.oauth import OAuth
from markdown import markdown
import random
import string
import datetime
import sys
import os
from pprint import pprint
import urllib
from flask import json

oauth = OAuth()
twitter = oauth.remote_app('twitter',
                           base_url='http://api.twitter.com/1/',
                           request_token_url='http://api.twitter.com/oauth/request_token',
                           access_token_url='http://api.twitter.com/oauth/access_token',
                           authorize_url='http://api.twitter.com/oauth/authorize',
                           consumer_key='[consumer_key]',
                           consumer_secret='[consumer_secret]'
)

# configuration
DATABASE = '/home/acotie/src/flaskr/flaskr.db'
DEBUG = True
SECRET_KEY = '[SECRET_KEY]'
USERNAME = ''
PASSWORD = ''

# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('FLASKR_SETTINGS', silent=True)


default_lang = {
'perl': 'pl',
'perl6': 'p6',
'awk': 'awk',
'basic': 'bas',
'brainfuck': 'bf',
'c': 'c',
'elisp': 'el',
'lisp': 'lsp',
'scheme': 'scm',
'haskell': 'hs',
'io': 'io',
'javascript': 'js',
'lua': 'lua',
'm4': 'm4',
'ocaml': 'ml',
'php': 'php',
'python': 'py',
'python3': 'py3',
'ruby': 'rb',
'ruby19': 'rb19',
'postscript': 'ps',
'tcl': 'tcl',
}

def query_db(query, args=(), one=False):
    cur = g.db.execute(query, args)
    rv = [dict((cur.description[idx][0], value)
               for idx, value in enumerate(row)) for row in cur.fetchall()]
    return (rv[0] if rv else None) if one else rv

def random_str(self, length = 10):
    ret = ""
    for i in range(length):
        ret += random.choice(string.ascii_letters)
    return ret


def connect_db():
    """Returns a new connection to the database."""
    return sqlite3.connect(app.config['DATABASE'])


def init_db():
    """Creates the database tables."""
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read())
        db.commit()

@app.before_request
def before_request():
    """Make sure we are connected to the database each request."""
    g.db = connect_db()
    g.user = None
    if 'user_id' in session:
        g.user = query_db('select * from users where twitter_id = ?',
                          [session['user_id']], one=True)

@app.after_request
def after_request(response):
    """Closes the database again at the end of the request."""
    g.db.close()
    return response

@twitter.tokengetter
def get_twitter_token():
    #return session.get('twitter_token')
    user = g.user
    if user is not None:
        return user.oauth_token, user.oauth_secret


@app.route('/')
def show_entries():
    cur = g.db.execute('select title, text, author, tag, lang, hash, date from entries order by id desc limit 10')
    entries = [dict(title=row[0], text=row[1], author=row[2], tag=row[3], lang=row[4], hash=row[5], date=row[6]) 
            for row in cur.fetchall()]
    return render_template('index.html', entries=entries, default_lang=default_lang, )


@app.route('/recent/<int:page>')
def show_entries_pager(page):
    if page is None:
        page = 1
    of_value = 1
    of_value = page * 10
    print of_value
    entries = query_db('select title, text, author, tag, lang, hash, date from entries order by id desc LIMIT 10 OFFSET ?', [of_value], one=False)
    if entries is None:
        print 'No such entry'
        abort(404)
    return render_template('recent.html', entries=entries, default_lang=default_lang, )


@app.route('/<hash>')
def entry(hash):
    dan = ''
    entry = query_db('select * from entries where hash = ?', [hash], one=True)
    if entry is None:
        print 'No such entry'
        abort(404)

    comment = query_db('select * from comments where entry_id = ?', [entry['id']], one=False)
    if comment is None:
        print 'No such comment'

    if entry['dan']:
        dan = json.loads( entry['dan'] )
        print dan

    return render_template('entry.html', entry=entry, comment=comment, dan=dan, default_lang=default_lang, )


@app.route('/<hash>/fork')
def entry_fork(hash):
    dan = ''
    entry = query_db('select * from entries where hash = ?', [hash], one=True)
    if entry is None:
        print 'No such entry'
        abort(404)

    comment = query_db('select * from comments where entry_id = ?', [entry['id']], one=False)
    if comment is None:
        print 'No such comment'

    if entry['dan']:
        dan = json.loads( entry['dan'] )
        print dan

    return render_template('entry_fork.html', entry=entry, comment=comment, dan=dan, default_lang=default_lang)


@app.route('/tag/<tag>')
def entry_tag(tag):
    entry = query_db('select * from entries where tag = ?',
                [tag], one=False)
    if entry is None:
        print 'No such entry'
        abort(404)
    return render_template('entry_tag.html', entry=entry, tags=tag )


@app.route('/about')
def about_entry():
    return render_template('about.html')


@app.route('/blog')
def blog_entry():
    return render_template('blog.html')

@app.route('/contact')
def contact_entry():
    return render_template('contact.html')


@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)

    if not g.user:
        abort(401)

    name = session.get('username',None)
    hash = random_str(20)

    # dan the api
    code = request.form['text']
    lang = request.form['lang'] 
    url = 'http://api.dan.co.jp/lleval.cgi'
    params = urllib.urlencode({'c':'', 's':code, 'l':lang})
    f = urllib.urlopen(url + '?' + params) # paramsはc=&s=code&l=lang
    dan = f.read()

    g.db.execute("insert into entries (title, text, author, tag, lang, hash, date, dan) values (?, ?, ?, ?, ?, ?, ?, ?)",
            [request.form['title'], request.form['text'], name, request.form['tag'], request.form['lang'], hash, datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"), dan ])
    g.db.commit()
 
    flash('New entry was successfully posted')
    return redirect( url_for('entry', hash=hash) )


@app.route('/add_c/<hash>', methods=['POST'])
def add_comment(hash):
    if not session.get('logged_in'):
        abort(401)

    if not g.user:
        abort(401)

    entry = query_db('select * from entries where hash = ?',
                [hash], one=True)
    if entry is None:
        print 'No such entry'
        abort(404)

    g.db.execute("insert into comments (text, entry_id, user_id, date) values (?, ?, ?, ?)",
            [request.form['comment'], entry['id'], g.user['id'], datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")])
    g.db.commit()
    flash('New entry was successfully posted')
    return redirect( url_for('entry', hash=hash) )



@app.route('/login', methods=['GET', 'POST'])
def login():
    if g.user:
        print "OK"
        session['logged_in'] = True
        session['user_id']  = g.user['twitter_id']
        session['username'] = g.user['name']
        flash('You were logged in')
        return redirect(url_for('show_entries'))
    else:
        print "NO"
        print g.user
        print(url_for("oauth_authorized"))
        return twitter.authorize(callback=url_for("oauth_authorized"))


@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    session.pop('username', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))


@app.route('/oauth-authorized')
@twitter.authorized_handler
def oauth_authorized(resp):
    next_url = url_for('show_entries')
    if resp is None:
        flash(u'You denied the request to sign in.')
        return redirect(next_url)
    else: #success
        user = g.db.execute('select name from users where twitter_id = ?', [int(resp['user_id'])]).fetchone()

        if user is None:
            g.db.execute("insert into users (twitter_id, name, oauth_token, oauth_secret, date) values (?, ?, ?, ?, ?)",
                         [int(resp['user_id']), resp['screen_name'], resp['oauth_token'], resp['oauth_token_secret'], datetime.datetime.now()])
            g.db.commit()

        session['twitter_token'] = (
            resp['oauth_token'],
            resp['oauth_token_secret']
        )
            
        session['logged_in'] = True
        session['username']  = resp['screen_name']
        session['user_id']   = int(resp['user_id'])

        flash(resp['screen_name'] + ' were signed in')
        return redirect(next_url)


if __name__ == '__main__':
    app.run(host='codetype.org', port=5001)


さくらのマルチドメインの公開ディレクトリの~/www/codetype/以下に.htaccessを置きます。
~/www/codetype/.htaccess

#AddHandler cgi-script-debug .cgi
DirectoryIndex index.html .ht

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^/
RewriteRule ^(.*)$ http://codetype.org:5001/$1 [L,P]

さくらのサーバーは定期的にpythonperlなど立ち上げっぱなしだとサーバー側のプロセスをkillしてしまう為
プロセスが落ちたら立ち上げるように無限ループさせるスクリプトを書いています。
問題はシェルのプロセス自体やscreenなどもkillされる恐れもあります。必要であれば別途、死活監視用スクリプトが必要かと思います。

~/codetype.sh

#!/usr/local/bin/bash

while true
do
    echo 'starting Flaskr server...'
    python ~/src/flaskr/flaskr.py
done

構造やレイアウトなどはこちらにまとめています。
https://gist.github.com/730666

謝辞

今回アプリを作る上で参考にさせて頂いたサイト

以下の4サイトにお世話になりました。本当にありがとうございます!!

  1. Welcome | Flask (A Python Microframework)*1
  2. https://github.com/mitsuhiko/flask/blob/master/examples/minitwit/minitwit.py*2
  3. Bitbucket | The Git solution for professional teams*3
  4. Flaskrの認証をOAuthで*4
MA運営事務局の方々、弾さん、知り合いの方々

今回のきっかけを作っていただいた、プレゼンしませんか?と声を掛けてくださったMashup Award運営事務局の山本さん、山田さん、
仕事終わってからカフェなどで資料thonに付き合ってくださった方々、温かい声を掛けてくださった方々。
本当に感謝の気持ちでいっぱいです。心からお礼を申し上げます。
授賞式でしか味わえないような感動や刺激を沢山受けました。

MA7への抱負

また一から新しいことを勉強しようと思います。
そして個人でも仕事でも、もっとスピード感のある開発ができるように努力します。
できればデザイナーさんと一緒にサービス作って、もっとデザインにもシステム的にも凝ったサービスを作りたいと思います。
あとは個人的に勉強してるFlex/Air系のアプリでガジェット、デスクトップアプリや、ゆるくiPhoneアプリ作りたいです!
なんかよくわからないけどデザインとかディレクションとかしてあげてもいいよ!っていう方はぜひ声掛けてください。

*1:わかりやすい本家サイト

*2:作者の方のコード。Flaskrだけでなく、OAuthのログインまわりも作者のexampleアプリが参考になりました。WAF本体のコード読んでても本当に勉強になります。

*3:id:a2cさん、id:ymotongpooさんによる日本語翻訳ドキュメント。毎日ページ開いて読んでました :D

*4:超貴重な日本語でのサンプル。全体的な流れも超参考になりました