2018年12月11日火曜日
Active Storage移行記:データ移行編
こんにちは、あさのです。
前にActive Storageの記事を書きましたが、今回もそのネタで行こうと思います。
Active Storage移行記:バリデーション編|sitateru tech blog
今回は、Paperclip管理のデータをActive Storage管理に移行したときのお話です。
データ構造
Paperclipではファイルのデータは各モデルのカラムに保存されています。
userクラスのiconというファイルであれば、userテーブルに以下のようなカラムがあります。
t.string "icon_file_name", comment: "ファイル名"
t.string "icon_content_type", comment: "ファイルのcontent type"
t.integer "icon_file_size", comment: "ファイルサイズ"
t.datetime "icon_updated_at", comment: "ファイル更新日時"
対してActive Storageでは全クラスの全ファイルをまとめて2つのテーブルで管理します。
create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
たとえば、
- userクラスのicon
- user.id=15
- ファイル名 prof.jpg
というファイルだと以下のようなレコードになります。
2つのテーブルは blob_id
で関連づけられるんですね。
id name record_type record_id blob_id created_at
15 icon User 3 16 2017-12-28 19:23:03
id key filename content_type metadata byte_size checksum created_at
16 3e0ca647-18e3-43ee-85c4-4de552bac46f prof.jpg image/jpeg {} 44202 isFyYNJIs/6pyptfRUMUlA== 2017-12-28 19:23:03
データ移行
さて、それぞれのデータ構造がわかったのでマイグレーションをしていきます。
このあたりの記事を参考にさせてもらい、rakeタスクで実装しました。
namespace :import_to_active_storage do
desc 'Import to ActiveStorage'
task run_all: :environment do
models = ActiveRecord::Base.descendants.reject(&:abstract_class?)
import_data(models)
end
private
def import_data(models)
conn = ActiveRecord::Base.connection
models.each do |model|
attachments = model.column_names.map do |c|
c =~ /(.+)_file_name$/ && Regexp.last_match(1)
end.compact
model.find_each do |instance|
attachments.each do |attachment|
puts "Process #{model.name}/#{instance.id}"
next unless instance.send("#{attachment}?")
next if conn.select_one("SELECT `id` FROM active_storage_attachments WHERE `record_type` = '#{model.name}' AND `record_id` = #{instance.id}").present?
puts "Migrate #{instance.send(attachment.to_s)}"
ActiveRecord::Base.transaction do
execute_statement(conn, model, instance, attachment)
end
end
end
end
end
def execute_statement(connection, model, instance, attachment)
active_storage_blob_statement(connection).execute(
key,
instance.send("#{attachment}_file_name"),
instance.send("#{attachment}_content_type"),
instance.send("#{attachment}_file_size"),
checksum(instance.send(attachment)),
instance.updated_at.strftime('%Y-%m-%d %H:%M:%S')
)
active_storage_attachment_statement(connection).execute(
attachment,
model.name,
instance.id,
instance.updated_at.strftime('%Y-%m-%d %H:%M:%S')
)
end
def active_storage_blob_statement(connection)
connection.raw_connection.prepare(<<-SQL)
INSERT INTO active_storage_blobs (
`key`, `filename`, `content_type`, `metadata`, `byte_size`, `checksum`, `created_at`
) VALUES (?, ?, ?, '{}', ?, ?, ?)
SQL
end
def active_storage_attachment_statement(connection)
connection.raw_connection.prepare(<<-SQL)
INSERT INTO active_storage_attachments (
`name`, `record_type`, `record_id`, `blob_id`, `created_at`
) VALUES (?, ?, ?, LAST_INSERT_ID(), ?)
SQL
end
def key
SecureRandom.uuid
end
def checksum(image)
uri = URI.parse("https:#{image.url}")
body = Net::HTTP.get(uri)
Digest::MD5.base64digest(body)
end
end
そこそこ長いですが、結局は各モデルの各ファイルごとにPaperclipのカラム情報とファイルのハッシュ値を取り、
Active Storageのテーブルに入れるという繰り返しです。
なお、各モデルの実装をActive Storage用に書き換えた後ではこのタスクは動かないので、
Paperclip時に実行する必要があります。
実際にやったところ数万件のデータがあったために5~6時間かかるという大引っ越しになってしましましたが、
なんとか乗り切りました。
ということで今回はActive Storageのデータ移行について書きました。
まだもう少しActive Storageネタで書けるかもしれません。
それでは。
2018年12月10日月曜日
縫製工場の類似度算出を深層学習のモデルでやってみた
シタテル株式会社CTOの和泉です。
Follow @shinobu_shiva
今回は研究開発的に、「縫製工場の類似度算出を深層学習のモデルでやってみた」について書きます。
まず初めに結果から。
['loss', 'acc']
[273999.25, 0.695652186870575]
69.6% 成功?なにが?って話ですよね。
結果的には全然精度出ませんでした。まぁ、のべ1週間ぐらいでやってみた感じですし、サーベイも全然できてないので結果出るわけないのですが。
せっかくやってみたのでブログに恥を晒しておきます。
その道の専門の方にはお目汚しかと思いますがご容赦ください。
やりたかったこと
弊社コンシェルジュが手動で類似分類(グループ化)した縫製工場 のデータを教師データとして学習し、同様の類似分類を行える学習済みモデルを作成する。類似分類ができれば、これまでのアイテム作成履歴から代替となる工場の提案ができる。かも。
希望的仮定
類似度の判定に用いられる特徴はある程度絞られているのではないかと想定し、学習によって効果の高い特徴が反映されるモデルが作成されれば、人の判断に近づけるのではないか。結果
教師データに対しては98.8%の正答率に達したが、テストデータについては69.6%にとどまった。残念ながら実用に足るような結果は得られなかった。図1:教師データに対する推論結果のプロット(青が教師データ、点線先のオレンジが対応する推測結果)
図2:テストデータに対する推論結果のプロット(青が教師データ、点線先のオレンジが対応する推測結果)
図3:学習の経過
何をやったのか
データベースに保有する123の縫製工場を2次元平面上で類似しているものを近くに配置するように、弊社コンシェルジュに依頼して教師データを作成。(図1の青い点が各工場を表す)この際、「類似している=あるアイテムを相談するときに変わりに相談できる工場であるか」とした。作成された教師データが含む縫製工場データは114件。9件は情報不足により配置できなかった。作成した教師データは各工場ごとに位置ベクトルが与えられた状態になっている。この位置ベクトルを各工場がもつ特徴ベクトル(全313次元のうち、名前などヒューリスティックに取り除けるものを除いて、108次元)から求めるモデルを学習により獲得した。
DNNモデルや条件などのメモ
model = Sequential()
model.add(Dense(DIM, activation='relu', input_dim=DIM))
model.add(Dropout(0.25))
model.add(Dense(DIM*2, activation='relu'))
model.add(Dense(2))
model.compile(optimizer='adam',
loss='mean_squared_error',
metrics=['accuracy'])
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 108) 11772
_________________________________________________________________
dropout_1 (Dropout) (None, 108) 0
_________________________________________________________________
dense_2 (Dense) (None, 216) 23544
_________________________________________________________________
dense_3 (Dense) (None, 2) 434
=================================================================
Total params: 35,750
Trainable params: 35,750
Non-trainable params: 0
_________________________________________________________________
history = model.fit(X_train, Y_train,
batch_size=50,
epochs=5000,
validation_split=0.1,
verbose=1)
考察
代替工場を考える際には、アイテムによって代替として扱うものが変わることが想定されるため、全体を2次元平面上に次元縮退してプロットすることが難しいであろうことは当初予定していたとおりであった。今回は、比較的手軽に作成できる教師データを用いて試してみたが、十分な結果は得られなかった。
統計によるリコメンドではデータの量が問題になるが、良質で量のあるデータが十分にないのが現状。シタテルの取扱量が増えることによりある程度のデータは蓄積されていくが、滝行との連携も含めて扱えるデータ量を増やしていくことが必要である。
工場データベースについて
シタテルは500を超える縫製工場やサプライヤーと連携して衣服づくりサービスを提供しています。それぞれの縫製工場に対して、設備や人員、アイテムごとの金額感、繁閑の目安など300を超える情報をデータベースに格納しています。
工場を検索して絞り込み
(工場名や取引先は非公開のため消してあります)
いくつかの工場を並べて比較
弊社コンシェルジュはこれらのデータを使ってご相談いただいたアイテムごとに最適な工場に問い合わせを行います。
2018年12月7日金曜日
CircleCIでAWS ECSに自動デプロイする(おまけで環境面の切り替えも)
こんにちは、シタテルの茨木です。
今回はCircleCIでDockerをビルドし、そのままAWS ECR/ECSにデプロイする為の設定例を紹介します。
Nuxt.jsアプリ用に作ったものですが、言語やAPサーバが違っても共通の部分がほとんどです。
PRマージからの自動デプロイ、いいですよね。
https://circleci.com/docs/2.0/ecs-ecr/
https://github.com/CircleCI-Public/circleci-demo-aws-ecs-ecr
基本的にはCircleCI公式ガイドの上記リンクを参考にしていますが、元ネタはterraform前提だったりでなかなか大仰です。(下記に説明漏れがあったら原典を見てください…)
今回紹介するのはリンク先のスクリプト類を簡素化し、少し機能を追加(リポジトリ名からデプロイ先の環境面を切り替えできるように)したものです。
以下で省略しているけれど必要なモノ
- ECS/ECRの設定
これだけで別の記事が書けてしまうので割愛します
ecsTaskExecutionRoleの割り当てとか忘れがちですかね
- githubリポジトリ
言わずもがな。CircleCIとの接続設定はされているものとします
- Dockerfile
リポジトリのルートに。Dockerfileの書き方は解説しません
- requirements.txt
リポジトリのルートに。awscliを使えるようにします
https://github.com/CircleCI-Public/circleci-demo-aws-ecs-ecr/blob/master/requirements.txt
- CircleCIの環境変数設定
github上にaccess_keyを晒さなくていいように、入れておきます
https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project
この手順で設定した環境変数はCircleCIのジョブから参照できます
.circleci/config.yml:build
version: 2
jobs:
~省略~
build:
docker:
- image: circleci/node:10-stretch
steps:
- checkout
- setup_remote_docker
- run:
name: Setup common environment variables
command: |
echo 'export ECR_REPOSITORY_NAME="YOUR-ECR-REPO-NAME"' >> $BASH_ENV
echo 'export FULL_IMAGE_NAME="${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${ECR=REPOSITORY_NAME}:${CIRCLE_SHA1}"' >> $BASH_ENV
- run:
name: Build image
command: |
docker build -t $FULL_IMAGE_NAME .
- run:
name: Save image to an archive
command: |
mkdir docker-image
docker save -o docker-image/image.tar $FULL_IMAGE_NAME
- persist_to_workspace:
root: .
paths:
- docker-image
~省略~
さっそくですがビルドジョブです。
- YOUR-HOGEHOGE箇所はご自身のECS/ECRの設定に合わせて置き換えてください
- image: circleci/node:10-stretch
node:10を使っていますが、これはビルドする対象がNuxt.jsアプリだからですね。Dockerビルド時に必要なモノに合わせて修正してください
.circleci/config.yml:deploy
~省略~
deploy:
docker:
- image: circleci/python:3.6.1
environment:
AWS_DEFAULT_OUTPUT: json
steps:
- checkout
- setup_remote_docker
- attach_workspace:
at: workspace
- restore_cache:
key: v1-{{ checksum "requirements.txt" }}
- run:
name: Install awscli
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
- save_cache:
key: v1-{{ checksum "requirements.txt" }}
paths:
- "venv"
- run:
name: Load image
command: |
docker load --input workspace/docker-image/image.tar
- run:
name: Setup target environment variables
command: |
echo 'export TARGET=`echo $CIRCLE_BRANCH | sed -e s/develop.*/dev/ -e s/release.*/stg/ -e s/master/prd/`' >> $BASH_ENV
source $BASH_ENV
- run:
name: Setup common environment variables
command: |
echo 'export ECR_REPOSITORY_NAME="YOUR-ECR-REPO-NAME"' >> $BASH_ENV
echo 'export ECS_CLUSTER_NAME="YOUR-ECS-CULSTER-NAME-PREFIX${TARGET}"' >> $BASH_ENV
echo 'export ECS_SERVICE_NAME="YOUR-ECS-SERVICE-NAME-PREFIX${TARGET}"' >> $BASH_ENV
- run:
name: Push image
command: |
. venv/bin/activate
eval $(aws ecr get-login --region ap-northeast-1 --no-include-email)
docker push $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_REPOSITORY_NAME:$CIRCLE_SHA1
- run:
name: Deploy
command: |
. venv/bin/activate
export AWS_DEFAULT_REGION="ap-northeast-1"
export ECS_TASK_FAMILY_NAME="YOUR-ECS-TASK-NAME-PREFIX${TARGET}"
export ECS_CONTAINER_DEFINITION_NAME="YOUR-ECS-CONTAINER-DEF-NAME-PREFIX${TARGET}"
export EXECUTION_ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/ecsTaskExecutionRole"
bash ./deploy.sh
~省略~
デプロイジョブです。
- ブランチ名から環境名へ
echo 'export TARGET=`echo $CIRCLE_BRANCH | sed -e s/develop.*/dev/ -e s/release.*/stg/ -e s/master/prd/`' >> $BASH_ENV
ブランチ名に応じた値(developブランチなら"dev")を環境変数に入れています。これをsuffixとして使い、デプロイ先のクラスタ名等に反映しています
- YOUR-HOGEHOGE箇所はご自身のECS/ECRの設定に合わせて置き換えてください
余談ですが、ECSはクラスタ・サービス・タスク・タスク定義といろいろ設定しないといけないのですが、なかなか直感的にわかりにくくてイマイチな印象です
.circleci/config.yml:workflows
~省略~
workflows:
version: 2
build-deploy:
jobs:
- build:
filters:
branches:
only:
- develop
- /release\/.*/
- master
- deploy:
requires:
- build
filters:
branches:
only:
- develop
- /release\/.*/
- master
この辺はよしなに
deploy.sh
#!/usr/bin/env bash
set -eo pipefail
# more bash-friendly output for jq
JQ="jq --raw-output --exit-status"
deploy_cluster() {
make_task_def
register_definition
if [[ $(aws ecs update-service --cluster $ECS_CLUSTER_NAME --service $ECS_SERVICE_NAME --task-definition $revision | \
$JQ '.service.taskDefinition') != $revision ]]; then
echo "Error updating service."
return 1
fi
# wait for older revisions to disappear
# not really necessary, but nice for demos
for attempt in {1..30}; do
if stale=$(aws ecs describe-services --cluster $ECS_CLUSTER_NAME --services $ECS_SERVICE_NAME | \
$JQ ".services[0].deployments | .[] | select(.taskDefinition != \"$revision\") | .taskDefinition"); then
echo "Waiting for stale deployment(s):"
echo "$stale"
sleep 30
else
echo "Deployed!"
return 0
fi
done
echo "Service update took too long - please check the status of the deployment on the AWS ECS console"
return 1
}
make_task_def() {
task_template='[
{
"name": "%s",
"image": "%s.dkr.ecr.%s.amazonaws.com/%s:%s",
"essential": true,
"portMappings": [
{
"containerPort": 80
}
],
"environment": [
{
"name": "TARGET",
"value": "%s"
}
]
}
]'
task_def=$(printf "$task_template" $ECS_CONTAINER_DEFINITION_NAME $AWS_ACCOUNT_ID $AWS_DEFAULT_REGION $ECR_REPOSITORY_NAME $CIRCLE_SHA1 $TARGET)
}
register_definition() {
if revision=$(aws ecs register-task-definition --requires-compatibilities FARGATE --cpu 256 --memory 1024 --network-mode awsvpc --execution-role-arn $EXECUTION_ROLE_ARN --container-definitions "$task_def" --family $ECS_TASK_FAMILY_NAME | $JQ '.taskDefinition.taskDefinitionArn'); then
echo "New deployment: $revision"
else
echo "Failed to register task definition"
return 1
fi
}
deploy_cluster
デプロイジョブから呼び出すスクリプトです。
task_templateの内容を色々弄るとカスタマイズできます
設定可能な項目はこちら
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/create-task-definition.html
ここでは、environmentで環境変数TARGETを設定しています
ECSがdocker runする際に引数として付与され、docker内のアプリから環境変数として参照可能になります
実際には、nuxt.config.js内でTARGETを参照し、APIサーバの向け先を切り替えたり等しています
以上、ご参考になれば幸いです。
2018年12月6日木曜日
チームでのUI/UX改善のための取り組み「マイオペ触る会」のご紹介
こんにちは!
シタテルでエンジニアをしている建山です。
主に工場向けのマイオペというシステムの開発を行っています。
シタテルでは、チームがプロダクトなどでわかれており、今担当しているマイオペチームでは、
デザイナー、エンジニアが一緒になって開発をしています。
その中で、「マイオペ触る会」というのを隔週で行っています。
その取組の目的や方法をご紹介します。
マイオペ触る会って
普段開発しているプロダクトを、開発しているメンバー全員でユーザーの気持ちになって操作する時間を設けています。
目的としては、以下のような感じです。
・ユーザーの目線に改めてなって自分たちが作っているものを使うことで、気づいてなかったユーザーの課題やUI/UXの問題を洗い出す
・ユーザー目線を忘れないようにする意識付け
方法として、それぞれ行いたい時に非同期でやろうとしたのですが、開発の忙しさに追われてやらないことがあったため、みんなで同じ時間に集まって行うようにしています。
マイオペチームは拠点がバラバラなため、触る会の際は、zoomを繋ぎっぱなしにして話しながら進めています。
以下のような、googleスプレッドシートを活用し、どういうストーリーで操作したかの簡単な説明、画面ごとの問題や気になったことを各自書いていきます。
終わった後はイシュー化
終わった後はgithubでイシュー化して、議論検討したり、ユーザーインタビューしてみたり、開発計画に組み込んで進めたりしていきます。
やっていてよかったこと
目的にも書いていますが、開発しながら毎日自分たちのつくっているものには触れ合っていますが、あらためて、ユーザーの気持ちになっと触る時間を設けると、また初心に帰ることができるし、新鮮な気持ちでユーザーの課題が見えることもあります。
また、触る会をきっかけに チーム全体でもユーザー目線で活発な議論が発生していると感じていてやっていてよかったと思う点ばかりです。
まとめ
今回は、チームで取り組んでいる「触る会」をご紹介しました。チームでは他にも、いろいろな取組をしていますので、また追々紹介したいと思います。
チームや状況に合わせて、引き続きいいやり方を模索しながら改善していきたいと思います!
優秀なUI/UXデザイナーがチームにいますので、きっと記事を書いてくれると思います。笑
2018年12月5日水曜日
Krispで雑音に気を取られずにWeb会議
こんにちは!
シタテル株式会社エンジニアのいしづかです。
シタテルは熊本と東京の2つ拠点があり、エンジニアもそれぞれいます。
また、週に2回はリモートワークも認められているため、物理的に人が集まらないことは、もはや日常です。
毎日の朝会や、様々なミーティングなどがオンラインビデオチャットで行われています。
シタテルではZoomというソフトを使っていますが、ここで悩まされるのが周囲の雑音です。
「発言時以外はマイクをミュートにする」というルールはあるものの、電話が鳴るとそっちの音が勝ってしまうこともしばしば。。。
「あ、ここのところなんですけd プルルルルルルル!!!」
ツライ。
そんな中、Krispというノイズキャンセリングのソフトがイイ!と聞いたので使ってみました。
結論から申し上げますと、なかなかよかったです。
Krisp
Krispは元TwilioのエンジニアだったDavitさんらが開発したアプリで、周囲のノイズ音を除去してくれます。ディープラーニングを用いて、ノイズ音をリアルタイムに除去しているそうです。
動画が出てましたが、パトカーのサイレンが鳴り響いていてもクリアに通話できているというスゴさ。
これはWeb会議の救世主ではなかろうか・・・!
残念ながら今現在ではmac版しか無いので、それ以外のOSユーザーはこのオドロキを体験頂けませんが、シタテルの開発陣は全員mac利用者なので問題ナシです。
Let's install !!
インストールはこちらのページより。
今ならDownload for freeなので無料で使えます。
pkgファイルが落ちてくるのでインストールします。
↑アイコンが表示されるので、SPEAK without noise をONにすれば準備完了です。
↑これはZoomの設定画面ですが、マイクとスピーカーにKrispがいるので、それを指定します。
これで準備完了です。
使ってみる
東京のエンジニアとZoomをつないだ状態で、以下のことをやってみました。
- わざわざ談笑しているところにmacbook片手に近づく
- 目の前で蛇口をひねって水をジャーっと出してみる
- 会社の電話を鳴らしてもらう
結果は良好でした!!
すぐ周りは談笑しているのに「その部屋に他には誰もいないと思える」ほど静かだったそうです。
蛇口の水音、全然しない、と!!マジですか!!
もう手放せません。
まとめ
Web会議は環境がものすごく重要です。雑音が多くて声が聞き取れないとかなりのストレスになります。
Krisp入れたばっかりなのでまだまだ試さないといけないですが、みんな入れてこそ価値が発揮されるので、これから布教活動をしていこうと思います。
他にどのような工夫ができるか
快適なミーティングをやるために、飽くなき探究を続けていきます。
2018年12月4日火曜日
シタテルで使っているデザインツールのご紹介
こんにちは!シタテル株式会社UI/UXデザイナーの田仲です。
今回はシタテルのデザイナーが使っている、デザインツールをご紹介します。
Sketch
デザインの作成はSketchをメインで使っています。去年まではPhotoshopがメインでしたが、下記で紹介するAbstract導入をきっかけに、Sketchをメインにしました。
Photoshopに比べると、とても軽いのでストレスなく使える点が気に入っています。アップデートが頻繁にあるため、その度に少し迷うこともありますが、アップデートでの変化を発見することが楽しみのひとつでもあります。
便利なプラグインもたくさん出てきているので、個人で試してチームにも導入していけたらと考えています。
Abstract
Sketchのバージョン管理ツールです。同じSketchファイルを複数のデザイナーが修正したり、サポートしあえるようにしています。
先日SketchのバージョンにAbstractが追いついていないことがあり、気がつかずSketchのバージョンを上げた時にSyncできない問題が起きてしまいました。(その時はSketchダウングレードして解決しました。)気軽にSketchのバージョンを上げられないという点は、微妙だなと感じています。
現在は複数人で作業しているプロジェクトは1つしかいない状態なので、もう少し共同で作業するプロジェクトを増やし、お互いの知見を増やすことにも活かしていけるような使い方をしていきたいなと考えています。
Adobe Creative Cloud
PhotoshopやIllustratorは、Sketchでは作業しにくい写真の加工、パネルや印刷物の作成を中心に使っています。
他にも、XDは気になる機能が次々に出ており、将来的にツールをAdobeに集約できると、データの互換性やコストなどの面でメリットがあると考えています。まだAbstractとSketchの方が便利だという結論から移行は考えていませんが、最新動向には日々注目しています。
Zeplin
デザイナーが作ったデザインをエンジニア確認できるツールです。開発内でのレビュー、最終的にエンジニアが実装するときに使っています。
コメントができる点はinVisionと変わりがないのですが、サイズやカラーコードがわかるだけでなく、アイコンのダウンロードなどもできるので、デザイナーとエンジニアのやりとりを減らすことができています。今後はよりエンジニアとどうやったらもっと便利になるかを話し合い、ガイドラインなどとしても活用できるようにしていけたらと考えています。
InVision
プロトタイピング・レビューに使用しています。
InVisionはコードなどの情報がないので、デザイナーとエンジニア以外の生産や営業などのメンバーがレビューに参加する際に使っています。シタテルでは開発以外の職種のメンバーともデザインの段階から頻繁に意見を交わしています。これからも部署問わず、よりよいプロダクトをつくり上げるためにコミュニケーションを活発にしていけたらと思います。
以上、シタテルで使っているデザインツールのご紹介でした。
シタテルでは、積極的に新しいデザインツールや機能を試し、今よりよりコミュニケーションしやすい&デザインしやすい環境となるものがあれば乗り換えていきたいと考えています
2018年12月3日月曜日
HDEさんのオフィスに遊びに行ってみた!
こんにちは!
シタテル株式会社CTOの和泉です。
HDEさんのオフィスに遊びに行ってみた!
HDEはクラウドセキュリティ、メールのSaaSサービスを展開している企業で、創業から20年以上の歴史があります。
先日参加した、SaaSカンファレンスで汾陽(かわみなみ)さんにお会いして、遊びに行かせてください!のノリで押しかけました。
丁寧すぎる道案内
自社ブログに道順を写真付きで乗っけるというアイディア!
(私が知らないだけで珍しくないのかも?)
GoogleMapで行こうかと悪魔がよぎりましたが、
ブログの説明と写真を頼りに渋谷駅ハチ公前から行ってみました。
これが、RPGみたいで楽しい。写真と道の形状や看板を見比べたりしながら、迷うことなくとたどり着けました!
受付からのドクターペッパー
受付のオープンスペースの写真撮り忘れた!
待ち合わせの時間に受付を訪れると、素敵な展望のオープンなスペースに汾陽さんがおられました。
そして真っ先に紹介されたのが、、、
ドクペ!ドクペ!ドクターペッパー!
の自動販売機!!
社員と 来訪者はなんとただで 飲める。驚愕!!
いただきました。
どうしてこうなった - 経緯
- 社長がドクペが好きだった
- 社員が6缶ぐらい入って冷やせる自動販売機を社長の誕生日にプレゼントした
- 社員に好きに飲んでいいよと開放
- 社員が増えてきて冷蔵庫にドクペがストックされるようになる
- 社長が自腹で無料で提供し続ける限界が訪れる
- 福利厚生の一部としてやろう
- 自社ラベルのドクペ作りたかったけどライセンス許可(本国)おりなかった
- 自販機ならいける?いける?いけた!
みたいな。
何この素敵な会社!
執務スペース
受付もそうでしたが、オープンで素敵なオフィス!
週に2回はランチが出たり、毎週のようにピザパーティーが開かれたりしているようです。
でも、集中部屋やスペースもきちんと完備されていて 個人の特性に配慮されてるなーと感じました。
真ん中に写っている着物の方が小椋社長。
そしてこの会社、外国人エンジニアがかなりいます。社内公用語も英語化しています。
グローバルインターンシッププログラムというものを作って、アジアや世界各地からのエンジニア候補を受け入れています。
その結果として優秀な方が多く採用できているとのことでした。したたか!
これは、シタテルも真似したい!真似するぞ!
20年を超える歴史のある企業で、汾陽さんも20年以上勤務されているとのことで、紆余曲折あった話などいろいろと教えていただきました。
まとめ
以上、ドクターペッパーのことしか伝わっていないのではないかという不安もありますが、本当にオープンで素敵な企業という印象を受けました。
社長がCTOでテクノロジー出身というのもあるのか、エンジニアが働きやすい環境が整備されていて。今後のシタテルのオフィスを考えていく上でもとても参考になりました。
ありがとうございました!!