プログラマにおすすめする書籍・その3

今回は以下で投票した本を紹介します。

以前の記事はこちら

擬人化でまなぼ! ネットワークのしくみ もしも、プロトコルが人格を持ったなら…!?

いきなりインパクトがデカいですが(笑)、まずは以下読んでください。
単純にWebサイトで動画や画像を見るのも、裏ではこんなことが行われているということを順を追って理解できます。
私自身がネットワーク関連に苦手意識があり、少しでもとっつきやすい書籍をということで購入しましたが、
数時間で読み切ってしまうほど読みやすいものでした。
IT業界の方はもちろんですが、日常的にパソコンを使う方でも読みやすいと思います。

何よりキャラクターがかわいいのでそれもモチベーションになります(笑)。

現場で困らない!ITエンジニアのための英語リーディング

エンジニアとして仕事をしていると、必ず英語に触れます。
英語に苦手意識がある方は少なからずいると思いますが、この書籍はその中でも「ITで使われる用語や表現」の読み解き方をわかりやすく説明してくれています。
ネットや新聞などの記事、OSSのドキュメントなどの例文が多く、それに対する解説もとても丁寧でした。
回し者感が出そうですが、「OSSへ貢献したい」という思いを大きく後押ししてくれました。

自然言語処理の基本と技術 仕組みが見えるゼロからわかる

先に書いた英語について、わからない単語があったとき、私はGoogle翻訳を使うことが多いです。
そこで出てくるのがこの「自然言語処理」です。
日本語は特に表現の幅が大きく、同じ単語でも文脈に大きく左右されます。
上記を知っていると、なんとなく「翻訳するのは難しいんやろうな」とわかりますが、この本を読むことで解析する手順や手法をより理解することができます。
この手の分野は難しい数式が多く登場しますが、そういった内容を一切使っていない点が個人的に嬉しかったです。
さらに高度な内容は専門書を読むことになりますが、概要を理解するにはとても良い書籍でした。

プログラマが知るべき97のこと

プログラマには有名な書籍なので今更ですが。
具体的なコードというよりは、見方や考え方についての説明が多いです。
97とありますが、著名日本人プログラマが書いた10本がプラスされています。
コーディング・ツール・データ・テスト・デプロイ・見積もり・OSSへの貢献などなど、プログラマである以上絶対に経験するであろう内容へのアドバイスが盛りだくさんです。
技術が進歩しても必要になるであろう見方・考え方がたくさん詰まっていますので、読んだことのないプログラマの方は是非ご一読ください。

冒頭の投票では5冊までということだったので、これら4冊と以前紹介した「60分でわかる!機械学習&ディープラーニング超入門」を投票しました。
皆さんもお勧めの本があればぜひ教えてください。

Pipenvを使ってPython開発を快適に

最近、Pythonでコードを書く機会が増えてきました。

  • インデント強制
  • 標準ライブラリで出来ることが多い
  • Python3からは仮想環境であるvenvが標準で利用できる

などの理由で主に使っています。
ただ、Webアプリケーションなどでライブラリが必要な場面に遭遇すると、easy_installpipなどのツールを利用してパッケージを取得することがあります。
今回はこのパッケージマネージャについてです。

他言語のパッケージマネージャとの比較

メジャーな言語には、たいてい強力なパッケージ管理ツールがあります。
以下は有名ですね。

  • composer(PHP)
  • RubyGems(Ruby)
  • cpan(Perl)
  • npm、yarn(JavaScript)
  • Maven(Java)
  • NuGet(C#)

依存関係の解決だけでなく、設定ファイルを書くことで開発・本番での場合分けや
マルチプラットフォームでの環境の再現も容易に行うことができるものもあります。

ただ、先述したeasy_installpipでは、ここまで高度なことができません。
そこで、以下に続きます。

requirements.txt という選択肢

私は最近までこのやり方を使っていました。
Python3でvenvを使うやり方だと以下のような手順です。

ファイル名は何でも良いですが、一般的にこの名前が利用されているようです。
書き出したファイルには以下のように、ライブラリ名==インストールされたバージョンというフォーマットで記録されます。

インストール時は、読み込むrequirements.txtを指定してコマンドを実行します。

問題点

ざっと思いつくだけでも以下があります。

  • 環境ごとにrequirements.txtを分ける必要がある
  • ライブラリに変更があるたびにファイル再生成する手間がかかる
  • そもそもバージョンアップの手順が面倒(仮想環境でインストール→ファイル再作成)

Pipenv という選択肢

そこで登場するのがPipenvです。
パッケージ自体は1年前ぐらいからあったようです。
未検証ですが、ドキュメントを読む限りPython2でも利用できるようです(可能な限りPython3を使ってとのことですが)。

Pipenv: 人間のためのPython開発ワークフロー

詳細は上記をご覧いただくとして、ざっと使い方を。

requirements.txtがすでに存在するプロジェクトの場合、デフォルトで解析してくれます。
(ファイル名が異なる場合でも、-rオプションを使うことで読み込み可能です)
コマンド実行後、プロジェクトフォルダに以下2ファイルが生成されます。

  • Pipfile (toml形式)
  • Pipfile.lock (JSON形式)

他言語のパッケージマネージャを使ったことがある方は名前からだいたい想像がつくと思います。
Pipfileが設定ファイル、Pipfile.lockがインストールされたライブラリの情報です。
また、このタイミングで仮想環境も自動で作成してくれます。

Pipfileは以下のようなフォーマットです。

ただ、requirements.txtからのインポートだと、上記のようにバージョンが完全に固定されてしまっています。
なので、必要に応じてバージョンを変更します。

パッケージを追加でインストールする際には以下のようにします。

仮想環境で対象プログラムを実行するようなケースでも、Pipfileがあるディレクトリでpipenv runを利用することで実行可能です。

都度「あれ?仮想環境入ってたっけ…?」「今入っている仮想環境はどのプロジェクトや?」とならないのでとても便利です。
ちなみに、デフォルトだと仮想環境はホームディレクトリの.virtualenvsディレクトリ内に生成されるようです。
これをプロジェクト直下(=Pipfileと同じディレクトリ)にしたい場合、以下のように環境変数を定義してインストールしてください。

まとめ

複数人での開発だと、こういった機能は本当にありがたいですね。
待ち望んでいた機能なので、今後何らかの形で貢献できれば良いなと思っています。

2017年を振り返る

2017年もあと数十分で終わります。
皆さんの今年の目標は何で、どの程度達成できましたか。

「年を忘れる会」というものもありますが、私は回顧癖があるので(笑)、
今年の自分を振り返ってみようと思います。

アジェンダ

  • 今年の目標と達成度
  • 楽しかったこと
  • 辛かったこと
  • 来年の目標
  • まとめ

今年の目標と達成度

今年の目標

  • フリーランスとして働き、成果を上げる
  • 常駐以外の仕事をする

達成度

1つ目は自信をもって「100%」だったかなと。
幸い、独立した月(=1月)から現場も決まっており、そこが現在も続いているため、
仕事が無いというタイミングがありませんでした。
また、有難いことにその現場で評価いただけており、継続に加えて単価UPもありました。

2つ目は20%といったところでしょうか。
独立して副業ができるようになり、広告収入を得られるようになりましたが、
まだ仕事と呼べるほどのものではないので、ひとまずこの達成度にしています。
このあたりは「辛かったこと」にも書いています。

楽しかったこと

とにかく自由だったことですかね。
常駐先では無駄な残業をせず、帰宅後は「別の手段で稼ぐ」ことに集中できるというのが
とにかく楽しかったです。
もちろん決められた労働時間はありますが、その範囲であれば平日も比較的休みやすいので、
そこで事務処理や別の仕事をできました。
また、社内政治とか考課とかを気にしなくて良いのもすごく気が楽でした。

辛かったこと

常駐しているが故に、個人の仕事がなかなか請けられませんでした。
提案しても、「平日の日中でお願いできる方を優先しています」といった返答をいただくことが多かったのです。
ただ、もう少し間口を広げれば請けられる仕事があるという感覚はあるので、このあたりを見極めるのが今後の課題かと思います。

来年の目標

今年の目標が100%ということだったので、来年はもう少し貪欲にいこうと思います。
以下3点です。

  • 月1本以上のOSSへのPR
  • 副業の収入(案件数・広告など)を増やす
  • 健康診断の値をすべて正常範囲におさめる

まず1つ目。
以前の記事にも書いた通り、今年はCakePHPのOSSへPRを出す機会がありました。
ドキュメント側、CakePHPのライブラリであるBakeにも修正PRを出せました。
PRを出すということは、「そのツールについてよく理解する」「修正した経緯・内容を正しく相手に伝える」「英語を学ぶ」といった、仕事でも必要な技術を身に着けられます。
来年はもっと頻度を上げて、自分が使っているライブラリやフレームワークをより良くすることに貢献していきたいと思います。

2つ目は「辛かったこと」に書いた通りです。

3つ目については、就職してからずっと課題だったことです。
研修後、寮生活から実家に戻って飲み歩いているうちに、1年で10kg太ってしまいました。
その結果、新卒2年目から太りすぎ+脂質異常で健康診断に引っかかるようになるという悲しい展開に。
そこから数年、食べる量や種類に注意していた結果、ようやく昨年~今年で体重が10kg減りました。
今年の健康診断では体重も標準範囲内にすることができ、200を超えたLDLが30以上減っていたんです。
来年はこのLDLの値を標準範囲内にして、1つも異常が無い状態を目指します。

まとめ

来年は30歳になります。
エンジニアとしても、人としても1つのターニングポイントかと思っています。
目標を達成することも大切ですが、「無理せずマイペースに」を大事に来年も頑張ります。
それでは皆さんも良いお年をお迎えください。

Djangoを使ってデータベースを持たないAPI認証を行う

この記事は Django Advent Calendar 2017 20日目の記事です。

先日、満を持してバージョン2.0がリリースされました。
ただ、今回は新しい機能の紹介ではなく、1.xでも実装可能な「API認証」について書きます。

アジェンダ

  • この記事を書こうと思ったきっかけ
  • API認証の実装
  • まとめ

この記事を書こうと思ったきっかけ

以前、こちらにも書いたのですが、私は自分がつくったシステムのログイン~ログアウト処理に、これまた自分で作ったGo(Gin)のAPIを利用しています。
※最近はソーシャルログインなど外部サービスとの連携が楽にできるのですが、自分の勉強のためにこのようにしています。

で、以前ASP.NETでつくったレシピ管理ツールを今年Djangoに移行しまして、そこでもAPI認証をすることにしました。
CakePHP3やLaravelでは比較的簡単にできたのですが、Djangoは少し癖があったので、備忘も兼ねて書き残しておこうと思ったのがきっかけです。

API認証の実装

手順は大きく4つです。

  1. 認証用ユーザモデルの作成
  2. 認証ミドルウェアの作成
  3. 認証バックエンドの作成
  4. 設定ファイルの変更

通常、Djangoではマイグレーション時にauth_userテーブルが生成され、そこでユーザ情報を管理します。
グループやバーミッションなど細かい設定もできるのですが、今回はそれらは使用しません。

カスタムユーザモデルの作成

AbstratUserを継承した、独自ユーザーモデルを作成します。

セッションにsigned_cookieを利用しているためJSON変換処理を用意しています。

カスタム認証ミドルウェアの作成

django.contrib.auth.middleware.AuthenticationMiddlewareを参考に、以下のようなカスタムミドルウェアを作成します。

認証バックエンドの作成

Django標準の認証バックエンドとしてModelBackend(データベースを利用)やRemoteUserBackend(ヘッダのユーザー名を利用)が用意されていますが、
今回はAPI認証のため独自のバックエンドファイルを用意します。

設定ファイルの変更

最後に、settings.pyを修正します。

以上で実装完了です。

まとめ

Djangoには標準で管理画面がついてきますが、こちらはDBありきの実装なので、認証・認可をAPIで乗り切ろうと思うとかなり大変です。
標準の管理画面を利用する場合は嫌でもデータベースを使うことになるので、その場合は素直にテーブル管理しましょう。

一応、上記コード上にもコメントで記載していますが、結局のところ認証ユーザとauth_userテーブルを一旦同期させることになりそうです。

主な手順

  • ApiUserauth_userとして利用
  • API認証時、auth_userにレコードがなければ追加
  • リレーションの維持にはその値を利用

この実装を通して、Djangoが認証をどのように行っているかを学べたのは良い経験でした。
まだまだ知らない機能が多いので、これからも機能追加しつつ楽しんで開発出来たらと思います。

一部記事用に修正しましたが、今回利用したソースコードの元はこちらにありますので、良ければご覧ください。

CakePHPバリデーションメッセージにフィールド名を動的に表示させる

※2017/12/21追記
日付フォーマット処理にミスがあったため修正しました。

この記事は CakePHP Advent Calendar 2017 20日目の記事です。

皆さん、CakePHP使ってますか。
私はPHPで初めて触ったフレームワークということもあり、かなり思い入れがあります。
そんなCakePHPのバリデーションについて紹介します。

アジェンダ

  • この記事を書こうと思ったきっかけ
  • 最終的なゴール
  • カスタムバリデーションの実装
  • まとめ

この記事を書こうと思ったきっかけ

そもそもCakePHPを使うきっかけが、「就職してずっと使ってきたJava以外の言語を本格的に学びたい」という思いからでした。
仕事では簡単なツールにPHPを使っていたこともあり、CakePHP導入を決めました。

そして、実装を進めていたとき、

「バリデーションにフィールド名が出ないな…」

と思ったことがきっかけです。

最終的なゴール

以下のようなメッセージを出力します。

  • 「ID」は必須入力です。
  • 「名前」は空欄にできません。
  • 「年」は数値のみで入力してください。
  • 「生年月日」は「y/m/d」形式で入力してください。

上記は、デフォルトの翻訳ファイル(./bin/cake i18nで作成されたもの)を利用すると、以下のように出力されます。

  • このフィールドは必須です
  • このフィールドは空欄にできません
  • 与えられた値は無効です
  • 与えられた値は無効です

Oh…。

バリデーション機構の拡張

モデル・翻訳ファイルの定義

モデル・翻訳ファイルは以下のように定義します。
今回、翻訳ファイルはバリデーション用に切り出しました。

カスタムバリデータクラス追加

基本的な方針として、requiredempty以外のバリデーションルールはValidator::add()メソッドを利用するので、それを継承して調整します。
コードを見ていただければわかるとおり、requiredemptyは別途実装しています。
※もう少し良い実装方法があるはずなので、引き続き検討します…。

利用するモデル・フォームに定義

作成したバリデーションを利用するよう、TableおよびFormで定義します。

  • Table

  • Form

以上で実装完了です。

まとめ

ErrorHelperなどは、規約に則っていれば特定ディレクトリにファイルを生成するだけで利用できます。
今回のバリデーションはこれができず、少し手間に感じました。
ただ、フレームワークのコードはわかりやすく、特に問題なく理解できたので、
自分でカスタマイズするのもそこまで難しくはありませんでした。

CakePHPは個人開発で一番使っているフレームワークで、先日出した初PRも無事マージされました。

これからも内容を理解しながらぼちぼち貢献していけたらなと思っています。
それでは、皆さんも良いCakePHPライフを!

一部記事用に修正しましたが、今回利用したソースコードの元はこちらにありますので、良ければご覧ください。

文系エンジニアが目指したきっかけを振り返ってみる

この記事は文系プログラマ Advent Calendar 2017 18日目の記事です。

アジェンダ

  • エンジニアを目指したきっかけ
  • 文系でエンジニアを目指す人へ
  • 自分の経験から、新人・若手に伝えたいこと
  • 最近やっていること
  • まとめ

エンジニアを目指したきっかけ

合同企業説明会(ドームとかでやるアレです)で気になったためです。

高校は普通科、大学は心理学を専攻していたので、正直プログラマがどういうことをする人かは全く知りませんでした。
また、まわりに影響されてようやく就職活動を始めた状況で、特に何かやりたいことがあったわけでもありませんでした。

そんな中、いくつかのブースをまわっていると「IT」というワードが目に留まりました。

「普段使っている改札とか自動販売機の内部ってどうやって動いてるんやろ」

と気になり、IT企業のブースをいくつか回ってみることに。
結果、「興味」が「目標」に変わったというわけです。
今になって思えば、以下のような要因も影響していたかもしれませんね。

  • 中学2年生からWebサイトの更新を続けていたこともあり、興味を持ちやすかった
  • コンピュータを使った大学の講義が面白かった(この講義はExcelやWordを駆使するものがほとんどでしたが)

IT業界を目指すにあたり、自分に何も情報が無い状態だったので、とりあえず基礎的なことを学ぼうと中古の参考書を購入しました。
自分のノートPC上にCとJavaの実行環境をつくって、コンソールに文字を出力する日々が続きました。
月並みな表現ですが、「自分がつくったものが動く」というのがとても嬉しかったですね。

文系でエンジニアを目指す人へ

エンジニアには向き・不向きがある。
誰でもなれるとか謳ってる会社には気をつけろ!!

これですね。
私の場合、そういった謳い文句に誘われるがまま新卒で入った会社がとにかく合わなかったんです。

  • 体育会系(飲み会の頻度や営業ノリ)
  • 技術(者)が大切にされていない(PCスペックがしょぼい、技術を極めるキャリアが無い、営業色が強すぎる)
  • 残業しすぎ(一定年数以降はみなし残業になるが定時後の集まりが多すぎる。しかも22時ぐらいから飲みに行ったりする)

入る会社はしっかり選んでくださいってことですね(当たり前ですが)。

あと、若いうちは資格の勉強をしたほうが良いと思います。
取れる・取れないはあまり問題ではなく、資格取得に向けて幅広く知識を仕入れることは絶対に無駄にならないです。
大学や大学院でがっつりコードを書いてきた人には、スタートラインではどうやっても勝てないので、コツコツ積み重ねていくことが一番です。
とにかくコードを書いてみる(もしくは何かサービスを作ってみる)。
最近はインターネットでスキルチェックできるサービスも多いので、是非有効活用してください。

自分の経験から、新人・若手に伝えたいこと

以下のようなことができると一目置かれるかなと思っています。

開発視点

  • 新規開発では中心メンバーになる(アーキテクチャ選定に関われると尚良い)
  • 保守・運用では既存のコードにある「背景・経緯」を考える

業務視点

  • 顧客の業務(登場人物・利用部門やフローなど)を抑える
  • 利用する立場になって「本当に望むものは何なのか」を考える

今やっていること

ここは色々書くより最近の記事をリンクしておきます。
興味のある方はご覧ください。

リポジトリ

ブログ

Twitterつぶやき

まとめ

文系・理系関係なく、出来る奴は出来るし、向いているやつはとことん向いている

色々書きましたが、結局上記の通りかと思います。
というと身も蓋もないので(笑)、もう少し思うところを。

私の場合、興味を持って「まずはやってみた」ことが、今でもエンジニアを続けられている原点だったのかなと思います。
何をするにも、よく知らないうちから評価できるはずがありません。
周りの意見はほどほどに、「まずはやってみる」ということが重要ですね。
その結果、辛くて仕方ないのであれば「向いていない」と割り切るのも大切です。
「まずはやってみる」→「今は理解できないけど続けてみよう」→「楽しくなってきた」というスルメ状態になればしめたもの。
これを読んでいただいた方がエンジニアになり、共に働けることを楽しみにしています。

CakePHPでステータスコード204がOK扱いにならなかった話

今年のQiita Advent Calendarに投稿予定です(CakePHPとDjango)。
いずれも12/20ですので、興味があればご覧ください。

CakePHP
Django

さて、今回はCakePHPに関する記事です。
結論から言うと、PRがマージされましたというお話です。

背景

私は自作アプリのログイン・ログアウトにGoの外部API(これも自作したやつです)を使っており、
それぞれ以下のように処理しています。

ログイン

  1. アプリ:ユーザ・パスワードで認証APIをコール(POSTメソッド)
  2. API:処理成功時、ステータスコード200とアクセストークン返却
  3. アプリ:アクセストークンを利用してユーザ取得APIをコール(GETメソッド)
  4. API:処理成功時、ステータスコード200とユーザ情報を返却
  5. アプリ:取得したユーザ情報をセッションに格納してログイン成功

ログアウト

  1. アプリ:アクセストークンを利用して認証解除APIをコール(DELETEメソッド)
  2. API:処理成功時、ステータスコード204を返却

ある時、CakePHP3を使ったアプリで、正常にログアウトした場合でもエラーログが出ていることに気づきました。

「エラーのくせに詳細が何も出力されないだと…」

という衝撃を隠しきれませんでしたが(笑)、一旦落ち着いて発生箇所を調査することに。

原因

コメントに書いた通りなのですが、上記コードをもとに説明します。

  • ログアウト時の処理2でステータスコード204が返ってくる(5行目)
  • isOk()の対象でないためif文に入らない(12行目)
  • レスポンスボディもないため、CakePHP側16行目Log::error()で出力する$bodyも空(17行目)

という流れで、何も情報が無いエラーログが出力されてしまっていたということです。
これだけなら「あえて204をOKしてないのかな」とも思えたのですが。

CakePHP3側の基底テストケースではまさかのOK対象内。

修正~PR

CakePHP側のコード修正・テストコードの修正および実施を行い、
それらのPRを出したところ、5時間ほどで無事マージされました。

ドキュメントは以前PRがマージされたのですが、コード側は初めてです。
「PRは内容に問題なければサクッとマージしてもらえるんだな」ということがわかりました。

とはいえ、IssueやPR作成時の説明にもあるように、注意する点もいくつかありますので、詳細は以下をご覧ください。
CakePHP コミュニティセンター

それでは、良いCakePHPライフを。

Gitでよく使うコマンドをメモしておく

バージョン管理システムであるGit。
便利なGUIツールはたくさんありますが、私はもっぱらコマンド派です。

今回はそんなGitで私がよく使うコマンドについて、備忘のために書いておきます。

リモート追加

ブランチをチェックアウト

リモートからブランチを取得

ブランチをマージ

git pullでfetch~mergeまでやってくれますが、私は上記をそれぞれ使っています。

変更をインデックスする

変更をなかったことにする

コミットする

コミットを取り消す

HEAD^は必要に応じて変更します(3つ前ならHEAD^^^など)。
この場合、push済みの場合は履歴を書き換えているので-fオプションが必要ですが、他の人に影響が出るので共用ブランチではやらないほうが良いです。

1つ前のコミットメッセージ変更

ブランチへpush

はオプションです。
-uオプションを付与することでデフォルトを設定できますが、実際はブランチをSwitchしながら色々やることが多いので、私は必ずどちらも打つようにしています。

ローカルの変更を一時退避

スタックになっているので、stashした数だけpopできます。

ちなみに、rebaserevertはあまり使いません。
ざっくり言うと、rebaseは指定のコミットまで戻って履歴操作(複数のコミットをまとめるとかコメント修正もこれで出来ます)、revertはコミットを打ち消すコミットです。

私は特によく使うコマンドをまとめたものを以下のようにエイリアスにしています。

このコマンドでは以下を実施しています。

  1. ローカルの変更を退避
  2. リモートにあるブランチと同名のブランチをローカルにチェックアウト
  3. リモートの変更をfetchしてチェックアウトしたブランチにマージ
  4. 退避していた変更を戻す

実際の作業時には、ローカルのブランチを別名にしたいとか、一気にやるとmergeのタイミングでconflictが起きた場合にpopを忘れそうといったケースが起こると思います。
上記はあくまでも参考ということで。

AWSで心がぴょんぴょんするんじゃぁ^~

皆さん、パブリッククラウド使ってますか。
無料利用枠があるサービスもあるので、個人で使っているという方も多いのではないでしょうか。

かくいう私もその1人です。
今回はその中から、Amazon Web Services(AWS)を利用したサーバーレスアプリケーションの作成について紹介します。

今回利用したサービス

  • API Gateway
  • Lambda
  • DynamoDB

作成したもの

処理の流れ

  1. API Gatewayで作成したエンドポイントをクライアントがコール
  2. API GatewayがLamdba関数を実行
  3. Lamdba関数内でDynamoDBのデータを取得し、呼び出し元(API Gateway)へ返却
  4. API Gatewayがクライアントへデータを返却

手順

アカウント登録

何をするにもアカウント登録しなければ始まりません。
手順はこちらをご覧ください。

登録後12ヶ月の無料利用枠があり、この間はほとんどのサービスが無料で利用できます。
にもかかわらずクレジットカードを登録するというのはやっぱり気になるところではありますが、
従量課金という仕組み上(12ヶ月中であっても有料サービスを使えば課金が発生するため)やむを得ないのでしょうね。

なお、今回利用するリージョンはいずれも「ap-northeast-1」です。

IAM(Identity and Access Management)ユーザ登録

IAMは、ユーザに適切な権限を割り振って管理するための仕組みです。
今回は必須ではありませんが、登録時のルートアカウントを使い続けるのはセキュリティ的にお勧めされていないので、AWSを利用するなら作成しておいたほうが良いです(IAM自体は12ヶ月の無料利用枠後も無料で利用できます)。
「サービス」→「IAM」→「ユーザー」→「ユーザーの追加」で作成できます。
※ユーザーの作成およびポリシーの設定については本筋ではないので省略します。

テーブル作成(DynamoDB)

DynamoDBは、最近何かと話題のNoSQLデータベースです。
管理コンソールより「DynamoDB」→「テーブルの作成」でテーブルを作成します。
今回は以下のように定義しました。

  • テーブル名:categories
  • プライマリパーティションキー:category(文字列)
  • プライマリソートキー:sortOrder(数値)

NoSQLデータベースなのでキー以外は自由に設定できますが、今回はとりあえず「message(文字列)」というフィールドに表示したいメッセージを格納します。

関数作成(Lambda)

Lambdaは、指定したイベントが発生したときのみ動作する(=常時稼働しない)サービスです。
管理コンソールより「Lambda」→「関数の作成」→「一から作成」で作成します。
「カスタムロールの作成」を選択し、Lambda実行用のIAMロールを作成します。

なお、今回はこのIAMロールに「AmazonDynamoDBReadOnlyAccess」ポリシーを付与する必要があります。
管理コンソールより「IAM」→「ロール」→「上記で生成したロール名」を選択→「ポリシーのアタッチ」で上記をアタッチしてください。

言語は色々使えるのですが、今回はPython3.6を使いました。
以下のコードを入力し「保存してテスト」で関数をテストします。

Lambda関数が呼び出された際、まずlambda_handlerが実行されます。
引数eventにパラメータが格納されるので、それを利用してDynamoDBから値を取得します。

エンドポイント作成(API Gateway)

API Gatewayは、APIのエンドポイントを作成できるサービスです。
実際の処理は今回のようにLamdbaでも良いですし、他のAWSサービスでも良いです(もちろん、HTTPサービスもコールできます)。
管理コンソールより「Amazon API Gateway」→「APIの作成」を選択し、APIを作成します。
その後、実行するメソッドを追加します。

今回はデータを返却するだけなので「GET」のみ作成しました。
セットアップでは「統合タイプ」に「Lambda関数」を選択し、先ほど作成した関数のリージョンと名前を選択します。
なお、Lambdaにパラメータを渡すためには、統合リクエストを編集する必要があります。

「統合リクエスト」を選択し、「本文マッピングテンプレート」→「マッピングテンプレートの追加」で以下を入力して保存します。

最後に「アクション」から「APIのデプロイ」を選択し、ステージを決定のうえデプロイ完了です。
ステージエディターの「URLの呼び出し」横にあるURLが今回利用するエンドポイントです。

呼び出しは以下のようになります。

https://(エンドポイントURL)/(ステージ名)?category=(テーブルのcategory)&order=(テーブルのsortOrder)

できあがったもの

かなり駆け足、かつ途中端折っている部分もありますが、いかがでしたでしょうか。

所感

正直「こんなに簡単に実装できるのか」と衝撃でした。
IAMやLambda関数を利用したAPI認証も可能なので、モバイルサービスやSPAと連携したAPIも低コストで構築できるのではないでしょうか。
Lamdbaは常時稼働でない分、初回起動時の速度をいかに担保するかが重要に感じました。
今回の件と直接は関係ありませんが、IAMユーザはポリシー割り当てで結構ハマったので、そのあたりは次回以降に書きたいと思います。

ちなみに、これらの機能を使った別のアプリケーションをこちらに公開していますので、興味のある方はご覧ください。

Laravelでカスタムコレクションクラスを利用する

今回はLaravelのお話です。
先日5.5(LTS)がリリースされるなど最近何かと話題のLaravelですが、今回はそんな新しい機能の話ではありません。

Laravel5.xやCakePHP3.xでは、PHPの残念な配列(連想配列含む)を良い感じに扱えるCollectionというクラスが存在します。
上記2フレームワークでは、ORMを使ってDBへ問い合わせた結果がCollection型で返ってくるケースが多いこともあって、new Collection()するよりはそのインスタンスを使うケースのほうが多いように感じます。

通常のforforeachでループできることはもちろん、map()filter()といったデータの整形や絞り込みをメソッドチェーンで行えるので、直感的にコードを書くことができます。
そこで、「拡張コレクションを作って特定モデルの結果はそいつを使おうぜ」というのが今回のテーマです。

注意しないといけないのは、map()メソッドのように内部でコレクションを生成する関数を呼び出した場合です。
map()関数は、内部で保持しているインスタンスがModelでなかった場合、Collectionクラスを返します。
上記evenPosts()の例だと、メソッドが最終的に返却するArticleCollectionクラスが内包しているのは配列なので、この戻り値からさらにmap()すると戻り値はCollection型になってしまいます。
つまり、evenPosts()map()evenPosts()といった呼び出し方をするとエラーになります。

その場合は上記コードにあるように、継承元であるIlluminate\Support\CollectiontoBase()メソッドをオーバーライドすれば良いです。

同様のことがCakePHP3でもできるんじゃないかと思っているんですが、こちらは今のところIteratorクラスを使うことになりそうです。

Laravelはドキュメントも充実しているので、大体はそこから情報を得られます。
以下に私が利用しているサイトのリンクを掲載しておきます。