株式会社クイックのWebサービス開発blog

HAPPYなサービスプランナー・エンジニア・デザイナーのブログです。

CREATEアクションファネル

最近植物にどっぷりハマっているデザイナーのFです。
先日社内のオンラインLT大会で植物について少しお話しました。

その時は部屋に植物がある素晴らしさを説いたのですが、 植物が枯れるメカニズムについても触れました。

枯れる原因の中に水やりがありますが、 水やりって忘れたり、めんどうくさくなったり、植物の存在自体を忘れたり、 要因は様々ですね。
習慣化できればよいのですが、難しいです。

私は水やりを忘れませんが、どうすれば水やりを習慣化させることができるのか、 水やりを忘れても枯れないようにできないか?と考えることはあります。

ちなみに私は会社で植物の仕事をしているわけではなく、 社内システムのUI/UX改善を行っているのですが、 どう習慣づけるのか、習慣づいているものをどう変えるのか、 などの行動変容についても日々考えております。

以前ブログでも行動変容について書かれている、 『行動を変えるデザイン』という本を紹介したのですが

aimstogeek.hatenablog.com

今回はその中から少しためになったお話をご紹介します。

CREATE アクションファネル

上記の本で紹介されているフレームワークの一つに『CREATE アクションファネル』というものがあります。

[C]Cue :きっかけ
[R]Reaction :反応
[E]Evaluation:費用対効果考える
[A]Ability:できるかな?
[T]Timing:いつやるか?
[E]Execute:実行

各単語の頭文字をとって『CREATE』となり、 実行までの5つのステップが行動の前提条件になっている、というものです。

水やりで当てはめる

f:id:aimstogeek:20210506221237p:plain

Cue:あ、土乾いている
Reaction:先々週から水やってないな
Evaluation:水やらないと枯れちゃう
Ability:今水を少しあげればいいだけ
Timing:今時間空いてる〜
Execute:水やり

と各ステップを通って『水やりを行う』になるわけです。

各ステップは離脱ポイント

ファネルではそれぞれのステップで離脱が発生します。

水やりの7~8割は一番初めのCue(きっかけ)で離脱してそうですが、 費用対効果を考えてめんどうくさくなったり、 タイミングを考えて後回しにしたりと、 このファネルに当てはめると、どこで離脱したかがわかりやすくなります。

また、先ほど習慣化できればよいと書きましたが、

習慣化することでEvaluation(費用対効果)とTimimg(いつやるか?)の離脱率が大きく下がるので、 行動を実行しやすくなるといった見方もできます。

最後に

行動のファネルを通して考えると、行動の理解が深まりとても整理しやすくなります。 このファネル単体でどうこうできるものではないですが、 調査や戦略と合わせて考えることで、説明や共有がしやすくなると考えます。

仕事とか抜きにして日頃からこのファネルに当てはめて考えてみても楽しいので、みなさんもやってみてください。

おわり


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

【Lighthouse/Docker】Chromeは入っていないけどDockerは動かせるサーバでLighthouseを動かす方法

こんにちは!Czです!

最近驚いたことがあるんですよ。
休日にね、子供たちとリビングでゲーム実況見ていたんです。
そしたらね、その動画のチャンネルのおすすめ動画に親戚が「どーん」と映ってたんですよ。
えっ?ちょっとまって?って感じで。 まさか親戚が登録者数40万のYoutuberだとは思いませんでしたよ。

おじさん、正月とかに会ったときにちょっと緊張しちゃうぞ!( ^ω^ )

ところでみなさん、Lighthouseは知っていますか?(話の切り替え下手)

ざっくり言うと あなたのサイトをGoogleの観点で評価してくれるツール です。
「Performance」「Accessibility」「Best Practices」「SEO」「Progressive Web App」の5つのカテゴリと、様々な指標で評価しスコア化してくれます。
SEO対策を考えている方は必ずチェックしておきたいやつです。

詳しく知りたい方は以下をチェック!
developers.google.com

手持ちのGoogle Chromeで動かしてみる

いまいちピンと来てない方、手持ちのGoogle Chromeで動かしてみましょうか!

右上のメニュー > その他ツール > デベロッパーツールを開き、Lighthouse タブを選択します。

そうすると以下のような画面が出てくるので f:id:aimstogeek:20210422231552p:plain

[Generate report]ボタンを押しましょう。(今開いているページをなにやらせわしなく評価してくれます)

終わったら以下のような結果が出てきます。 f:id:aimstogeek:20210422231639p:plain

このように100点満点中何点かというスコアを表示してくれます。
これを基にどこを改善すべきかを考えることが出来そうですね!

またNode CLIとしても用意されているのでjsさえ書ければ上の手順を踏まなくても実行できます! github.com

...ここでタイトルに結びつけるために唐突な脳内会議

A「Lighthouseを毎日決まった時間に動かしたいな〜」
B「でも自分のPCでは動かしたくない!絶対に!」
C「ちょうどJenkinsサーバあるじゃん」
D「Nodeは入ってないけどDocker入ってるからNodeは実行出来そうだな」
E「え〜っと、Chromeは...?」

A,B,C,D,E「入ってない!!!」

Chromeは入っていないけどDockerは動かせるサーバでLighthouse動かしたい

ここからはコードを書いて説明しますね。

まずはDockerの前にホストマシンでLighthouseを動かしてみましょう!

ファイル構成はとりあえずこんな感じ

.
├ ─ ─  package.json
├ ─ ─  src/
|    └ ─ ─  index.js
└ ─ ─  dist/ ← 計測結果出力先

まずはpackage.json

{
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "node src/index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chrome-launcher": "^0.13.4",
    "lighthouse": "^7.3.0",
    "prettier": "^2.2.1"
  }
}

今回必要なのは「chrome-launcher」と「lighthouse」この2つ。
お好みでprettier(フォーマッター)も入れときましょうか。

そして src/index.js 以下のように記述してください。

const fs = require('fs'); // 結果の保存用
const chromeLauncher = require('chrome-launcher'); // Chrome起動用
const lighthouse = require('lighthouse'); // Lighthouse実行用

// 計測対象のURL
const targetUrl = process.env.URL;

// デバイス: 'mobile' or 'desktop'
const device = process.env.DEVICE || 'mobile';

// 保存先
const distDir = `${process.cwd()}/dist`;
const fileName = process.env.FILE_NAME || 'report';

if (!targetUrl) {
  console.error('URLが指定されていません')
  return;
}

// Lighthouse用オプション
const opts = {
  output: 'html', // 出力の形式。jsonは別の方法で取得できるのでhtmlとしている
};

// Lighthouse用設定
// @see[https://github.com/GoogleChrome/lighthouse/blob/master/docs/configuration.md]
const config = {
  extends: 'lighthouse:default',
  settings: {
    emulatedFormFactor: device,
  },
};

// Chrome用オプション
const chromeOpts = {
  autoSelectChrome: true, // False to manually select which Chrome install.
  chromeFlags: [
    '--no-sandbox', // このフラグがないとオレオレ認証のローカル環境ではこけてしまう
    '--headless', // ヘッドレスモードで起動
  ],
};

(async () => {
  // Chromeを起動
  const chrome = await chromeLauncher.launch(chromeOpts).catch(reason => console.error(reason));

  // 起動したChromeのportをlighthouseが参照するportに指定する
  opts.port = chrome.port;

  // lighthouseを実行
  const res = await lighthouse(targetUrl, opts, config).catch(reason => console.log(reason));

  // html形式で保存
  fs.writeFileSync(`${distDir}/${fileName}.html`, res.report, 'utf8');

  // json形式で保存
  fs.writeFileSync(`${distDir}/${fileName}.json`, JSON.stringify(res.lhr), 'utf8');

  // Chromeの終了
  await chrome.kill();
})();

何をやっているかと言うと

  1. Chrome起動して
  2. Lighthouse起動して
  3. htmlとjsonで結果を保存

という非常にシンプルな感じとなっています。

実行するときはこんな感じ

env URL=<対象のURL> DEVICE=mobile FILE_NAME=report npm start 

環境変数で必要なオプションを渡しています。

URL
Lighthouseを実行対象となるページのURL
DEVICE
携帯かPCか('mobile' or 'desktop')
出力するファイル名
'report'とすると report.html と report.json がdistディレクトリ配下に作られる


結果はdistディレクトリ配下に作られます。 確認してみましょうか。

こんな感じでjsonとhtml形式で出力されています!

/dist/report.json f:id:aimstogeek:20210423110701p:plain

/dist/report.html f:id:aimstogeek:20210422234618p:plain

ちゃんと出力されましたね!

Chromeが起動できるDockerコンテナを作成する

ではやっと本題。先ほど作ったコードをDocker上で動かせるようにします。

ディレクトリ構成

├ ─ ─  docker
│    └ ─ ─  chrome
│        └ ─ ─  Dockerfile
├ ─ ─  docker-compose.yml
├ ─ ─  package.json
├ ─ ─  src
│    └ ─ ─  index.js
└ ─ ─  dist/ 

Docker関連のファイルが追加していきます。

まずは/docker/chrome/Dockerfile

FROM ubuntu:20.04

#SHELL ["/bin/bash", "-c"]

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

# google-chrome-stableをインストールするための準備
RUN apt update && apt-get update
RUN apt install -y wget gnupg gnupg1 gnupg2
RUN sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
      wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN apt update && apt-get update
RUN apt install -y tzdata

# google-chrome-stableのインストール
RUN apt install -y google-chrome-stable

# nodeのインストール(n package使用)
RUN apt install -y nodejs npm && npm install n -g && n stable && apt purge -y nodejs npm

コード内のコメントにある通りなのですが以下の処理を行っています。

  1. google-chrome-stableをインストールするための準備
  2. google-chrome-stableをインストール
  3. n packageを使ってnodeをインストール

次にdocker-compose.yml

version: "3"
services:
  chrome:
    build:
      context: ./
      dockerfile: ./docker/chrome/Dockerfile
    volumes:
      - .:/work
    working_dir: /work
    shm_size: 2gb # メモリが足りないとスコアが下がるため多めに割り当てる

これで準備完了!

Docker上でLighthouseを実行

次のコマンドを実行してみてましょう

docker-compose run --rm -e URL=<対象のURL> -e DEVICE=mobile -e FILE_NAME=report chrome npm start

f:id:aimstogeek:20210423005426p:plain

ちゃんと動いてくれました!

あとはこれをJenkinsなりcronなりで定期実行することで、改善を定量的に評価できたり改善のモチベーションにもなりそうですね!

今日はここまで!

収集したデータをBIツールとか使って解析するのも今後紹介できたらいいな!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

4年目エンジニアが思う、新人エンジニアが意識すること5つ

こんにちは。なししです。
花粉症持ちの私はまだまだ花粉を感じながら過ごしている2021年春。

そんな私、この4月で社会人4年目になりました!!いえ〜い

社会人1〜3年を振り返って、
あ〜〜もっとやるべき・意識するべきだったな〜〜
これはなかなか意識してた!!
ってことを5つ挙げてみました。

まだまだ足りない部分がたくさんある私ですが、この春エンジニアになった新卒の方々やエンジニアデビューした方々のお役に立てれば幸いです。

1.ググり力

業務でググりまくるエンジニアには必須スキルだと思っています。
わからない!!!つまった!!!なんだこのエラー!!
ってなったときはとにかく調べる。
自分が悩んだことはきっと他の人達も悩んだことです。

大切なのは、どんなキーワードでググるか。その結果ほしい情報がヒットするか。
それがググり力。
欲しい情報をだすためにどんなキーワードだったらでてくるか考え、調べまくります。
英語のサイトから逃げないことも大切です。

でももちろん自分で調べてもすべてわかるとは限りません。
制限時間を設けて、30分調べてわからなかったら人に聞く!とすると、時間もかかりすぎず作業できると思います。

自分が調べてもわからず、先輩エンジニアが調べたらわかったなんてこともあると思います。
そんなときはどんなキーワードで調べたのか聞いてみるとよいです。

2.本を読む

言わずもがなって感じですが、自分で調べたい知識をググる!だけだと知識の幅が狭められてしまうこともあるので必要だなって思います。
私は正直めちゃくちゃ読んでた!と誇れるほど読めていなかったので、これからめちゃくちゃ読む予定です。

自分にとって必要だな〜って思う本を読むといいです。
良書は調べれば、たくさんでてくるので、

  • 興味があるもの
  • 業務で必要なもの

から読んでいって興味がある幅を増やしていく!

色々揃えるとなるとコストが…と思うかもですが、そこの自己投資はとっても大事だなぁって感じています。
そして、すべてを買わなくても、

  • 会社に置いてある
  • 書籍補助を活用する
  • 先輩にもってないですか?貸してください!!!っていう
  • (潔癖症とかでなければ)フリマサイトでゲットする

等、ゲット方法はたくさんあります。

3.質問力

これがかなり大事だと思ってます。

自分で考えてもわからない場合、なんて先輩エンジニアに質問するかがとっても重要です。

「わかりません!」「できません!」
だと先輩も、なにがわからないのか・できないのかわからず、求めていない答えがかえってきてしまったり、ちょっと調べてみな〜といわれてしまったりします。

そうならないためにも、

  • 具体的に何が聞きたいのか(具体的の粒度はその時に合わせる)
  • どんな期待値を求めてるのか
  • そのためにどんな作業をしたのか
  • 結果なにがだめだったのか

を最低限盛り込んで質問することを意識するだけでコミュニケーションがスムーズになります。

質問力がなかなか身につかない場合は質問テンプレートを作って、質問前にまとめてみると自分の頭の中を整理できます。

4.先輩のコードを読む

先輩のコードを読むと、いろんな発見があります。
実際にコードを追ってみると、そのプロジェクトの癖だったり、決まった書き方だったり、自分が知らない書き方だったり…たくさんの知識・情報が詰まっています。

そして先輩のいいところは真似してみる!使ってみる!
これはコードだけでなく、行動も!!(だじゃれみたいになっちゃった)

5.スケジュール管理

すごくむずかしいですが大事です。
1~2年目はとにかく振られた仕事を必死にやるって感じでなかなか意識しづらいですが、2年目後半、3年目くらいから意識するようになります。

そのタスクでやらねばならないことを洗い出し、
自分の技術力であれば、このタスクこれくらいでPRだせるかな〜。
この日のリリースがマストだから、逆算するとこの日までにここまでできてないとだめだな〜。
って考えながら、スケジュール管理していきます。

そしてなにかつまづいて遅延してしまう、なんらかの問題がある場合、

  • 巻き返せるのか
  • 他の人のちからを借りたいのか
  • リリース日を延ばすのか、

等上位者に報連相することも大切です。

最後に

どうでしたか?意識していることありましたでしょうか?
これらがちゃんとできると先輩エンジニアからの信頼度や、業務効率アップに繋がるので、ぜひできてないことがあった方はトライしていただきたいです。
私も意識して真似してもらえるエンジニアになれるよう精進してまいります!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

LaravelでGraphQLを使ってみた

こんにちは。ソフトウェアエンジニアのやぎーです。

4Kモニタを購入してみたのですが、想像以上に文字が見やすくて疲れにくいです。
PCで文字を見る時間が長い方には4Kおすすめします。

さて、最近LaravelでGraphQLを触る機会がありましたので、簡単にご紹介させていただきます。

ざっくり環境

  • PHP 7系
  • Laravel 5系
  • Lighthouse 5系

GraphQLとは

  • APIのクエリ言語で、データ用に定義した型システムを使用してクエリを実行するためのサーバー側ランタイム
  • クライアントとサーバー間のデータのやり取りを容易に記述できる

graphql.org

Lighthouseとは

LaravelでGraphQLが簡単に利用できるライブラリ f:id:aimstogeek:20210407181407p:plain

lighthouse-php.com

こんな人におすすめ

  • RESTful APIでエンドポイントの管理が限界
  • なるべくオーバーフェッチを減らしたい
  • 必要なデータを揃えるために、複数のAPIリクエストが必要になっている

導入方法

Laravelを使っている環境があればとても簡単に導入できます。

# Lighthouseをインストール
composer require nuwave/lighthouse

# 初期設定
php artisan vendor:publish --tag=lighthouse-schema

DevToolsを使いたい場合は下記もどうぞ。

# /graphql-playgroundで直接クエリを実行できる
composer require mll-lab/laravel-graphql-playground

スタンドアロン版もあるようです。 www.electronjs.org

DevToolsの画面はこんな感じ。 f:id:aimstogeek:20210407101415p:plain

スキーマの確認や、クエリの実行ができます。

書き方

インストールが完了すると、graphql/schema.graphqlというファイルが生成されます。 ここにスキーマを記述していくのですが、スキーマが膨らむ場合には下記のように分割が可能です。

# graphql/schema.graphql

# 追加
#import **/*.graphql

スカラー

5つのスカラー型が存在します。

  • String(文字列型)
  • Int(整数型)
  • Float(浮動小数点型)
  • Boolean(論理型)
  • ID(ID型)

ルート型

データソースに対する操作を表現する型。

  • Query
# データの取得

type Query {
  me: User
  users: [User!]!
  userById(id: ID): User
}
  • Mutation
# データの登録・更新・削除

type Mutation {
  createUser(name: String!, email: String!, password: String!): User
  updateUser(id: ID, email: String, password: String): User
  deleteUser(id: ID): User
}
  • Subscription
# websocket

type Subscription {
  newUser: User
}

オブジェクト型

1つ以上のスキーマで定義されているフィールドの集合。

# 例
type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Post {
  title: String!
  author: User!
}

ディレクティブの種類

紹介し切れないくらいあるので、公式リファレンスを参照ください。 lighthouse-php.com

Resolver

特定のフィールドのデータを返す関数(サーバーサイド) 独自に実装することもでき、スキーマに実行したいResolverを指定できる。

# こんなかんじ
type Mutation {
  createPost(title: String!): Post
    @field(resolver: "App\\GraphQL\\Mutations\\PostMutator@create")
}

ここがいい

  • リクエストをまとめられる

    • 一度に複数のresolverに対してqueryを送れるため、必要な情報をまとめて取得できる
  • Eloquentモデルをそのまま利用できる

    • Eloquentモデルで定義してあるリレーションなどをスキーマ側で指定して利用することができる

      • リレーション(hasMany/belongsTo等)
      • 認証
      • ページネーション
      • バリデーション etc...
  • 導入しやすい

    • Lighthouse使えばGraphQLの導入がとても簡単
  • エンドポイントがひとつ

    • RESTと違ってエンドポイントが共通のため管理がしやすい
  • バージョン管理しなくていい

    • クライアントで必要な情報を要求できるため、fieldの削除などをしなければ破壊的な変更になりにくい
  • ジェネレータでコードを自動生成できる

    • graphql-codegenを利用すればGraphQLのschema定義からTypeScriptの型定義を生成できる

ここがよくない

  • パフォーマンス計測がしづらい

    • エンドポイントが同じため、細かい分析がしづらい
  • キャッシュがしづらい

    • RESTと違い、URLをベースのキャッシュができないため方法を検討する必要がある

まとめ

とても大雑把な紹介にはなってしまいましたが、使ってみた感じ非常に好感触です。 学習コストも少なく、柔軟性にも優れていると感じました。

実際のスキーマに関してあまり記載はしませんでしたが、公式のリファレンスがわかりやすいので参照してみてください。

もちろん用途によって向き不向きはあるかと思いますので、無理に導入する必要はありません。

実際に使ってみるのが一番わかりやすいと思うので、興味を持っていただけたらぜひお試しください。

最後まで読んでいただきありがとうございました!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

クイックへ転職してみて…

f:id:aimstogeek:20210401004445j:plain こんにちは。デザイナーのタニモです。よろしくお願いします!
クイックには中途で入社し、この4月で8ヵ月目となります。 現在はデザイナーとして様々なプロジェクトに関わり、主にイラスト制作業務を担当しています。
前職は全く業界の異なるゲーム会社で、約14年勤めていました。今回はそんな私がクイックに転職した経緯と、 クイックでの将来の夢について少しお話させて頂ければと思います。

畑違い過ぎる前職

前職は某ゲーム会社のCGデザイナーです。主に担当プロジェクトのキャラクター制作(デザイン・3Dモデリング)や、 ゲームの世界観・ビジュアル全般をディレクションするアートディレクター業務などを担当していました。 アニメや漫画など、他社IPとのコラボプロジェクトを担当することが多く、特にキャラクターに関連するものは何でも作ってきた感じです!

転職の動機

1つの会社に長く務めると仕事はやはりマンネリ化してくるもので、転職は以前から意識していました。 他のゲーム会社への転職もこれまでに何度か考えたのですが、職種が同じである以上、今とさほど仕事内容は 変わらないだろうな…という思いもあり、なかなか決断までは至りませんでした。転職するならゲーム以外の分野に視野を広げ、 より幅広いユーザーと向き合えるような仕事がしてみたい!そこで自分のスキルとこれまでの経験を生かしていきたい!そんな思いが強かったです。
そのようなタイミングで、前職の良き後輩からクイックへのリファラル採用のお話をもらい、今回の転職のきっかけとなりました。

転職への期待と不安…

私がクイックへの転職を決断した大きな理由は、Web事業企画開発室がこれから事業の柱となる新しいことに チャレンジしていくフェーズであり、一緒に組織を成長させていける仲間を募っているという点に大変魅力を感じたからです。 自分の経験を他業種で生かすには非常に相性の良い会社だ!…と期待が膨らみました。
しかし、いざ転職に向けて本格的に準備を始めると、いろいろと不安も抱きました。業界も職種も今の会社とは異なるため、 仕事内容や職場環境が全く想像つかない。14年も今の会社で積み上げてきたものをリセットしてまで転職する価値はあるのか。 年齢的にも失敗はしたくない!…かと言って、ここで転職を諦め、今の会社で定年まで働き続ける覚悟はあるのか。後々後悔しないだろうか…。
まさに人生をかけた選択でもあるため、本当に転職すべきかどうか、その決意がしっかりと定まるまで 何度も自分自身に問いかける日々でした。(笑)

f:id:aimstogeek:20210401005743g:plain

クイックで働いてみて

私が所属するWeb事業企画開発室は職種の幅が広く、多種多様なスキル・経験のあるスタッフが働いています。 業務中の様々な場面で刺激を受けることが多く、また、出る杭は伸ばすといった社風で、誰もが主役になれ、 輝けるチャンスのある職場だなと感じます。
前職が畑違いな私ですが、それを個性とし、強みとして受け入れてくれる職場。 だからこそ、自身の強みを生かした夢ややりたいことを自由に思い描くことができ、それを実現することをモチベーションに、 日々の仕事に励めているのだと思います。

クイックでの将来の夢

私がクイックで実現したいことは2つあります。1つは、キャラクターの力を使って既存のサービスや コンテンツの価値をより一層高めること。もう1つは、オリジナルのキャラクターを使った新規webサービスの立ち上げに貢献することです。
将来的には、生み出したキャラクターとその世界観をIPとして独立させ、様々なメディアや商品、エンタメコンテンツにも 展開していきたいと考えています。
…キャラクターばっかりですね。(笑)
人材サービス業界でここまでキャラクターに力を入れる会社はまず無いでしょう。 だからこそ、やる価値があると私は思っています。ゲーム業界で培ったノウハウをフル活用し、 人材サービスという畑では今まで作れなかった新たな作物を育てることで、同業他社にはない独創的な価値を生み出す。 これを実現することが、ゲーム業界出身の私がクイックに存在する意味だと思っています。
入社したからには、クイックの歴史に名を残したい!(笑)

f:id:aimstogeek:20210331233905p:plain


以上が、私のクイック入社までの経緯と入社後の心境になります。 これからクイックに入社される方、またクイックに興味を持って頂けている方に、 私の今回の経験談が少しでもお役に立てば幸いです。 これから一緒にクイックを盛り上げて頂ける仲間を心よりお待ちしております!

最後までお読み頂きありがとうございました。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

「マテリアル・オネスティ」という思想でデザインに向き合う

MaterialHonesty こんにちは。デザイナーのヨシナリです。

突然ですが、「マテリアル・オネスティ」という言葉をご存知でしょうか。
恥ずかしながら、僕は半年前くらいに知りました。
尊敬している先輩デザイナーと話をしていた時に教えていただいた言葉です。

日々、僕なりにデザインの本質について考え悩んでいるのですが、その思想がすごい腹落ちをしたので、今日はその話をしたいと思います。

こういった思想的な話は、様々な解釈や想いがあるので、
ブログのような一方通行な媒体で発信すると、誤解も生みそうなので正直こわいですw
ですが、この言葉がもっと世の中的に広まったら嬉しいなぁという思いの方が勝ったので、話をさせてください。

「マテリアル・オネスティ」とは

プロダクトデザインの文脈における言葉です。
さかのぼること1800年代に生まれたもので、モダンデザインの父、ウィリアム・モリスにも強い影響を与え、アーツ・アンド・クラフツ運動の中心思想となったものです。

そのまま訳すと、その素材(マテリアル)を正直(オネスティ)に表現するというもの。
「何かの模倣やディテールを誇張するものではなく、素材本来の姿に忠実であるべき」
という意味で、デザイン史上の格言的なものになります。

では「素材に忠実」とはどういう意味でしょうか。
例えば、椅子は最初に木で作ろうとされました。
なぜか。それは柔らかい人に優しい素材だからこそ、長時間座れるからです。
だから、固い鉄やコンクリートを選ばず、自然と木を選択していったそうです。
製造工程に無理がない。そこには無駄な加工が存在しない。
それが「素材に忠実」という解釈になるかと思います。

もう少し言うと、アルミ削りだしのApple社製のノートパソコンの筐体が美しいと感じるのも、マテリアルオネスティが根本にあるからと言われています。

ちなみに、Web業界では、フラットデザインが登場した頃に話題になったようです。
当時は、「フラットデザインはマテリアルオネストで、スキューアモーフィックデザインはマテリアルディスオネストだ」
という議論があったようです。
この議論を追いかけていくと様々な考えを知れるのでとても面白いです。

ただ、今回僕が伝えたいことはこの粒度の話ではなく、もっと広義に現代のデザイン全般にとって大事な考え方なんじゃないかなということです。

デジタルメディアにおいての「素材に忠実」

「素材」をデジタルメディアの視点でどう考えるか。
当時でいう家具や建築などの並列にバナー、Web、アプリなどのプロダクトがあります。
では、その素材はというと、「伝えるべき情報」なんじゃないかなと。

デザインの役割として、コンテキストや情報量を整理・設計するのはもちろんです。
ですが、それだけでなく、複雑な多くの情報をどれだけ「忠実に素直に」表現していくか。
これが、デザインという行為の中で重要なんじゃないかなと考えています。

こういった考えが、頭の中にズーっとあったんですが、うまく言語化ができずモヤモヤと違和感を感じていたんですよね。
そんな中、「マテリアル・オネスティ」という言葉を知って、すごく腹落ちしたんです。

今回はデジタルメディアを例にして話ましたが、この概念は、他のデザインにも当てはまるんじゃないかなと思います。

例えば、グラフィックデザイン
表現したいモノの「らしさ」。
広告的にいうと「シズル」を忠実に再現するといった行為に代替えできるのかも。

「LESS IS MORE」「神は細部に宿る」とならぶ格言だと思う

クリエイティブの世界にはたくさんの格言があります。
その中で、「LESS IS MORE」「神は細部に宿る」は特に有名だと思うのですが、この「マテリアル・オネスティ」はそれらに並ぶ大切な考え方なんじゃないかと僕は思います。

なぜ、そのかたちでなければいけないのか。
なぜ、その色でなければいけないのか。 全てが必然になったとき、納得のいくデザインにたどり着けると僕は考えています。
素材に素直に向き合い忠実に表現する努力をすることで、その必然を導き出せるかもしれません。

自分のデザインは本来のマテリアルにオネスティなのか。
そう自問自答しながら、デザインに向き合っていきたいと思います。

一緒に向き合えたら嬉しいです

エモ散らかしてしまって失礼しました。

クイックにはデザイン、イラスト、コピー、そしてユーザーに忠実に向き合っているクリエイターがたくさんいます。 今日の話に少しでも興味をもってもらえたら嬉しいです(^^)

読んでいただきありがとうございました。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

【スプレッドシート】範囲保護しつつフィルタを利用する方法

こんにちは、ちーかまです!
初めてブログ担当になってフレッシュな記事を書いてから早7ヶ月、少しづつエンジニアとしての自信がついてきた今日このごろです。

(ちなみに過去記事はこちら!) aimstogeek.hatenablog.com
最近業務で大勢の人とスプレッドシートを共有しながら使う機会が多いのですが、その中で悩んでいることがあります。
それは編集されたくない箇所が他の人によって編集されてしまうこと!
ならば範囲保護をしようという考えに至ったのですが、今度は範囲保護の編集権限を持たない人がフィルタが使えなくなってしまい作業効率が落ちる...

そこで今回は、スプレッドシートで範囲保護しつつフィルタを利用する方法を考えてみました。

今回使用するスプレッドシート

サンプルとして、下記のようなスプレッドシートを用意しました。

f:id:aimstogeek:20210304114345p:plain

B列・C列は入力が行われる作業用の列、A列・D列・E列は問い合わせに関する情報が入っているため編集されたくない列、という構成になっています。
それではさっそく解決方法を紹介していきます!

1.データ保持用のシートと作業用シートを分ける

1つ目に紹介するのは、データ保持用のシートと作業用シートを分けて、作業用シートにデータを読み込ませるという方法です!以下で手順を説明します。

Step1 データ保持用のシートを作成する

まずサンプルのA列・D列・E列のみが記載されている、データ保持用のシートを作成します。今回このシート名を「マスタ」に設定しました。

f:id:aimstogeek:20210304161852p:plain

Step2 作業用のシートを作成する

次にサンプルのB列・C列のみが記載されている、作業用のシートを作成します。

f:id:aimstogeek:20210304161911p:plain

Step3 作業用のシートにデータを読み込ませる

最後に、ARRAYFORMULA関数を使用してデータを読み込ませて完了です!

f:id:aimstogeek:20210304164937p:plain

注意点

とても簡単なこの方法ですが、実は注意しなければならない点があります。それは並び替えを使うとデータと入力内容がリンクしなくなるということです。
実際に担当者の昇順で並び替えた後のサンプルを見てみましょう。

f:id:aimstogeek:20210304165512p:plain

B列・C列が並び替えられているのに対し、A列・D列・E列が並び替えられていないことがわかるでしょうか?A列・D列・E列は別シートを読み込んでいるため、並び替えを行った後も再度読み込みが行われ順番が元に戻ってしまうのです。
データ保持用のシートと作業用シートを分けて運用する場合は、並び替え禁止というルールを周知させることを忘れないようにしてください。

2.フィルタ表示を用意してあげる

2つ目に紹介するのは、範囲保護の編集権限を持つ人が代わりにフィルタ表示を作成してあげるという方法です!
...と言っても、みんなが必要な絞り込みのパターン分フィルタ表示を作成してたら業務どころではないですよね?ということでGASを使ってフィルタ表示作成を自動化してみました。

フィルタ表示作成をGASで行う

以下で手順を説明していきます。
同じ形式のシートを作成してスクリプト内にあるシート名称を変更するだけで使えるようになっているため、もしよろしければ試してみてください!

Step1 絞り込み条件を入力するシートを作成する

まず追加してほしい絞り込み条件を入力するためのシートを作成します。
A列に「フィルタ名」と記載し、B列以降にフィルタを追加したいシートのヘッダーをそのままコピペすれば完了です。

f:id:aimstogeek:20210304174722p:plain

あわせて入力方法も説明していきます。
A列はフィルタ表示の名称を登録する列です。未記入の場合はデフォルト名である「フィルタ(数字)」という名称で追加されます。
B列以降に単語を入力すると、「その単語が含まれる」という条件で絞り込みが作成されます。「該当列になにも記入されていない」という条件で絞り込みを行いたい場合は、「空欄」と記入するようにしてください。

f:id:aimstogeek:20210304174028p:plain

Step2 Google Sheets APIを有効にする

GASでフィルタ表示を操作するためには、Google Sheets APIを使用する必要があります。メニューより ツール > スクリプトエディタ を選択した後、下記のように操作してGoogle Sheets APIを有効にしてください。

f:id:aimstogeek:20210304185713g:plain

Step3 スクリプトを書く

フィルタ表示を追加するためのスクリプトを書いていきます。
下記が実際に書いてみたスクリプトです。

function addFilterView() {
  // アクティブなスプレッドシートのIDを取得
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ssId = ss.getId()
  // フィルタービューを追加するシートのIDを取得
const sh = ss.getSheetByName("フィルタ表示を追加したいシートの名称");
const shId = sh.getSheetId()
  // 絞り込み条件を入力するシートを取得
const iSh = ss.getSheetByName("絞り込み条件を入力するシートの名称");
  // 依頼シートの最終行と最終列を取得
const lastRow = iSh.getLastRow()
const lastColumn = iSh.getLastColumn()
const requests = [] // フィルタ追加のリクエストデータを登録する配列

 // フィルタビュー追加用のJSONデータを生成する
for(let row = 2; row <= lastRow; row++) {
  const title = iSh.getRange(row, 1).getValue(); // フィルタ名取得
  var request = '[{"addFilterView": {"filter": {"range": {"sheetId": ' + shId + '}, "title": "' + title + '", "criteria": {'
  const conditions = [] // 絞り込み条件を作成するための配列
  for(let column = 2; column <= lastColumn; column++) {
   const condition = iSh.getRange(row, column).getValue();
    if(condition !== '') {
      if(condition === '空欄') {
        conditions.push('"' + (column-2) + '": {"condition": {"type": "BLANK"}}')
      } else {
        conditions.push('"' + (column-2) + '": {"condition": {"type": "TEXT_CONTAINS", "values":[{"userEnteredValue": "' + condition + '"}]}}')
      }
    }
  }
  if(conditions.length !== 0) {
    request += conditions.join(', ')
  }
  request += '}}}}]'
  requests.push(JSON.parse(request))
}

 // フィルタビューを追加
if (requests.length > 0) {
  Sheets.Spreadsheets.batchUpdate({'requests': requests}, ssId)
   // 追加済みの依頼内容をシートから削除
  iSh.getRange(2, 1, lastRow, lastColumn).clearContent();
} else {
  return
}
};

よくわからない...という場合は上記をコピペして、「フィルタ表示を追加したいシートの名称」と「絞り込み条件を入力するシートの名称」を書き換えれば動きます!

Step4 実際にフィルタ表示を追加してみる

それではスクリプトを実行して、フィルタ表示を追加してみましょう!

f:id:aimstogeek:20210304185507g:plain

やったー、無事追加できていますね!!この後確認しましたが絞り込みの条件も問題ありませんでした!
何度も同じフィルタ表示を追加しないように、絞り込み条件を入力するシートから入力内容を消す処理もきちんと動いてます。

まとめ

スプレッドシートで範囲保護しつつフィルタを利用する方法として

  1. データ保持用のシートと作業用シートを分ける
  2. フィルタ表示を用意してあげる

を取り上げてみました。
制約がある、導入方法が難しい等まだまだ改善の余地はありますが、みなさまの参考になれば幸いです。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! // 919.jp