達人に学ぶDB設計徹底指南
達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ
- 作者: ミック
- 出版社/メーカー: 翔泳社
- 発売日: 2012/03/16
- メディア: 単行本(ソフトカバー)
- 購入: 18人 クリック: 254回
- この商品を含むブログ (15件) を見る
「初心者で終わりたくないあなたへ」という副題ですが、基本的には初心者が手っ取り早く基礎を固めるための書籍のように感じました。データベーススペシャリストの午前の解説書のような正規化理論やインデックスなど基本的なテーマにページをさいていますので、。このあたりの知識がある人にとっては1時間くらいあれば読める内容で多少物足りないかもしれません。
個人的に興味を持ったのは以下のような話題でしょうか。
- サロゲートキーではなくナチュラルキーをしようすべき
- group byでアドホックキーを使う
- sequenceとIDENTITY
ORMのようなフレームワークとの相性もあってか、最近はサロゲートキーが全盛という気がするのでナチュラルキーを使え、という話は自分の中でそれぞれのメリット・デメリットを再考するきっかけになりました。
IIJmio高速モバイル/D
スマートフォンの通信環境として、いままで日本通信のb-mobile Fairを使っていたのですが、期限が切れたのを機に、IIJmio高速モバイル/Dのファミリーシェア1GBプランに変更してみました。
ファミリーシェア1GBプランは通信量1GBまでは2940円/月で、特徴的なのがSIMが3枚まで使えるということです。家族で共有してもよし、自分で複数枚使ってもよしですが、うちは妻が私のお下がりのGalaxy Sに入れて使ってます。家族がスマホを使っているような家庭では、かなり通信費が節約できるのではないでしょうか。ただし2台持ち前提ですが。1GBというのもこれまでもb-mobile Fairの1GBを使い切るのに3ヶ月くらいかかっていたので、私には全然問題無いです。
以下、速度です。多少時間帯が違いますが、端末はXperia acroで同じ場所で測定した結果です。IIJmioの方が速いですね。体感的にもそんな感じがします。IIJmioの方はXi対応ですが、私は検証できる端末がありません。
b-mobile Fair
IIJmio高速モバイル/D
継続的デリバリー
継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化
- 作者: David Farley,Jez Humble,和智右桂,高木正弘
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2012/03/14
- メディア: 大型本
- 購入: 23人 クリック: 507回
- この商品を含むブログ (35件) を見る
ワンクリックで本番環境へのディプロイやリリースが可能な状態を常に維持して開発を行うということが目標ですが、そこに至るために必要な要素というかプラクティスが多いため、実現することはかなりしんどいな、というのが印象です。ただ、これくらいはやっていかないと、自信を持って、常にリリース可能な製品は作れないというのもわかります。本書は
などを熟知した上で、より効率的な継続的デリバリーを実現のためには、、ということだと思います。私自身まったくそのレベルには至っていないのですが、いくつか印象に残ったことを書いておきます。その他にもDVCSやデーベースリファクタリングやリリース方法など盛りだくさんです。
少し気になる点としては、全体的に文章が多くて、特に前半は同じ事が繰り返し述べられている印象がありました。
ブランチを使わない
VCSを使ってある程度大きな機能追加やリファクタリングを行う場合には、ブランチを切って作業を行うことがありますが、本書は一貫して否定的です。メインラインにマージする時間が遅れるほど問題が起きやすく、大規模な変更を分割して小さくしたうえでインクリメンタルにメインラインにコミットせよということです。
受け入れテストのレイヤー化
私も苦労していますが、、自動の受け入れテストをUIベッタリに書いてしまうと(webであればhtmlのid等をハードコーディングする)、テストコードの変更コストが大きくなりすぎるので、UIを抽象化したレイヤを設けるべき。SeleniumのPageObjectモデルのような考えだと思います。
旧バージョンに戻すとき
何かの理由で旧バージョンに戻すときには、旧バージョンをディプロイし直すか、そもそも旧バージョンを残しておいて切り替えるべき。バージョンを戻すための手作業はダメ。ディプロイもステージング環境と本番とで同じ手順にしておけば、何回も繰り返していることなので安全。
Gitによるバージョン管理
- 作者: 岩松信洋,上川純一,まえだこうへい,小川伸一郎
- 出版社/メーカー: オーム社
- 発売日: 2011/10/25
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 210回
- この商品を含むブログ (25件) を見る
git関連の本は入門gitを持っているのですが、そろそろ業務でもgitを使おうかというタイミングなのでもう一冊『Gitによるバージョン管理』を読んでみました。gitを使うシチュエーションとして、
- 一人で使う
- チームで使う
- オープンソースプロジェクトで使う(大規模)
という順に、ストーリー仕立ての導入とそこでよく使うgitコマンドの解説という構成になっています。VCSの本は、だいたいこんな感じが多いですが、導入とコマンド解説がわりとしっかり分かれていて、参照しやすいです。ストーリー仕立ての中にコマンド解説が紛れているとリファレンス的な使い方をしづらいので。
チームで使う場合のワークフローも紹介されていていますが、管理者がセントラルリポジトリを管理して、さらに個人用のリモートリポジトリを作ってというのは、結構しんどい気がします。。私自身一人で使ったことないので想像ですが、git flowを試してみようかと思っています。
Play framework2.0を使ってみた
ちょうどPlay framework 2.0が正式にリリースされたましたが、1ヶ月くらい前(RC2くらいのころ)に、Scalaの方を少し試してみたときのメモや感想です。とりあえず、Play Scalaのチュートリアル(‘Yet Another Blog Engine’)を、2.0で写経してみました。もともとScala版のチュートリアルは、CRUD(いわゆるスカッフォールディング)などのモジュールがないため、Java版のチュートリアルにある後半部分(管理画面や認証機能)がないのですが、今回も同じところまでです。
コードは以下においてありますが、私はScalaについては本は読んだけど実際にまとまった量のコードは書いたことがない初心者なので、Scalaのコードとしては酷いレベルだと思います。
kenichiro22/yabe-play20-scala
Play 2.0からの仕様変更やサポートされなくなった機能の影響などで、チュートリアルのコードのうち以下のような部分は変更しています。
Bootstrap
Bootstrapクラスに書いていた初期化処理は、play.api.GlobalSettinsを継承したクラスに書く。
object Global extends GlobalSettings { override def onStart(app: Application) { if (app.mode == Mode.Dev) { // 開発環境での初期データの登録 InitialData.insert() } } }
Fixtures
FixturesというYAMLからデータを読み込む機能がなくなっています。Scalaのコードで書いてもYAMLとそんなにかわらないということのようです。
Seq( User(Id(1), "bob@gmail.com", "secret", "Bob", false), User(Id(2), "jef@gmail.com", "secret", "Jef", false) ).foreach(User.create)
Anorm
1.2のScalaモジュールや2.0の途中までは、モデルクラスでMagic[T]を継承しておくとinsert/updateや基本的なselect文は自動生成していましたがこれはなくなったようです。例えばone-to-manyの集約なんかもScalaのコレクションAPIを使うということのようです。いちいち基本的なSQLを書くのは面倒なので、別のORMを使うか自前で自動生成部分を書く必要がありそうです。
テンプレートヘルパー
テンプレートはこれまでのGroovyベースからScalaベースのものに変更されています。コントローラーや静的リソースにアクセスするためのヘルパーメソッドがかなり変わっています。@action(controllers.Application.***) は @routes.Application.*** になっていて、@asset は@routes.Assets.at になってます。
Flashスコープ
Flashスコープの使い方は以下のような感じです。
def postComment(postId: Long) = Action { implicit request => Ok(〜).flashing("success" -> "Success!") }
Controllerで↑のようにしておいて、テンプレート↓で受け取る。
@(/* 通常のテンプレート引数 */)(implicit flash: Flash)
Captcha
チュートリアルでcaptchaを使っているのですが、2.0ではCaptcha関連のクラスがまだないようだったので、JCaptchaというライブラリを使いました。sbtで依存ライブラリの管理を行います。
Job
Jobというクラスを使ってスケージュール実行を行なっていましたが、AkkaというScalaのアクターライブラリを使う方針のようです。前はCron形式のスケジュール指定ができたと思いますが、この辺もいまは自前でしょうか。
AWS SDK for Rubyでインスタンスのイメージ(AMI)を登録する
未だにEC2インスタンスのバックアップというかスナップショットからのリストアのベストプラクティスというのがわかりません。VMwareでのスナップショットと同じ感覚で操作したいのですが。。
EBSボリュームのスナップショットから復元する場合には、以下のような手順になると思います。
単一ボリュームであればそれほど問題ないのですが、複数のEBSボリュームをアタッチしている場合に手順が煩雑です。この処理を行うスクリプトやツールを作成すればよいのかもしれません。
また、別の方法として、インスタンスごとイメージ(AMI)を作成して登録しAMIを世代管理すればよいのではと思いスクリプトを書いてみた、、のですが、どうもうまく動かないので放置状態になってました。せっかくなのでここにあげておきます。
AMIから新しいインスタンスを立ち上げた場合には、インスタンスIDが変わってしまうので、別の処理でインスタンスIDに依存した部分があったりすると、それはそれで面倒です。そもそも、うまく説明できないのですがインスタンスの一個に依存するような利用・運用がEC2の特性にそぐわないのではないかという気もします。
# -*- coding: utf-8 -*- require 'rubygems' require 'yaml' require 'aws-sdk' require 'date' ID_TAG="backup" unless ARGV.size == 2 puts "Usage: #{$0} <target_instance> <count>" exit 1 end instance_id = ARGV[0] count = ARGV[1].to_i unless count > 0 puts "Count must be greater than 0 !" exit 1 end puts "Create image of #{instance_id} with #{count} generations." config = YAML.load(File.read("config.yml")) AWS.config(config) ec2 = AWS::EC2.new instance = ec2.instances[instance_id] unless instance.exists? puts "No such instance: #{instance_id}" exit 1 end # Create new image image_name = "#{instance.id}-#{DateTime.now.strftime("%Y%m%d%H%M%S")}" image_desc = "Backup image(#{instance.tags['Name']}) at #{DateTime.now}" new_image = instance.create_image(image_name, {:description => image_desc, :no_reboot => true}) # Add tag for indentifying backuped images new_image.tags << ID_TAG # wait for complete puts "waiting for new image: #{new_image.name}" begin sleep 1 new_image = ec2.images[new_image.id] end until new_image.state != :pending if new_image.state == :failure puts "create image failed: #{new_image.state_reason}" exit 1 end # Remove old images ec2.images.with_owner(:self). filter("name", "*#{instance.id}*"). filter("state", "available"). tagged(ID_TAG). sort_by{|i| i.name}.reverse_each. # sort descending by datetime each_with_index {|i, idx| if idx >= count puts "#{i.name} -> deregister" i.deregister else puts "#{i.name} -> hold" end }