おまけ:今後の受験予定

Image for post
Image for post

イワモトです。2020年7月末でベルトラを退職することになりました。どうしても挑戦したいことができ、悩んだ末に出した結論です。

ベルトラでは、本業のソフトウェアエンジニアのほか、資格コンサルタント(自称)としての活動もおこなっていました。人事部の方から「資格を取るなら何がよいか」と相談され、社労士をすすめたこともあります。

ぼく自身、ベルトラ入社前から多くの資格を取ってきました。ただ、ラーメン好きが一年中ラーメンを食べ歩いているようなもので、それが偉いとか偉くないとかいう話ではないと思っています。ただの趣味です。

この記事では、ぼくがベルトラ在職中 (2017–02 ~ 2020–07) に取った資格をご紹介します。あなたにとって、おいしそうなラーメンが1杯でも見つかれば幸いです。

情報処理技術者試験

※日付は受験日です(以下同じ)

ITエンジニアにはおなじみの国家試験です。ぼくは、情報処理安全確保支援士試験を含めた13区分のコンプリートを目指しています。

ベルトラ在職中は調子がよく、7連勝できました。特にプロジェクトマネージャからITサービスマネージャにかけての4つは、論述式の出題を含むため、以前は苦手意識を感じていたものです。少しは成長できたかなと思っています。

ITに関する資格(情報処理技術者試験以外)

興味のある分野を手当たり次第に受けました。特におすすめがあるとすれば、AWS認定とウェブ・セキュリティ基礎試験です。AWS認定は仕事の幅が広がると思います。ウェブ・セキュリティ基礎試験はWebエンジニアなら知っておくべき内容です。

旅行に関する資格

ベルトラは旅行会社なので、旅行の知識を身につけたいと思って受けたものです。国内旅行業務取扱管理者は2017年に一部合格となってしまい、取得に2年かかってしまいました。

その他の資格

これらも手当たり次第でした。特におすすめがあるとすれば、ファイナンシャル・プランニング技能検定(FP)と危険物取扱者(乙4)です。FPは家計のやりくりの参考になります。乙4は老後の再就職に有利なはずです。

FPの実技試験にはベルトラ入社前に受かっていたのですが、学科がなかなか受からず、3度目でようやく合格できました。人間、向き不向きがあります。3度受けてダメなら諦めたほうがよいかもしれません。

日本語検定を2度受けたのは、複数回合格するともらえる盾を狙ってのことでした。こうした記念品も資格取得の楽しみのひとつです。

おまけ:今後の受験予定

ベルトラ退職後も受験しまくるつもりです。時期が決まっているものを挙げると下記のようになります。

せっかく旅行分野の勉強をしてきたので、運行管理者と総合旅行業務取扱管理者までは取りたいと思っています。残りの4つは本業のITに関する資格です。

また、以下のIT関連資格も気になっています。いずれ受けるつもりです。

まとめ

以上、ベルトラ在職中に取得した資格と今後の受験予定についてまとめました。

くり返しになりますが、資格取得は単なる趣味です。誰にでもおすすめするわけではありません。ただ、何か学びたいことがある方や、自分の可能性を広げたいと思っている方には、うってつけの趣味だと思います。楽しいですよ。


放置されたissueは、伸びきったひげのようだ

Image for post
Image for post

マスク生活のおかげで、ひげを伸ばしたい放題のイワモトです。先日、GoのMustacheテンプレートエンジンにプルリクエストを送ったところ、マージされました。その話を書きます。小ネタです。

Mustacheとは?

Mustacheはプログラミング言語や用途に依存しない汎用的なテンプレート仕様です。40以上のプログラミング言語で処理系が実装されています。

構文に {{var}} のように波括弧が頻出し、{ が横向きの口ひげに見えることから、口ひげを表すMustacheと名づけられました。

どんなプルリクエスト?

ぼくが送ったプルリクエストはこちらです。写真はメンテナの方で、ぼくではありません。

こんなテンプレートに対して:

You have {{count}} items:
{{#sections}}
--{{name}}--
{{#items}}
{{.}}
{{/items}}
{{/sections}}

下記のコードを実行した場合:

mustache.AllowMissingVariables = false
s, err := mustache.Render(tmpl, map[string]interface{}{
"count": 2,
"sections": map[string]interface{}{
//"name": "Stuff",
"items": []string{"foo", "bar"},
},
})
fmt.Println(s, err)

sections.name が存在しないのだからエラーを返してほしい、というissueが立ったのが2016年10月のこと。

メンテナから「I agree this is a valid issue.」「PRs are welcome 😄」と返信があったものの、ずっと放置されていました。

2020年4月、GoのMustacheについて調べていたぼくは、たまたまこのissueを見つけました。むむ、これは対応できそうな気がするぞ。

さっそく手もとで試したところ、エラーハンドリングの追加と、テストコードの移動だけでエラーを返せることがわかりました。なかなかエレガントなdiffではないでしょうか。

すぐにプルリクエストを送ったものの、メンテナが忙しそうなので、反応は期待しませんでした。そして送ったのを忘れた頃、マージ完了の通知が来た次第です。送ってみるものですね 🧔


Intent-Responseパターンの提案

Image for post
Image for post

昨秋に受けた人間ドックの結果、メタボ予防の指導対象となったイワモトです。半年間の指導が先日終わりました。

人間のファットも問題ですが、Webアプリにおけるコントローラのファットも問題です。保守性が下がり、エンバグの危険性が高まるためです。書籍『Rails AntiPatterns』でも、Railsのアンチパターンのひとつとして「Fat Controller」が挙げられています。

Fat Controllerの予防には「ビジネスロジックやプレゼンテーションロジックをコントローラに書かない」ルールを守るのが効果的です。前者はモデル、後者はビューの責務です。このルールを守れば、コントローラをスリムに保てます。

ただ、ルールを守るといっても、なかなか大変です。プロジェクトに携わるすべてのプログラマにルールを守らせるには、相応のコストがかかるでしょう。ルールの周知、ルール違反の検知・修正といったコストです。

何か、頑張らなくてもルールが守られる実装パターンは考えられないものでしょうか? もし、そのようなパターンで実装されたフレームワークなりミドルウェアなりが使えたら、コストをかけずにFat Controllerが予防できます。

Intent-Responseパターン

そこで思いついたのが「Intent-Responseパターン」です。以下、詳しく説明します。

Intent

  • ビジネスロジックを担当
  • コントローラのアクションから即座に呼び出される
  • HTTPリクエストを受け、HTTPステータスコードとビジネスロジックの実行結果(outcome)を返す

Response

  • プレゼンテーションロジックを担当
  • Intentが返したHTTPステータスコードをもとに、コントローラから呼び出される
  • HTTPリクエストとoutcomeを受け、HTTPヘッダとレスポンスボディを返す

コントローラ

  • IntentとResponseの呼び出しを担当
  • HTTPリクエストを受け、呼び出すべきIntentを決めて呼び出す
  • Intentから返されたHTTPステータスコードをもとに、呼び出すべきResponseを決めて呼び出す

Intent-Responseパターンの実装例

言葉だけでは分かりづらいので、実装例として、Flaskの拡張機能を作ってみました。flask-skinnyです。

インポートすると、Flaskアプリを下記のように実装できます。

from flask import Flask
from flask_skinny import skinny
from random import randint
import json


def intent(request): #3
if randint(0, 1) == 0:
status_code = 200
outcome = "OK"
else:
status_code = 403
outcome = "Forbidden"
return status_code, outcome


def response(request, outcome):
headers = {"content-type": "application/json"}
body = json.dumps({"message": …


「リダイレクトテスト」機能では不可能。どうする?

2020年5月に「高度なリダイレクト」機能が追加され、多数のページのA/Bテストがリダイレクトテスト機能でできるようになりました。本記事のタイトルおよび本文は、2020年3月時点の情報であり、古くなっています。ご注意ください。
Image for post
Image for post

ベルトラのイワモトです。「人生は選択の連続である」と誰かが言ったそうですが、確かに、A定食にすべきかB定食にすべきかなど、難しい選択を迫られる場面はよくあります。

さて、Googleオプティマイズは、ウェブサイトのA/Bテストが簡単にできる便利なツールです。「リダイレクトテスト」機能を使うと、新デザインページへのリダイレクトによるA/Bテストが実現できます。

しかし、2020年3月現在のリダイレクトテスト機能では、リダイレクト先が静的URLでしか指定できず、1ページしかテストできません。たとえば「商品0001の新ページ」はテストできますが「商品0001~商品9999の新ページ」はテストできないのです(※)。

※リダイレクトを /products/0001 → /products2/0001 のようには指定できるのですが、/products/{product_id} → /products2/{product_id} のようには指定できないためです。

それでも、Googleオプティマイズで多数のページをリダイレクトテストする方法があります。以下、詳しくご紹介します。

1. エクスペリエンスの作成

まず、エクスペリエンスを作成します。Googleオプティマイズでは、各種テストやパーソナライゼーションを総称して「エクスペリエンス」と呼んでいます。

作成する際は、下記の2点に気をつけます。

  1. 「エディタページ」には新デザインページのURLを指定します。ビジュアルエディタの操作対象として使われるだけなので、どの商品でも構いません。現行デザインのURLにすると、ビジュアルエディタ上でリダイレクトが効いてしまい、操作しづらくなります。
  2. 「テストのタイプ」は「A/Bテスト」を選択します。「リダイレクトテスト」を選択しないのがポイントです。
Image for post
Image for post

2. パターンの追加

次に、パターンを追加します。現行デザインは「オリジナル」パターンとしてデフォルトで登録されているので、新デザイン用のパターンだけを追加すればOKです。実際には、パターン名を決めるだけです。

Image for post
Image for post

3. パターンの編集

続いて、手順2で追加したパターンを編集します。ここでビジュアルエディタが使われます。

3–1. 要素の選択

ビジュアルエディタが開いたら、head要素を選択します。

Image for post
Image for post

3–2. 要素の編集

「要素を編集」ボタンを押し、「JavaScriptを実行」を選択します。

コード入力欄が開いたら、リダイレクト用のコードを入力します。

Image for post
Image for post

適切なコードの内容はサイトやページによって異なります。ここでは下記のようにします。

if (location.href.includes('/a/')) {
// Hide body
var css = 'body {display:none}';
var style = document.createElement('style');
style.appendChild(document.createTextNode(css));
element.appendChild(style);
// Redirect
location.href = location.href.replace('/a/', '/a2/');
}
  • URLに「/a/」が含まれる場合だけリダイレクトする
  • 現行デザインがちらっと表示されるのを避けるため、bodyを非表示にする
  • リダイレクト先は、現行デザインページの「/a/」を「/a2/」に変えたもの

プルダウンは「開始タグの後」を選択するのがよいと思います。「終了タグの後」より若干早く処理されるためです。

3–3. 編集内容の保存

「適用」ボタン、「保存」ボタン、「完了」ボタンを順に押し、編集内容を保存します。これでビジュアルエディタが終了します。

4. ターゲティングURLの編集

次に、ターゲティングURLを編集します。現段階では、手順1で選んだ新デザインページが仮設定されています。

Image for post
Image for post

これを、正しいターゲットである「リダイレクトテストを実施したい現行ページすべて」に変更しなければなりません。

変更するには、鉛筆アイコンを押して編集画面を開き、下記のように編集します。

  1. 「URL」「次の正規表現に一致」を選ぶ
  2. 現行ページにマッチする正規表現を入力する
Image for post
Image for post

編集したら「ルールの確認」欄で、現行ページのURLが正しくマッチするかどうか確認します。問題なければ保存しましょう。

保存すると「 エディタページが URL ターゲティング ルールと一致しません。」と警告されます。が、気にしなくて大丈夫です。

Image for post
Image for post

5. その他の設定

あとは必要に応じて、新デザインの表示確率、ターゲティングユーザー、テスト目標などの項目を設定します。このあたりはGoogleオプティマイズの通常の使い方なので省略します。

6. テストの開始

設定が完了したら「開始」ボタンを押します。いよいよテスト開始です。

現行ページのURLにアクセスすると、手順5で指定した確率で、新デザインページにリダイレクトされます。されなかった場合は、Cookieを削除し、再度アクセスしてみてください。

Cookieを削除するのが面倒なら、ブラウザのシークレットウィンドウでアクセスするのが簡単です。ウィンドウを閉じるとCookieが自動的に削除されます。

おわりに

今回は、Googleオプティマイズの「A/Bテスト」機能を使って多数のページをリダイレクトテストする方法をご紹介しました。将来的に「リダイレクトテスト」機能で可能になることを期待しますが、それまでは今回の方法で実施するのがよいと思います。

なお、この方法は下記ページの内容と原理的には同じです。下記ページでは、ビジュアルエディタに指定するJavaScriptコードが「フラグ変数を設定するだけ」になっています。フラグが立っていたらページ側のスクリプトでリダイレクトする寸法です。この辺は好みの問題でしょう。

Happy A/B testing!


SAMテンプレートの記述例とその解説

Image for post
Image for post

虎の穴ラボさんの「Python + AWS LambdaでSSL証明書の有効期限をチェックする」を拝見し、この構成ならSAMでデプロイするのが便利そうだと思いました。SAMテンプレートの記述例はこんな感じです。

SAMテンプレートの記述例

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
Urls:
Type: String
Description: "Domains to remind (comma separated)"
Default: "example.com"
BufferDays:
Type: Number
Description: "Days to start reminding"
Default: 30
IncommingWebhooks:
Type: String
Description: "URL of Slack Incoming Webhook"
Default: "https://hooks.slack.com/services/*"
Resources:
RemindFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: remind/
Handler: app.lambda_handler …

AWS::Serverless::ApiのOpenApiVersionを指定すればOK

Image for post
Image for post

先日、AWS SAMチュートリアルを進めていて、アプリケーションをデプロイした際、API Gatewayに2つのステージ(「Prod」と「Stage」)が作られ、不思議に思いました。必要なのは「Prod」だけです。調べると、これはSAMのバグで、すでに回避策が提供されていることが分かりました。本記事では、その回避策をご紹介します。

回避策:AWS::Serverless::ApiのOpenApiVersionを指定する

その回避策とは「SAMテンプレートのAWS::Serverless::Apiリソースに対するOpenApiVersionの指定」です。GitHubのissue正式な回避策として紹介されています

OpenApiVersionに指定できる値は下記の通りです。

This can either be 2.0 for the Swagger specification, or one of the OpenApi 3.0 versions, like 3.0.1. For more information about OpenAPI, see the OpenAPI Specification.

Globalsセクションで指定する場合

実際の指定先として手っ取り早いのはGlobalsセクションです。下記のように指定するだけで、不要な「Stage」ステージが作られなくなります。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 3
Api:
OpenApiVersion: 3.0.2
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.7
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get

Resourcesセクションで指定する場合

もしくは下記のように、AWS::Serverless::FunctionリソースのEventSource側で指定しても、不要な「Stage」ステージが作られなくなります。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.7
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId:
Ref: HelloWorldApiGatewayApi
HelloWorldApiGatewayApi:
Properties:
StageName: Prod
OpenApiVersion: 3.0.2
Type: AWS::Serverless::Api

回避策が使えるAWS SAM CLIのバージョン

この回避策はAWS SAM CLI 0.22.0以降であれば使えるはずです。aws-sam-translator 1.13.0で回避策が追加され、AWS SAM CLI 0.22.0で依存しているaws-sam-translatorのバージョンが上がりました

まとめ

AWS SAMで余分な「Stage」ステージが作られるバグについて、回避策をご紹介しました。余分なステージを作ってもメリットはないので、忘れずに回避しましょう。


運行管理者とは/基礎講習とは/受講した理由

Image for post
Image for post

こんにちは、知識欲のブレーキが壊れているイワモトです。先日、運行管理者(旅客)の基礎講習を受けてきました。この記事では、運行管理者とは何なのか、基礎講習とはどんなものか、そして、なぜ受講しようと思ったのか、ご説明します。

運行管理者とは

自動車運送事業者において、安全運行を実現するために選任されるのが運行管理者です。運行管理者の仕事内容は多岐に渡ります。運行シフトを組んだり、乗務員の点呼をしたり、休憩所の管理をしたりなどです。

自動車運送事業者といえば分かりづらいですが、その典型例は、バスやタクシーでの輸送を営む企業や、トラックでの運送を営む企業です。前者を旅客自動車運送事業者、後者を貨物自動車運送事業者とよびます。

これらの事業者は、運行管理者を必ず選任しなければなりません。道路運送法や貨物自動車運送事業法でそのように決められているのです。

運行管理者になるには、まず運行管理者資格者証を取得する必要があります。取得するには下記のいずれかを満たさなければなりません。

  • 運行管理者試験に合格する
  • 運行管理者の補助者として選任され、5年の実務経験を積みつつ所定の講習を受ける

ちなみに、資格者証にも旅客と貨物の種別があります。対応する事業者でなければ、運行管理者にはなれません。旅客の資格者証を持っていたとしても、貨物自動車運送事業者の運行管理者にはなれないのです。

基礎講習とは

自動車事故対策機構などの認定機関が運行管理者になりたい人のために開催しているのが基礎講習です。名前のとおり、運行管理に関する基礎知識が学べます。

基礎講習を修了すると、下記のメリットがあります。

  • 運行管理者試験が受験できる
  • 運行管理者の補助者になることができる

運行管理者になるには、前述のように、試験の合格か、補助者としての実務経験が必須となります。結局のところ、基礎講習を修了しないと運行管理者にはなれないわけです。

ぼくの例

ぼくは、2019年12月16日から18日にかけて、杉並交通株式会社で旅客用の基礎講習を受講しました。講習時間が16時間と定められているため、3日間に分けて開催する機関がほとんどのようです。杉並交通さんもそうでした。

参加者はぼくを含め5名でした。他の機関では100名以上になることもあるみたいです。ぼくの場合、少人数のほうが講義に集中できる気がします。参加者には、バスやタクシーの運転手さんもいましたし、受験資格を得るために来ている若い方もいました。

講習の内容はテキストの説明が主体で、安全や業務内容に関するDVDの上映や、実体験にまつわる裏話などが織り交ぜられる形でした。開催機関によっては、眠気防止のためか、参加者にテキストを音読させるところもあるようです。

最終日には記述テストがありました。「80点以上取らないと修了証が出せない」との説明が初日にあって不安でしたが、受けてみると簡単な内容でした。修了証は全員もらえたはずです。ただ、開催機関によって難度が異なる可能性もあります。適度な緊張感をもって受講すべきでしょう。

受講した理由

さて、ぼくがこの基礎講習を受けたのは、やはり運行管理者試験の受験資格が欲しかったからです。ぼくは老後も仕事を続けたいと思っています。続けるには資格が多いほうが有利なはずです。本当は今のままWebエンジニアとして働きたいのですが、需要があるとは限りません。

ほかには、旅行業界の一員として、旅客自動車運送事業者の業務知識を少しでも得たいとの思いもありました。実際、講師の話を聞いた限りでは、事業者向けのクラウドサービスには発展の余地があると感じています。それが分かっただけでも参加した甲斐がありました。

次回の運行管理者試験は2020年3月です。せっかく受験資格が得られたので、合格を目指してがんばります。


誤入力の実例と対策案

Image for post
Image for post

イワモトです。最近は、ベルトラのメール送信に関する課題の解決に取り組んでいます。課題のひとつがメールアドレス誤入力による送信エラーです。そのうちドメイン部の誤入力は、入力チェックで減らせそうだと思っています。誤入力の実例を示すとともに、対策を検討してみましょう。

ドメイン誤入力の実例

下記は、誤入力と推測されるドメインの一覧です。送信エラーログに含まれるドメインのうち、DNSレコードが引けず(詳細は後述)、主要なフリーメール・キャリアメールのドメインに類似しているものを機械的に抽出しました。

類似度の計算に使ったのは、PHPの similar_text 関数です。この関数は、2つの文字列の類似度をパーセンテージで計算してくれます。結果が100なら完全一致です。

前掲の一覧は、類似度の計算結果が80以上となったもののみに絞り込んでいます。gmale.comme.com のように微妙なペアも含まれていますが、閾値をあまり高くすると拾うべきものが拾えなくなってしまうため、ほどよい辺りに設定したつもりです。

対策の検討方針

これらの誤入力は、メール送信より前、具体的にはユーザが自身のメールアドレスをフォームに入力した時点でチェックし、フィードバックするのが妥当でしょう。見逃してしまうと、いつまでたってもメールが届かず、ユーザの方に迷惑をかけることになるためです。

そこで検討すべきは、どのようなチェック規則を設け、どのようなフィードバックを送るかということになります。

チェック規則の案

まず、チェック規則については、さきほど少し触れたように、DNSレコードが引けなければ誤入力の可能性が高いとみなすのが適当ではないかと考えます。具体的には、下記すべてが引けない場合です。

  • MXレコード
  • Aレコード
  • AAAAレコード
  • CNAMEレコード

ぼくの理解に誤りがなければ、SMTPクライアントは、これらのレコードを検索して配送先ホストを決定しています。検索できなければ送りようがなく、誤入力が疑われます。

ただし、DNS設定ミスやサーバダウンなどが原因で検索できなくなっていることもありえます。「誤入力の可能性が高い」とみなすにとどめておくことが肝心です。

PHPでのチェック例

ちなみに、このチェック規則をPHPで実装するなら、checkdnsrr 関数が利用できます。下記は実装例です。

フィードバックの案

さて、「誤入力の可能性が高い」と疑われるときに、そのことをユーザにどのようにフィードバックすべきでしょうか。ぼくが考えたのは下記の案です。

  • 主要なフリーメール・キャリアメールのドメインに類似している場合、正しいと推測されるドメインをサジェストする
  • 類似していない場合、誤入力の可能性があることを伝える

類似度の計算方法は前述の通りです。たとえば hoge@i-softbank.ne.jp が入力されたら、hoge@softbank.ne.jp hoge@i.softbank.ne.jp がサジェスト候補となります。

サジェスト候補が存在しないときは、誤入力の可能性があることだけ伝えれば充分でしょう。正しいドメインはユーザ自身が知っているはずだからです。

繰り返しになりますが、あくまで「誤入力の可能性が高い」だけなので、そのようなメールアドレスの登録自体は許容すべきです。念のため見直してもらうだけにとどめましょう。

まとめ

というわけで、今回の記事では、ドメイン誤入力の実例を示し、対策を検討しました。そのまま実装を進めるかどうかは未定ですが、まずは考えを整理した次第です。何らかの対策ができた暁には、その効果をご紹介できればと思っています。


きれいなビーチ、おいしい食事、懐っこい猫

Image for post
Image for post

2019年11月上旬、沖縄の竹富島に初めて行ってきました。ビーチと食事、そして猫のたたずまいがすばらしく、いずれ再訪したいと思っています。この記事では、特に気に入った場所や、旅行時の注意点について、写真をまじえてお送りします。

気に入った場所

コンドイビーチ

島の西側にある砂浜です。再訪先をひとつだけ選ぶならここにします。朝に立ち寄ったところ、人がまだ少なく、潮が引いていて、絶景でした。沖のほうにできた浜まで歩いて渡る人もちらほらいました。

Image for post
Image for post
2019-11–08 09:49

しばらくぶらついていると、猫が寄ってきました。ビーチ周辺では猫が何匹も暮らしていましたが、いちばん懐いてきたのがこの子です。レジャーシートやぼくの膝の上にじっと座るので、次の場所に移動するのがもったいなくなってしまいました。

Image for post
Image for post
2019–11–08 09:55

そば処 竹乃子

集落西側にあるそば屋さんです。「そば処」なのだから絶対おいしいだろうと選びました。本場のそばを食べるのが今回の旅行の目的のひとつだったのです。

宿の朝食が重く、おなかは減っていなかったのですが、お昼は混むとの噂なので11時前に入店しました。頼んだ三枚肉そばは期待以上で、空腹ならおかわりしたかったくらいです。

午後には噂どおり空席待ちの人だかりができていました。コンドイビーチもそうですが、行動をふだんより1時間ほど早めるのが竹富島観光のコツなのかもしれません。

Image for post
Image for post
2019–11–08 10:59

ブーゲンビリア通り

集落北側のブーゲンビリアが植わっている小道です。花、正確には苞葉の色が鮮やかで、集落内で写真を撮るなら、ここが一番だと思います。

Image for post
Image for post
2019–11–08 11:43

頻繁に通る水牛車を待ちかまえて撮るのも一興です。

Image for post
Image for post
2019–11–08 11:48

ちろりん村

集落南側にあるカフェです。中心部から外れていて、落ち着ける印象でした。

店外奥のテーブルは、猫に占有されていました。首輪をしていたので、お店の飼い猫なのかもしれません。この子も懐っこく、陽射しがきつくなければ、もっと遊んでいたかったところでした。

Image for post
Image for post
2019–11–08 15:28

番外編:パポイヤ(石垣島)

石垣港離島ターミナル近くのステーキレストランです。帰京の日、竹富島からフェリーで石垣島に戻り、空港に向かう前のランチで寄りました。

注文したのは、特上石垣牛サーロインステーキと、おなじく特上石垣牛テンダーロインステーキです。めったに行けるところではないので、奮発しました。「最初は何もつけずに」とのことで、そのまま食べたら本当においしく、思わずのけぞりました。

ソースでも石垣塩でも当然おいしく、今まで食べたステーキのなかではダントツでした。また石垣島に行く機会があれば、絶対に寄ろうと思っています。

Image for post
Image for post
2019–11–09 11:57

竹富島旅行時の注意点

レンタサイクルは疲れる

竹富島内をレンタサイクルで走り回ったのですが、ふだん自転車に乗っていないせいか、脚がパンパンになりました。特に集落内の道は、砂にタイヤを取られそうになり大変でした。

なので、体力に自信のない方は、無理をせず、観光バスで巡ることをおすすめします。小さな島なので、石垣島からの日帰りツアーでも満足できるはずです。ぼくが務めているベルトラでも、石垣島発のツアーが予約できます。よろしければご利用ください。

日焼け対策は必須

日焼け止めを塗らず、帽子もかぶらずに遊び回っていたら、帰京後、顔の皮がボロボロにむけてしまいました。暑さをしのぐ意味でも、せめて帽子をかぶっておけばよかったなと思っています。竹富島の11月は東京の9月くらいの感覚でした。

おわりに

そんなわけで、初めての竹富島で、きれいなビーチ、おいしい食事、懐っこい猫を満喫してきました。ただ、心残りがふたつあります。強風でグラスボートに乗れなかったことと、パーラーぱいぬ島がお休みでフワフワかき氷が食べられなかったことです。次回の目標とします。


プログラマの不注意をアーキテクチャで予防する

Image for post
Image for post

イワモトです。2019年9月から10月にかけ、ベルトラの速度改善に取り組みました。サーバ側の平均応答速度が2割ほど改善され満足なのですが、とある速度低下の遠因がフレームワークのWeb MVCアーキテクチャにあると気づき、モヤモヤしています。本稿で掘り下げてみます。

速度低下とその原因

本稿で掘り下げたいのは「コントローラからビューテンプレートに対して不要なデータを渡していることにより速度が低下している」状況です。

速度を重視するのであれば、無駄な処理は避けるべきです。不要なデータなら、わざわざ参照したり受け渡したりする必要はありません。なぜ、そのような無駄が生まれるのでしょうか。

考えられる原因

今回の速度改善の経験から、不要なデータがビューテンプレートに渡される原因は下記の2つに大別できると考えます。

  1. あるコンテンツの表示が不要となり、ビューテンプレートから削除されたが、コントローラには手が入れられなかった
  2. あるコンテンツの表示/非表示が、ビューテンプレート側のロジックで決まっている

1つめは「書籍詳細ページから売上ランキングの表示を削除した」ような場合です。売上ランキングデータはもはや参照不要ですが、コントローラから参照処理を削除し忘れることが往々にしてあるようなのです。

2つめは「書籍の概要文が1000文字未満の場合のみ売上ランキングを表示する」ような場合です。概要文が1000文字以上の書籍なら、売上ランキングデータを参照しなくてよいはずです。

Web MVCアーキテクチャの問題点

上記のような問題が発生する遠因は、フレームワークのWeb MVCアーキテクチャにあるのではないか、というのがぼくの見立てです。以下、詳述します。

まず、多くのWeb MVCフレームワークは、コントローラがモデルのデータを参照し、ビューテンプレートに渡すよう設計されています。そのため、データの設定箇所と使用箇所が離れることとなります。

もし両者が離れていなければ、使用箇所のみを削除して設定箇所の削除を忘れることは少ないはずです。また、特定の条件下でのみ使用されるデータを無条件に参照することも減るでしょう。

つまり、Web MVCアーキテクチャが前提としている「ビューテンプレートで使われるデータをコントローラが知っていなければならない」という制約こそが、速度低下を招く遠因なのではないかと思うわけです。

回避策1:コントローラの責務を減らす

一般的なWeb MVCフレームワークでは、3つの責務がコントローラに任されています。

  • リクエストに応じて、モデルを参照/更新する
  • ビューテンプレートを決定する
  • ビューテンプレートにデータを渡してレンダリングする

しかし、ビューテンプレートで使われるデータを本当にコントローラが知っていなければならないのでしょうか。ぼくにはビューテンプレートが必要としているデータの参照はビューテンプレート自身に任せるのが自然な気がします。

もし、データ参照をビューテンプレートに任せられるならば、コントローラの責務は下記のようにすっきりします。

  • リクエストに応じて、モデルを更新する(POST、PUT等の場合)
  • ビューテンプレートを決定するために必要なモデルを参照する
  • ビューテンプレートをレンダリングする

また、データの設定箇所と使用箇所がビューテンプレートのみに集中するので、懸案の問題も解消すると考えられます。

回避策2:サーバサイドをAPIに専念させる

ビューテンプレートからモデルを参照するのに抵抗感を抱く方も多いかもしれません。他の回避策として、サーバサイドをAPIの提供に専念させる方法が考えられます。サーバサイドをM、フロントエンドをVおよびCとするアーキテクチャです。

フロントエンドは門外漢ですが、Vue.jsを少し触った印象では「データの設定箇所と使用箇所が離れる」問題が起こりにくい気がします。仮に離れたとしても、無駄なデータ参照、つまり無駄なAPIコールを放置する状況にはなりにくいはずです。

したがって、この方法でも懸案の問題が軽減できると期待できます。

まとめ

本稿では、Web MVCアーキテクチャに起因する速度低下の問題と、その回避策について検討しました。

1つめの回避策は、コントローラの責務軽減でした。ビューテンプレートが必要とするデータはビューテンプレートだけが知っていればよいという発想の転換です。

2つめの回避策は、サーバサイドをAPIに専念させるアーキテクチャへの移行でした。フロントエンドのほうが問題が起きにくいと考えられます。なお、このアーキテクチャにはテストが書きやすくなる優位性もあります。新規開発では採用を積極的に検討すべきではないでしょうか。

About

Takashi Iwamoto

クラウドサポートアソシエイト at AWSジャパン/リリースチェッカー運営( https://a.noare.net/ )/情報処理技術者試験マニア( https://didit.iwamot.com/iwamot )/JAPAN MENSA会員/投稿は所属先の見解ではありません。文責は個人にあります

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store