RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

VagrantとDockerで「環境に縛られない」開発環境を構築しよう

f:id:rs_tukki:20180509170211p:plain

はじめに

こんにちは。@rs_tukkiです。

先日、このエンジニアブログでY-KanohさんがDockerでの開発環境構築について説明されていましたね。
tech-blog.rakus.co.jp
また、mickey-STRANGEさんはHerokuを使った開発環境の構築を行っていました。
tech-blog.rakus.co.jp

恥ずかしながら、一エンジニアとしてもう1年以上が経過している私ですが、業務以外でガッツリ開発することがあまりありません... 環境の構築についても色々手法があるなー程度で見ていたのですが、
先日Vagrantというツールを使って、「どの」、「誰の」、「どんな」環境でも手軽に開発環境を構築できる手順を学びましたので、今回はそちらについて簡単に記事にしたいと思います。

Vagrant?Docker?

f:id:rs_tukki:20180615103526p:plain

まず初めにVagrantとDockerで開発環境を構築するにあたっては、当然ですがVagrantとDockerがどのようなツールなのか、ということを理解しなければなりません。
正直自分も違いがよくわからないまま触っていたのですが...調べていると面白い例えを見つけました。

Vagrant : 家の内装、全体的な設計 - どんな室内構造か、部屋は何があるのか~その他
Docker : 部屋or(キッチンも可) - 様々な種類がある、場合によってば独特な空間を持ち合わせている

Vagrantは、設計図を基に自分のPCに仮想環境という「家」を作成するためのツールです。
普通に環境を作ろうとした場合は、どういう階層構造にするか、どんなOSを使うのか…等々、都度細かく設定しなければなりませんが、それらの設定をVagrantfileとしてテキスト形式で保存しておけば、それを元にどんなPCからでも同じような仮想環境を作成できるのです。

Dockerに関してはこのブログでも何度か説明されていますが、今回の場合では、Vagrantから作成された「家」の中に作られた部屋*1というイメージで説明します。
それぞれ作られたコンテナの中にはそれぞれ単独で機能する仕組みがあり、例えばそれがWebサーバならWebにアクセスできる仕組みがありますし、DBであればデータを保存する仕組みがあります。また、それぞれのコンテナの間にネットワークという通路を作っておけば、複数のサーバを用いるようなWebアプリケーションも簡単に作成できるというわけです。
そして最も便利なのは、このコンテナ自体もVagrantと同じくDockerfileを作成しておくことによって、細かい設定なしにいきなりコンテナを配置することが出来るという点です。

VagrantとDockerで誰でも使える開発環境を構築してみる

では、VargrantとDockerを用いて、実際に開発環境を作成してみましょう。

必要なツールのインストール

まずは必要なソフトとしてVagrantと、仮想環境を作成する際に必要となるVirtualBoxをインストールします。
Dockerは? となるかもしれませんが、DockerをインストールするのはあくまでVagrantで作った仮想環境に対してなので、現時点でのインストールは不要です。

Vagrant by HashiCorp f:id:rs_tukki:20180615104032p:plain

Oracle VM VirtualBox f:id:rs_tukki:20180615104051p:plain

特にこだわりがなければ、最新版でOKです。
画面の指示に従ってインストールしてください。

Vagrantfileの作成、VMの起動

インストールが完了したら、早速仮想環境の元となるVagrantfileを作ってみましょう。
ちなみに今回の手順は、windowsでの操作を前提にしています。予めご了承くださいm(__)m。

まずはコマンドプロンプトを開き、 適当な作業用フォルダを作成します。

mkdir vm\test
cd vm\test

作成したこのフォルダの中にVagratfileを作成していきます。
本来であればvagrant initコマンドでテンプレートをダウンロードするのですが、今回は手軽に環境構築をお試しするためのVagrantfileをサクッと作っておきました。

Vagrant.configure("2") do |config|
 config.vm.box = "CentOS/7"
 config.vm.network :private_network, ip: "192.168.33.10"
 config.vm.provision "docker"
end

Vagrant.configure("2") do |config|...endで囲まれた範囲が、細かい設定を記述する箇所になります。

  • config.vm.box は仮想環境のOSを表します。今回はCentOSを使用します。
  • config.vm.networkは仮想環境のIPアドレスの指定に使用します。実はこれがかなり重要で、これが設定されていないと仮に仮想環境上でWebサーバを立ち上げても、IPアドレスがないのでPC上からアクセスできません。考えてみれば当然のことなのですが…こんな単純なことに3,4日も気づかずつまづいてしまいました…
  • config.vm.provisionで、環境の作成時にインストールするソフトを指定します。今回は前述の通りdockerを使用するので、今のうちに記述しておきます。

これだけ書いて保存したら、あとは仮想環境を作成して接続するだけです。

vagrant up
vagrant ssh

vagrant upでVagratfileを元に仮想環境を起動し、その環境にvagrant sshで接続します。初回はdockerのインストール等もあるので多少時間がかかりますが、気長に待ちましょう。
しかし、気長といってもここに第二のつまづきポイントがあり、何故かVagrantfileは問題なく作成できているはずなのですが、10分経っても20分経っても起動が完了せず、タイムアウトしてしまうことがあります。
調べたところ、どうやらBIOSの設定が邪魔をしているらしく、この設定をこちょこちょして何とか解決。

Dockerイメージの取得

接続が完了すると、ごく一般的なCentOS上でLinuxコマンドを叩けるようになります。
この環境上に、Dockerを使ってコンテナを作っていくわけですが、それには主に2つの方法があります。

  1. Vagrantfileを作成したのと同じフォルダ内に「Dockerfile」を作成してビルドする
  2. dockerHubという、公式で提供されるコンテナの「カタログ」からDockerfileを借りてくる

細かく設定を行いたい場合は1.で行うのもいいですが、今回はとっかかりなので2.の方法で行きましょう。
プロジェクト管理OSSである「redmine」と、そのデータを格納するための「MySQL」を作成してみます。

docker pull sameersbn/redmine:3.3.1
docker pull sameersbn/mysql:latest

dockerHubからイメージを借りてくる際は、docker pullコマンドを使用します。特に細かい設定は必要なく、dockerHubで提供されているイメージ名とバージョンを指定するだけで落とせるので便利。
こちらも時間がかかるので、気長に待ちましょう。

mkdir -p /srv/docker/redmine/mysql
mkdir -p /srv/docker/redmine/redmine

続いて、MySQLredmineのデータを格納するフォルダを作ります。
本来データはコンテナの中に格納されていますが、このフォルダと紐づけを行う(後述)ことで両者を共有することが出来ます。四次元ポケット

これで、コンテナを動かす準備が完了しました。

実行

少し長いですが、以下2つのコマンドを実行してみてください。

docker run --name=mysql-redmine -d --env='DB_NAME=redmine_production' --env='DB_USER=redmine' --env='DB_PASS=redpass' -v /srv/docker/redmine/mysql:/var/lib/mysql sameersbn/mysql:latest  
docker run --name=redmine -d -p 8080:80 --link=mysql-redmine:mysql -v /srv/docker/redmine/redmine:/home/redmine/data sameersbn/redmine:3.3.1

docker runコマンドでコンテナを動かしています。以下、コマンドのオプションについて解説。

  • --name : 起動するコンテナの名前を定義しています。
  • -d : バックグラウンドで動かします。これがないと、一つ動かしている間は何も操作できなくなってしまいます。
  • --env : コンテナで扱う環境変数を設定します。
  • -v : コンテナの中にあるデータ配置のためのフォルダを、仮想環境の特定のフォルダと紐づけます。
  • -p : 起動したコンテナのポート番号と、自分のPC上で操作する時に指定するポート番号を紐づけます。
  • --link : 他のコンテナを指定することで、そのコンテナと連携することが出来ます。

これでPC側からアクセスができるはずなので、http://192.168.33.10:8080にアクセスします。

f:id:rs_tukki:20180615132038p:plain

Redmine使用者には見慣れたTOPページが表示されました!

おわりに

VagrantとDockerを使って環境を構築するやり方を説明いたしました。
正直なところ、結構噛み砕いて説明したつもりでしたがそれでも大分難しいと思います。なんとたったこれだけのことを調べ始めてから記事にするまで約一ヶ月
ただ、当然若手エンジニアにとっては勉強になりますし、何よりどんな環境でも、同じように環境を構築できるのはとても便利だと思います。ぜひ皆さんも試してみてはいかがでしょうか。

参考

acchi-muite-hoi.hatenablog.com

https://qiita.com/hidekuro/items/fc12344d36d996198e96qiita.com

weblabo.oscasierra.net

qiita.com

www.risewill.co.jp


  • エンジニア中途採用サイト
    ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
    ご興味ありましたら是非ご確認をお願いします。
    20210916153018
    https://career-recruit.rakus.co.jp/career_engineer/

  • カジュアル面談お申込みフォーム
    どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
    以下フォームよりお申込みください。
    forms.gle

  • イベント情報
    会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com

*1:以下、これを「コンテナ」と呼びます

PHP カンファレンス関西 2018 に登壇します&協賛します

はじめまして!普段業務では Java や Swift を書いていますが、本当は(?) PHP が大好きな @kawanamiyuu です。

今日は PHPer な私にとって嬉しいお知らせです!

お知らせ

関西での PHP の一大イベント、PHP カンファレンス関西に弊社のエンジニアが登壇します。

また、株式会社ラクスはシルバースポンサーとしてイベントに協賛します。

2018.kphpug.jp

登壇内容

タイトル

チャットディーラーの高速開発を支える Laravel

概要

チャットディーラー」は株式会社ラクスが提供する、チャットを活用した Web 接客ツール (SaaS) です。

10 年以上 PHP でノンフレームワークで開発・運用されてきた主力サービス(メールディーラー)の開発チームが、新規に姉妹サービス(チャットディーラー)を立ち上げる際に Laravel を選択をしました。

開発期間半年というスピードが求められる中で、チームが Laravel に抱いた理想と現実、また、Laravel (Blade) と Vue.js の組み合わせにより発生した脆弱性への対応など、Laravel での新規サービス立ち上げの経験を具体的にお伝えします。

最後に

当日は弊社のエンジニア数名もイベント本編および懇親会に参加します。セッションや懇親会を通して、弊社のサービス開発やエンジニアリングについてぜひたくさんお話できればと思います!

PostgreSQL10についてまとめてみた

こんにちは。開発エンジニアのd_shr(id:d_shr)です。
前回はNode.jsのことを書いていましたが、今回はPostgreSQLのことを書きます。

前回投稿した記事 tech-blog.rakus.co.jp

はじめに

最近、PostgreSQLについて調査する機会がありました。
主にPostgreSQL9系やPostgreSQL10の変更点を調査しましたが、その中でも最新のPostgreSQL10について書きます。
PostgreSQL10はリリースから半年以上経っており今更ですが、新機能や変更点で気になったものをピックアップしてまとめようと思います。

PostgreSQL10 変更点

  • ロジカルレプリケーション
  • 宣言的テーブルパーティショニング
  • 改善された並列問い合わせ
  • その他

ロジカルレプリケーション

PostgreSQL10でPublish/Subscribeによる論理レプリケーションが実装されました。

PostgreSQL9.6までのレプリケーション

マスタからスタンバイにトランザクションログを転送し適用することでデータの複製を実現していました。
対象はデータベース全体。完全な複製でスタンバイには物理的な変更はできないものでした。

PostgreSQL10 ロジカルレプリケーション

レプリケーション先に対して変更したレプリケーション情報を送付できるようになります。
トランザクションログを「テーブルに〇〇を挿入しました」のように論理的な変更内容として転送することができます。
データベース全体をレプリケーションするのではなく、特定のテーブルの情報やinsertだけをレプリケーションすることが可能です。
レプリケーション情報のやりとりにPublish/Subscribe(出版/購読型)モデルのメッセージ送信を用いています。
複製元でPUBLICATIONを作成し、複製先でSUBSCRIPTIONを作成することでテーブルの同期とレプリケーションが行われます。
INSERT, DELETE, UPDATEには対応していますが、CREATE TABLEなどには対応してません。

所感

柔軟にレプリケーションできるようになったという印象を受けました。
学生の頃にPub/Subモデルのメッセージングを用いた開発をしていたので興味深い内容でした。

パーティショニング

パーティショニングとは、巨大な親テーブルを複数の子テーブルに分割することです。
今までパーティショニングの手順がめんどうだったのですが、CREATE TABLE文でパーティショニングが構築可能になりました。

これまでのパーティショニング

  1. 親テーブルを作成
  2. 親テーブルを継承する子テーブルを作成
  3. CHECK制約を作成
  4. 親テーブルにINSERTトリガを作成 ......

宣言的テーブルパーティショニング

CREATE TABLE文で構築可能 1. 親テーブル作成 PARTITION BY構文 2. 子テーブル作成 PARTITION OF構文

所感

PostgreSQL9.5でもUPSERTが追加されていましたが便利な構文が増えたということで使ってみようかなと思いました。

パラレルクエリの強化

パラレルクエリとは、PostgreSQL9.6で追加された大きなテーブルに対するクエリを並列問合せで実行することです。
パフォーマンスの向上が期待できます。
PostgreSQL9.6で追加されたパラレルクエリ(並列問い合せ)がPostgreSQL10で強化されています。

PostgreSQL9.6で対応していたもの

  • シーケンシャルスキャン
  • 結合(nested loop, hash join)
  • 集約

PostgreSQL10で追加されたもの

  • インデックススキャン(B-tree, index only scan, bitmap heap scan)
  • 結合(merge)
  • 非相関副問合せ

所感

パラレルクエリ自体、バージョンアップで既存のシステムに取り入れるのは難しいのかなという印象を持っています。
これからも並列化はどんどん強化されそうな流れなので、パフォーマンス向上に繋がるなら考慮するべきなのかなと思います。
正しく理解しておきたい機能だと思いました。

その他

PostgreSQL10.3の修正で
他ユーザからの search_path を使った「トロイの木馬」攻撃を防御する PostgreSQL とアプリケーションの設定方法がドキュメントに記載されました。
pg_dump や他のクライアントプログラムで安全でない search_path 設定の使用が回避されました。 *1

PostgreSQLのpublicスキーマの仕様によるもので、悪意あるユーザがpublicスキーマに不正な挙動を行うユーザー関数を仕込んでおくことができます。
他のユーザがその不正なユーザ関数を一般のユーザ関数として実行させることで攻撃(漏えい、改ざんなど)ができてしまう問題がありました。
pg_dump」「pg_upgrade」「vacuumdb」などの管理者ユーザで実行されるアプリケーション関してはsearch_pathからpublicスキーマが取り除かれました。

PostgreSQLの仕様が原因になっていることなのでpublicスキーマの設定を見直す必要もあり 既存のシステムで問題に直面しそうな場合は、運用面のことを考えるのなかなか辛いなという印象を受けました。

まとめ

PostgreSQL10についてまとめました。
個人的に興味深い技術が使われていたものや、構文が追加され便利になったものなどありました。
また、パフォーマンスの向上に繋がることや脆弱性に関連した修正もあり、正しく理解しておかないといけないこともあるなと思いました。

参考

Android Studioで天気情報を表示するアプリを作ってみた

はじめに

kuwa_38です。以前Android Studioを使ってみたので、その続きとして天気情報を表示するアプリを実装してみました。簡単に実装できるかと思いきや、AndroidではAPI接続に非同期処理(AsyncTask)を用いる必要があるらしく苦戦しました。この記事では今回苦戦した非同期処理も含め、天気情報を表示するアプリについて、実装に必要なこと、実装したコードを記載します。

前回実装した処理

今回は下記の実装に付け加える形で実装したため記載しておきます。

Android Studioを使ってHello Worldをやってみた

  • 初期画面の表示
  • ボタンを押すとテキストが変わる

今回実装した処理

  • ボタンを押すとその日の大阪の天気が表示される

利用したAPI

Weather Hacksを利用させて頂きました。GETでエンドポイントにアクセスすることで、パラメータcityで設定した都市の天気をJSONで返してくれます(因みに270000は大阪です)。

補足:jqを活用してAPIレスポンス等から欲しい情報だけを抽出する【初級編】

$ curl -s http://weather.livedoor.com/forecast/webservice/json/v1\?city\=270000 | jq -r

# 結果
{
  "pinpointLocations": [
    {
      "link": "http://weather.livedoor.com/area/forecast/2710000",
      "name": "大阪市"
    },
# ...(中略)
 "link": "http://weather.livedoor.com/area/forecast/270000",
  "forecasts": [
    {
      "dateLabel": "今日",
      "telop": "晴れ",
      "date": "2018-05-27",
      "temperature": {
        "min": null,
        "max": {
          "celsius": "29",
          "fahrenheit": "84.2"
        }
      },

Androidのバージョンに伴う注意点

それでは実装、といきたいところですが、先に私がハマった注意点について述べておきます。

実装概要

コードなどは次の節に記述します。この節では実装すべきことについて大まかに述べます。

※ 今回は実機デバックを対象とします(エミュレータを使用する場合は、エミュレータwifi設定などが必要です)。

ネット接続を許可する

  • AndroidManifest.xmlに下記を追記
<!-- ネット接続を許可する -->
<uses-permission android:name="android.permission.INTERNET" />

ボタンを押すと特定の処理を実行する

  • 前回の記事を参照ください

APIサーバに接続する

  • 注意で述べたようにメインスレッドでは接続できませんので、実行用のクラスを作成してあげます

    • 参考:AsyncTaskを使った非同期処理のきほん

      1. AsyncTaskを継承するクラス(今回はAsyncHttpRequestというクラス名にしました)を作成する
      2. 作成したクラス内にdoInBackground(非同期で行いたい処理を記述する)メソッドを実装する
      3. メインスレッド(MainActivity.java)で1のクラスをインスタンス化し、executeメソッドを呼び出す
        doInBackgroundが呼び出される

受け取ったJSONを加工する

  • 受け取った文字列をJSONObjectでパースし、天気情報を取り出します

天気情報を表示する

  • AsyncTaskを継承するクラスでonPostExecute(非同期処理が終わった後に実行される)メソッドを実装し、メインスレッドのラベルを変更する

実装例

下記にMainActivity.javaAsyncHttpRequest.java(AsyncTaskを継承するクラス)を載せますので、実装してみたい方は参考にして下さい。

AndroidManifest.xmlは1行追記したのみですので載せていません

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * トップ画面を制御するActivityクラス.
 */
public class MainActivity extends AppCompatActivity {

    /**
     * 画面を表示する.
     *  note:デフォルトで実装されている
     * @param savedInstanceState savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    }

    /**
     * テキストラベルを変更する.
     * @param view view
     */
    public void changeTextView(View view) {
        // 非同期処理(AsyncHttpRequest#doInBackground())を呼び出す
        try {
            new AsyncHttpRequest(this).execute(new URL("http://weather.livedoor.com/forecast/webservice/json/v1?city=270000"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

AsyncHttpRequest

import android.app.Activity;
import android.os.AsyncTask;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 非同期処理を行うクラス.
 */
public final class AsyncHttpRequest extends AsyncTask<URL, Void, String> {
    private int TODAY_FORCAST_INDEX = 0;
    private Activity mainActivity;

    public AsyncHttpRequest(Activity activity) {
        // 呼び出し元のアクティビティ
        this.mainActivity = activity;
    }

    /**
     * 非同期処理で天気情報を取得する.
     * @param urls 接続先のURL
     * @return 取得した天気情報
     */
    @Override
    protected String doInBackground(URL... urls) {

        final URL url = urls[0];
        HttpURLConnection con = null;

        try {
            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            // リダイレクトを自動で許可しない設定
            con.setInstanceFollowRedirects(false);
            con.connect();

            final int statusCode = con.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK) {
                System.err.println("正常に接続できていません。statusCode:" + statusCode);
                return null;
            }

            // レスポンス(JSON文字列)を読み込む準備
            final InputStream in = con.getInputStream();
            String encoding = con.getContentEncoding();
            if(null == encoding){
                encoding = "UTF-8";
            }
            final InputStreamReader inReader = new InputStreamReader(in, encoding);
            final BufferedReader bufReader = new BufferedReader(inReader);
            StringBuilder response = new StringBuilder();
            String line = null;
            // 1行ずつ読み込む
            while((line = bufReader.readLine()) != null) {
                response.append(line);
            }
            bufReader.close();
            inReader.close();
            in.close();

            // 受け取ったJSON文字列をパース
            JSONObject jsonObject = new JSONObject(response.toString());
            JSONObject todayForcasts = jsonObject.getJSONArray("forecasts").getJSONObject(TODAY_FORCAST_INDEX);

            return todayForcasts.getString("dateLabel") + "の天気は " + todayForcasts.getString("telop");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }
    }

    /**
     * 非同期処理が終わった後の処理.
     * @param result 非同期処理の結果得られる文字列
     */
    @Override
    protected void onPostExecute(String result) {
        TextView tv = mainActivity.findViewById(R.id.messageTextView);
        tv.setText(result);
    }
}

おわりに

本記事ではAndroid Studioを使い、天気情報を表示するAndroidアプリの実装方法を紹介しました。まだまだ実用には遠いクオリティですが、非同期処理やjqコマンドなど知らなかったことを学ぶいい機会になりました。自分の学習目的で始めた部分が大きいですが、Androidアプリ開発の初心者や非同期処理の実装で困っている方の手助けになれば幸いです。


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

メンバー同士でお互いの価値観を可視化するムービングモチベーターズを新チーム結成時に使ってみよう

id:radiocat です。今年度はビアバッシュ推進委員から一歩身を引いてアドバイザー役になりました。

このブログでも何度か紹介している ビアバッシュ ですが、このたび新しい運営メンバーが選抜されて、先日キックオフを行いました。同じ会社の社員とはいえ価値観は人によって違うため、ビアバッシュをどのように推進していきたいか、思い描くイメージはそれぞれ違っているものです。はじめはお互いに手探り状態で意見をすり合わせながらやりたいことをまとめていくことになりますが、そんな時に役に立つ価値観を可視化する手法が「ムービングモチベーターズ」です。

ムービングモチベーターズとは

チームのメンバー同士でお互いの価値観を共有するためのワークショップです。手法の成り立ちや考案者については後述します。

10種類のカード

モチベーションの源泉となるキーワードが書かれた10種類のカードがあります。このカードを自分が価値を感じる順番に並べ替えて共有します。

f:id:radiocat:20180523000145p:plain:w500

やってみよう

テーマの認識合わせ

まずは何に対しての価値観について考えるのか全員でしっかり認識合わせをします。今回は「開発部のビアバッシュを推進していくうえで価値が高いと感じるキーワード」としました。

実践タイム

5分~10分程度で時間を決めて並び替えます。あまり深く考えず直感的に並び替えましょう。

f:id:radiocat:20180523000251p:plain:w500

共有タイム

1人ずつ結果をチームに共有します。なぜそのキーワードを選んだのか理由も説明して価値観の理解を深めましょう。

f:id:radiocat:20180523005955p:plain:w500

今回はメンバーそれぞれが選んだトップ3を発表しました。このチームは「関係性」と「受容」を選んだメンバーが多いとか「名誉」や「権力」は誰も選ばなかったといったコミュニケーションを取って価値観を共有しました。

まとめ

ビアバッシュのような社内イベントの運営ではルールや手順が細かく決まっているわけではなく、むしろ集まったメンバーの個性や考え方に委ねられている面もあるので、このように手軽に価値観を共有できる手法はとても有効です。

また、私の所属する開発チームでは毎月1回全員でこれを行って前月からのメンバーの価値観の変化も追いかけています。「最近新しい技術に取り組んでいるので好奇心を選んだ人が増えた」とか、「難しい課題に取り組んでいるのでゴールの重要性を感じている」といった、チームの状況の変化に応じたメンバー同士の価値観の変化にも気づけます。

最後に、実践しするうえでのポイントを3つ紹介します。

気軽に並べる

結局どれも大事な言葉なのです。時間をかけずにその瞬間の価値観をさらけ出しましょう。もちろん隣の人のカードを見てはいけません。

言葉の捉え方も共有する

やってみると言葉の捉え方が人によって違うことにも気づきます。元々英語で作られたカードなので、「受容」や「熟達」など、日本語だと少しイメージしにくい言葉もあります。しかし気にする必要はありません。「自分はこう思ってこれを選んだ」という考えを共有することが大事です。どうしても気になる場合はみんながどういう意味で捉えているか聞いてみましょう。

楽しむ

お互いに価値観を共有しあうので、堅苦しい雰囲気だと発言しづらくなります。無言でカードを並べるのではなく、楽しくワイガヤしましょう。

参考:Management 3.0

ムービングモチベーターズはManagement 3.0のプラクティスの1つです。

management30.com

Management 3.0は 公式サイト で以下のように説明されています。

オランダ出身のヨーガン アペロ(Jurgen Appelo)の世界80ヶ国で展開している新しいイノベーションとリーダーシップそしてマネジメント運動です。

近年マネジメントの領域で注目されている自己組織化や心理的安全性などについても言及されており、アジャイル開発の現場でも手法が使われているようです。

ARKit + Unityでアプリ開発

こんにちはsts-250rrです。

今回も前回の記事に引き続きAR技術の紹介になります。

tech-blog.rakus.co.jp

前回は簡単にARを体験する。まででしたので今回はSoftware DesignのコラムにあったARアプリARKittenを作ってみました。

gihyo.jp

ちなみにGithubリポジトリでサンプルを公開してくださっていますので、こちらでまず試してみるのも良いかもですね。

では、やっていきましょう。

猫、ARに立つ

前回はARの世界で平面を検出し、キューブを設置するところまででしたが、それではあまりに味気ないので猫を配置することにします。 ※AssetStoreからARKitをインポートする部分は割愛します。

UnityのAssetStoreでは、3Dのモデルデータを購入することもできます。
ここから猫のモデルを取得していきたいところですが、残念なことにARKittenで使用する猫のモデルは作成者の諸事情により、AssetStoreからダウンロードできなくなってしまいました。
現在は上記のGithubからモデルデータを取得してくるしかないようです。
Kittenディレクトリをプロジェクト名/Assets配下に格納しておきましょう。

単純に猫を平面に追加するだけでは、拡張現実らしくなりません。
それはなぜか、ズバリ影がないからです。

そこで今回作成するアプリではUnityARShadowsというサンプルを元に作成していきます。
このサンプルであれば平面を検出した部分に3Dモデルの影を落とすことができます。

UnityARShadowsにはCubeの代わりにHitPlayerが存在しています。
f:id:sts-250rr:20180519210601p:plain これをAssets/Kitten/Prefabs/KittenNPCに置き換えます。 f:id:sts-250rr:20180519210723p:plain

これだけではiOSの画面をタップしても猫が平面に配置できないのでスクリプトを組み込んでいきます。

KittenNPCを選択しインスペクターウィンドウ(右側に表示されている設定窓)の設定を以下のようにします。 f:id:sts-250rr:20180519211418p:plain

ここで一度ビルドして、画面をタップして見て猫を配置してみます。
猫に影がついていたり、アニメーションが定義されているので、まるで猫がそこにいるようです。 f:id:sts-250rr:20180520172607p:plain

カメラを向かぬ猫

f:id:sts-250rr:20180520172401p:plain

単純に猫を配置するだけでは、場所によってはそっぽを向かれてしまいます。
猫を配置した時にいつもこちら側(カメラ)を向いてくれるようにしつけスクリプトを追加していきます。
ここでは猫がカメラを向いてくれる時の処理の流れを解説します。

  1. 猫位置の取得
    タップで配置した猫の位置を取得します。
    このままでは猫は初期の向きを向いてしまいます。
    3Dグラフィックスの世界では向き(回転)という情報はクオータニオンと呼ばれるもので保持されています。

  2. カメラ位置の取得
    猫とカメラの位置(座標)を比較することで、猫がどの方向を向けば良いのかがわかるようになります。

  3. カメラの方に向かせる 猫とカメラの位置の差から、猫がどれだけ回転すれば良いのかを計算します。
    この計算は3Dを扱うライブラリであれば、大抵3次元ベクトルを与えてやれば計算してくれる関数があります。
    ARKitであれば、QuaternionクラスのLookRotationクラスがその一つに該当します。
    スクリプトの内容はサンプルコードを眺めてみてください。

スクリプトが完成したら再びビルドしましょう。
そこには従順にこちらを向いている猫が佇んでいるはずです。

f:id:sts-250rr:20180520172311p:plain

まとめ

今回は前回ご紹介したARKitのサンプルプログラムを作ってみました。 猫が配置され、それを眺めるまでしかできませんが、本来そこにいないはずの猫が画面を通して存在している感覚はまさしく拡張現実です。

次回も引き続きARKitネタをお送りしたいと思います。
お楽しみに、

実録ビルドできない事件簿

iPhoneiOSをアップデートしたばかりにビルドできなくなってしまった・・・・ f:id:sts-250rr:20180520140348p:plain

エラー内容を見てみると、 「iOS11.3のデバイスサポートファイルがない」ということだそうです。

みなさん結構起きてしまっているようで、解決策を調べてみたらすぐに出てきました。 今回は以下の記事を参考にさせていただきました。

iOSをアップデートしたために実機でビルドができない - Qiita

Copyright © RAKUS Co., Ltd. All rights reserved.