ぽんぽんぺいんでつらたんなので、おしごとおやすみしまーす

🗣: バイクに乗ったり、ものづくりしたり、ひたすら寝たり。

MotionLayoutでリッチなUXをxmlのみで表現してみました

長いこと更新をサボってました。。 最近はもっぱらKotlinでのAndroid開発に従事していますが、ビューの原則はMaterialDesignを取り入れ、バラツキのあるデバイスの端末性能を吸収する優秀なプラグインが用意してあったりと、奥深く、ネイティブは楽しい分野だと感じています!

(デザイナーさんから思いもよらぬ仕様を叩きつけられることもありますが…)

勉強がてらに新しい部品に触る事も楽しいです!

そんな感じでいただいたデザインと納期の間で不安に苛まれていたとある日、何某Kotlinイベントに参加してみました。 Droid会議直後の温まった会場でMotionLayoutについて教えていただく機会があり、実装してみたので軽くレビューしていきます🐕

1. xmlファイルでリッチな動きが実現するMotionLayout

実装例・導入方法など詳しくはこちらをご覧ください💁‍♀️

https://github.com/googlesamples/android-ConstraintLayoutExamples

Google I/O 2018で紹介されているようですね♩ youtu.be

< 実装例gif >(でかくて申し訳ない…)

gfycat.com

RecyclerViewは別途Adapterクラスなどの実装が必要なので、実装にはこちらを参照してください。

2. 導入 : build.gradle

build.gradle

dependencies {
  implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha3'
}

3. ベースのxmlを記述する

base.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".HogeActivity">

    <android.support.constraint.motion.MotionLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/design_default_color_primary"
        app:layoutDescription="@xml/motion"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">   
 
       <android.support.v7.widget.RecyclerView
            android:id="@+id/top_recycler_view"
            android:layout_width="wrap_content"
            android:layout_height="500dp"
            android:paddingTop="30dp"
            android:background="@drawable/recycler_view_bkground"
            android:scrollbars="vertical">

        </android.support.v7.widget.RecyclerView>
    </android.support.constraint.motion.MotionLayout>
</android.support.constraint.ConstraintLayout>

4. motionタグの追加

motion.xml

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:motion="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Transition
        motion:constraintSetStart="@id/base_state"
        motion:constraintSetEnd="@id/open_state"
        motion:duration="3000">
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@id/top_recycler_view"
            motion:touchAnchorSide="top">
        </OnSwipe>
    </Transition>

    <ConstraintSet android:id="@+id/base_state">
        <Constraint android:id="@id/top_recycler_view">
            <Layout
                motion:layout_width="400dp"
                motion:layout_height="100dp"
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintVertical_bias="1.0">

            </Layout>
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/open_state">
        <Constraint android:id="@id/top_recycler_view">
            <Layout
                motion:layout_width="400dp"
                motion:layout_height="500dp"
                motion:layout_constraintEnd_toEndOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintBottom_toBottomOf="parent">
            </Layout>
        </Constraint>
    </ConstraintSet>
</MotionScene>

非常にさっくりと説明すると、app:layoutDescription="@xml/motion_activity_first_visit"のように設定したmotion.xmlで該当の部品のアニメーションを指定します。 今回のアニメーションはベースの状態(@id/base_state)とアニメーション終了時の状態(@id/open_state)です。 motionタグで囲う範囲については、アニメーションの可動域となるので、くれぐれも他の要素が消え去らないように注意してください。(プレビューすれば一目瞭然ですが…)

今回はmotion.xmlで、部品上部において上にスワイプする操作で、ビューがプルアップ+ダウンする挙動を制御しています。 フリック(軽く指で弾くような動作、スライドショーをめくるような動き)では反応しないので、適宜使用するタグを付け替えてみてください。

公式のリポジトリの例が豊富なので非常におすすめです。

https://github.com/googlesamples/android-ConstraintLayoutExamples

報告者を指定日時で通知するスクリプト<Slackユーザー向け / コード付き>

N番煎じ?

月末に部門定例会があるので、公平にみんなの中から報告者を決めることにしました💁‍♀️



Slack当番通知
Slack当番通知


GoogleAppScript

var postUrl = 'https://hooks.slack.com/services/HOGE/HOGEHOGE/HOGEHOGEHOGE'; …①

var icon = ':hatching_chick:';
var index = 0;
var checked_engeneer = '';
var icon_url = 'https://hogehoge-team.slack.com/team/HOGEHOGE'


var engeneer_ids = ['<@hoge1_slackId>', '<@hoge2_slackId>', '<@hoge3_slackId>', '<@hoge4_slackId>', '<@hoge5_slackId>'] …②



function shuffleReporter() {

index = Math.floor(Math.random()*6)

var id = engeneer_ids[index]

var jsonData =
{
"username" : '悪意のないchick',
"channel" : "#development",
"icon_emoji" : icon,
"text" : '今月の開発部門報告者は' + id + 'さんだよー\n開発のみんなの1ヶ月のタスクと、最近自分ががんばったことを話してね!',
"icon_url" : icon_url
};

var payload = JSON.stringify(jsonData);

var options =
{
"method" : "post",
"contentType" : "application/json",
"payload" : payload,
};

UrlFetchApp.fetch(postUrl, options);
}

①… SlackのwebhookAppをオンにして、出力URLを取得しましょう。
②… メンション用の個人タグです。付けないとメンション飛びません。個人の詳細ページからmemberIdとして取得できます。



悪意のないひよこが教えてくれます。(これはKotlin因み…🐤)
Cronもあるらしいけど、今回は手動で時間設定。
時間主導型の設定フローは下記画像を参考にしてください。
時間主導型設定フロー

カレンダーのイベント抜いて設定したら、また更新します。

2018年振り返り+2019やりたい事まとめ🐶

生活面

## 遅まきにはじめた一人暮らしが存外に快適だった。

- 杉並区は都内までのアクセスがよくて(JRとメトロの駅が15分圏内のとこにいる)、割と飲食系の有名店も多い。
- 家は全然広くないけど、一人だと部屋のメンテが超楽。
- アニメ充と引きこもりが捗る(家の裏にファミマがある)
- クロスバイクに乗り始めたけど運動解消にいい。コミュニティとかにも参加したい。

## 生活リズム狂いがち。

- 無職時代は1年前と違って昼起床がデフォになりつつあった。
- 料理し始めるのはいいが、モチベーションがそこまで上がらない😊(テンプレをローテーション)
- 割と情緒不安定な時期とかあった。
- 自己投資と称した散財は割と多かった💸💸💸


仕事面

## 2年前よりはコードを書く機会が増えた。

- エンジニアとしてやっていけるか超不安で、センスもないと思い込んでいたけど、
頼まれごとも割と増えて去年よりは自信がついた。
- MAMPの設定もよくわからんかった自分ですが、GCPでDBサーバ建てて通信したり、ドメイン取ったりしてデプロイが出来た。
- 貧弱資格だがRuby Association Programmer Silverを取得した。Goldは5問正答が足らず落ちてしまったので、やる機会あればまた受ける。
- web系あるあるなフロント周り、頑張ろうと思えば極められたけど、技術を摘み喰いしてしまった結果サーバサイド寄りな事をやっていた😇
- ↓↓やった事たち↓↓

---書いた
Ruby, Ruby on Rails, slim, SaSS, js(jQuery, erb, ECMA2015), Kotlin

---触るもしくは眺める程度
Docker, GCP(GA, GKE), AWS, Elasticsearch, Vue.js
mysql, postgres
Ubuntu, Debian stretch
Photoshop
Dialogflow
vim, zsh周り


## 転職できたー🎉🎉🎉㊗️

- ほんとは前職で3年くらいいる予定でいたが、技術的な方の自分のテンションが上がってしまった為、転職する事にした。
- 10件強面談とかして4件内定もらえた。実感したのは自分の頑固さや人と話すことの下手さ😇
- ビズよりな知識も不足している。もうちょっとニュース見たり官報見たり、経営の勉強してもいいよね。

- GCP, Kubernetes, Kotlin, Swift, Java, Ruby, Railsが主な活動範囲の会社です。
 アウトプットサボらず頑張ろう。

## プログラミングという行為を通して人見知りが解消してきたような気がする。

- 勉強会・もくもく会行きまくった。(connpass上の勉強会は21件参加してた)
- 同業の人たちとお話しする機会があってとても良かった。特に同世代からは刺激を受けた。
- 何気に下手くそなLTをもくもく会で披露したりした。



2019年やりたい事

- アプリのデプロイ回数を増やす

Herokuを年中disり、無駄課金を言い訳にあまり捗らなかったところがある。

- 英語

ドキュメントを読んだり、外注の人とやり取りするだけに止まった。スピーキング力を上げたい。
 現在の職場の先輩曰く、本になっている情報は古い。
 (本に書いてある情報を知らない事もあるので本を読むなという意味ではない😇)

- 余暇の過ごし方

  技術と食べる事以外にそんなに頑張っていない。カメラとか二輪取得に向かって頑張りたいところ。
 多分素材が集まれば個人HP作るだろう(管理費も会社から支給されないかしら)

- 資格取る

 基本情報技術者かな…とりあえず受かるまで受ける😇

- 技術的なポリシーを打ち立てて勉強を進めたい

 頼まれて実装することは多くても、保守性を意識してコーディング出来ていなかった気がする。
 アプリやDB設計周りの勉強は続けたいし、テストを書く習慣を付けていきたい。
 Goを触りたいという気持ちでいるけど、実務で私の書いたKotlinが受け入れられてから考えることにする。

SQLアンチパターン論理設計編の追記

こんばんわ!Paypayを導入した翌日に20%還元イベントが終了した者です。
意外にコンビニで「Paypayで」とお願いすると困惑される事も多くて、まだまだ10日では日本国民に浸透していない雰囲気ありますね?
セブンイレブンでは怪訝な反応をされましたが、ファミマはPaypayアナウンスが入る程度に対応が早かったですね)

しかしアマゾンとメルカリさんが経団連の面子に入ったことから、IT分野が経済圏の掌握をしていく未来は避けられなさそうですね。扱うジャンルのものにも依ると思うのですが、再度金融商品周りの勉強をしても損はなさそうな気がしています。
UI周りの重要度の認識も上がるといいのですけど!
あとは著作物の権利関係かな。民間資格で言うとビジネス著作権検定などもありますので、資格コレクターな方は是非是非。


経営面も強くなりたいので、バランスシートを読む練習はしたいなーと思いつつ全然やってないですね…
会社を持つ気にはなれないのですが、身を置いている会社がどんな状況にあるかは把握しておきたい的なやつです。
今話題の基本用法技術者の出題範囲でもあります。

それよりもカジュアルに、エンジニアによるエンジニアの為の生存戦略ベンチャーの経営状況を把握するみたいな標題の勉強会がそのうち開催されることを夢見てます。笑



本題です。なんとSQLアンチパターンまとめの目次抜けがありました🤣
自らまとめると意気込んだにも関わらず、この体たらくです。本は1回読んだだけじゃダメですね。
自分はかなり物覚えも悪いので、だいたい目に付くところに提出書類をまとめたファイルをぶら下げてあります。
とりあえず目に入らない情報は綺麗に忘れていく

エンジニアの勉強で難しいところは、個人的に触って実践できる部分と、本番でなければその利点や使いづらさを身にしみて理解できない部分があるところだと思います。

本番の再現ができる技術レベルでもない限り、私たちにできることは、なんとなく勉強会などで聞きかじったことを、経験のある人に話題として振ってみるくらいのことしかできないので、
今後は自分のスキルを積み上げる為にも、初心に戻ってシステム開発の基礎+他言語+フレームワークを触る予定でいます。
近いうちに〇〇と〇〇ができる人!って感じに頼られたいですからね!笑


ようやく本題。今回ご紹介するDB設計アンチパターンはこの2つ!

マルチカラムアトリビュート(複数列属性)
メタデータトリブル(メタデータ大増殖)


マルチカラムアトリビュート(複数列属性)

この事例を読んだ時には、「あー。これこれ。よくやるやつ本当これ」ActiveRecordを触っていた時によく思っていたこととがっつり同期しました。

なんか増えそうな項目なんだけど、とりあえずカテゴリ分けしておきたい時
Bugsというテーブルがあったとします。
このテーブルは単一テーブルでバグの発生日時、発生順、バグの内容、バグの起因を表現しています。

bug_id バグの発生順
reported_at バグの発生日時
issue バグの内容
case1 バグの起因(ユーザー起因)
case2 バグの起因(開発者起因)
case3 バグの起因(運用起因)

こんな感じで設計してみました。ただ、このcase*カラムは未使用のものに関してNULLを返す仕様になっています。

この設計で困る時

なんか検索クエリ長い

起因が複数にまたがる時は以下のようなクエリを発行したくなります。(INを使えばもう少しマシになる)

select * from Bugs
where (case1 = 'user' or case2 = 'developer' or case3 = 'customer service')
and (case1 = 'user' or case2 = 'developer' or case3 = 'customer service');

値を更新したいけど更新処理が突合しないか

どの列が空いていないかを確認し、更新処理をかけたところで他のユーザーが同じデータの列に更新処理をかける可能性も否めないわけです。
しかし、この事例ではNULLIF関数を使用することでそれが避けられそうだというソリューションが乗っていました。

update Bugs
set case1 = NULLIF(case1, 'user'),
set case2 = NULLIF(case2, 'developer'),
set case3 = NULLIF(case3, 'customer service')
where bug_id = 1234;

ちょう便利!しかし、これでfalseを返す場合にデータの更新処理は行われません。
従ってIF文を書かなければいけないわけです(もうコレアプリ側でやるやつやん…

万が一属性が増えた場合に、クエリがさらに長くなる
スキーマを変更したいときにテーブル自体をロックしなければいけない可能性
新規テーブルを定義して既存テーブルをコピーしてマイグレートするサードパーティ製品もあるので気をつける(地獄

ソリューション

caseを切り出してテーブルにしてしまうのが良いようです。縦管理で心置きなくdelete文を発行できます😇

メタデータトリブル(メタデータ大増殖)

本棚を買ったけど、スペースがどうにも気になって読まない本まで入れてしまうやつ。

本書の事例では、ある顧客管理テーブルと関連性を持った年毎の顧客データ格納テーブルを設計した話が記載されています。
使用用途はアクティブな顧客を一目でわかるようにしたいとのこと。

しかし毎度クエリを発行するのがめんどくさい怠惰なCSチームはもれなくこのテーブルを放置プレイする訳です。おめーらが作れって言うてたやんけ!
開発者の中ではこのテーブルをどう活用するのか議論になりますが、下記のようにおえかきじゆうちょうもびっくりなフリーダムなテーブルへと変貌を遂げます。

年毎のテーブルを毎年createする必要がある
データの整合性をチェックする必要がある

私は正規表現などで弾くものかと思ってましたが、
CHECK制限を儲けるとこのあたりは捗るみたいです。

create table Bugs_2018 (
date_reported DATE CHECK (EXTRACT(YEAR FROM date_reported) = 2018)
);

他の年度とjoinしたテーブルから特定の値を抜きたい要件では、発行するクエリがめんどくさい感じになる…

ソリューション

パーティショニングする
やっぱり別枠で切り出す😇

パーティショニング is 何?

私もこの章を読んで初めて知りました。パーティショニングとは、

テーブルをデータベース内部で複数の領域(指定キー)に分割する機能

だそうです。

私のイメージではAテーブルにA'というテーブルが違うレイヤーにあるイメージとして捉えています。

本書で発行されるクエリは以下のようなものです。

水平パーティショニングされたテーブルの作成の例

4分割されたテーブルにdate_reportedがはいる。

create table Bugs(
bug_id SERIAL_PRIMALY_KEY
date_reported DATE
) PARTITION BY HASH ( YEAR(date_reported) )
PARTITIONS 4;

パーティションはpostgres, Oracle, mysqlではざっと対応していそう)

垂直パーティショニング

水平パーティショニングは行で(1レコードずつ)分割するが、
垂直パーティショニングは列で分割をする。格納データが膨大な場合に後者を使用する。


\-- 関連テーブルを外部キーで参照するのもパーティショニングのテクニック

create table ProductionInstallers (
product_id BIGINT UNSIGNED PRIMARY KEY,
installer_image BLOB,
FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

例えば、ブログ記事に見出し画像を設定したい場合にバイナリで持つ場合にした時に関連テーブルを持たせる雰囲気です。(BlogDetail?)

この辺あやふやなので後ほど加筆します!



ラクル社の提供する講座&pdf
第10回 パーティションについて
https://www.oracle.com/technetwork/jp/ondemand/database/db-technique/d-12-disk-1484778-ja.pdf

ユニバーサルデザインの機能についてまとめてみる。

前記事から引き続き、UIとユニバーサルデザインについて触れていきます。
こちらの本をベースに記事内容を展開していきますので、よろしくお願い致します。
(著者のユニバーサルデザインに対するこだわりは前記事からどうぞ)

www.amazon.co.jp

ユニバーサルデザインの7原則

前記事でUIやユニバーサルデザインにこだわる背景は紹介したと思うので、今回は本旨に移ります。
そもそもユニバーサルデザインはどのような法則性に則りデザインされているのか見ていきましょう。

wikipediaより

1. どんな人でも公平に使えること。(公平な利用)
Equitable use

2. 使う上での柔軟性があること。(利用における柔軟性)
Flexibility in use

3. 使い方が簡単で自明であること。(単純で直感的な利用)
Simple and intuitive

4. 必要な情報がすぐに分かること。(認知できる情報)
Perceptible information

5. うっかりミスを許容できること。(失敗に対する寛大さ)
Tolerance for error

6. 身体への過度な負担を必要としないこと。(少ない身体的な努力)
Low physical effort

7. アクセスや利用のための十分な大きさと空間が確保されていること
(接近や利用のためのサイズと空間)
Size and space for approach and us


The Center for Universal Design, NC State University による。

本書では12のテクニックがあげられていますが、今回はかいつまんでうち6つを紹介します。

発見性 到達性 判別性
秩序性 柔軟性 連想性
直感性 可読性 理解性
公平性 快適性 審美性

1. 発見性

f:id:letterneginr:20181213205334p:plain コントラストを強調する
・視認性の低い色調同士の配色では、文字が目立たずユーザーに認識してもらえる機会を逃してしまいます。
・あえて他のセクションと差別化させる為、色相ブロックの配置を転換することは有効です。

視認性のコントロールで優先順を明確にする
・上述したように、セクション毎で明度や色調を変える事でユーザーに伝えたい情報の優先順位づけが可能になります。

クリーム色の背景と青色の背景に白い文字
セクションのコントラスト比

視認性のコントロールで可読性を上げる
・しかし、セクション内での色の使い分けは重要です。
薄目にしてセクションを見比べてみると、文字が際立って見える方はどちらでしょうか。
視力が弱い人への配慮を想定する場合にはこのような明度や色調の使い方は重要です。


2. 到達性

f:id:letterneginr:20181213205334p:plain 伝えたいを絞り込む

煩雑さを避けて情報の要約に努める
・大量の情報を受け取った場合に、うまく処理ができず、「対応できない」と感じてしまう場合があります。
・特に高齢者や左脳的な文字面の処理が苦手な人などに対しては不安感や苦手感を与えてしまう可能性があります。
・大量の情報は項目化し、見出しを着色するなどして情報をしやすいようにパターンを決めてみましょう。

項目化された情報
・色を使用できない場合はピクトグラム化(絵にしてしまう)事も有用です。

3. 連想性

f:id:letterneginr:20181213205334p:plain 自然の造形からヒントを得る
・絵を使うと言っても、その意図が伝わるかどうかは文字よりも不確実であることは拭いきれません。
・これは文章にも言えることですが、必ずしもエンジニアの画力が高いとは言えないからです(笑)
ピクトグラムのデザインをする機会があれば、私たちにとって身近で、触れたことがある物に例える事が近道になるかもしれません。

フィッシュボーンで図解されたフロー図
フィッシュボーン
・この本では『フィッシュボーン』という形態図を例に取り上げています。要因を書き出す際にはエゴグラムのように情報を書き出してしまいがちですが、こちらは要素との相関が流れとして表現できるのが魅力です。
・本能的な喚起を促す為、ハチのイラストを取り入れて黄色と黒のコントラストで注意を引く事も有用なようです。
ユーザーにシンボルから連想させる事で、情報の整理を促します。

4. 直感性

f:id:letterneginr:20181213205334p:plain 簡潔な選択肢を提示する
情報の優先順位

・便利な機能を実装しすぎた結果、導線が複雑になり、ユーザーがその使用用途がわからずに迷ってしまうことがあります。
・人は似たような選択肢を見かけた場合に、消去法で情報を整理する場合があります。
・伝えたい内容を強調したり、大項目と小項目に分けて整理する事も重要です。

チャット画面が2パターンあって、吹き出しで説明がないものとあるもの
チャット画面のチュートリアルの例

5. 理解性

f:id:letterneginr:20181213205334p:plain 主体はユーザーである
・プロダクトを使用するのはユーザーです。情報の受け手であるユーザーは、私たちが表現する情報を意図通りに受け止め、
機能の使用の導線まで辿り着くことができない場合もあります。

・だからと言って情報を提示しすぎることは、ユーザーの考える余地を失くしてしまい、UX体験の低下にも繋がってしまうのではないでしょうか。

・ユーザーペルソナを設定し、プロダクトを使用するシナリオを描くことが有効です。
ユーザーがプロダクトを使用した時の経験を想起させる事もこのテクニックでは重要なポイントとなります。

プログラミングの広告例
プログラミングスクール勧誘のビラの例(プログラミングを学んでユーザーがどういう経験を経るのかがフロー立てて紹介されている)

6. 公平性

f:id:letterneginr:20181213205334p:plain 利用する人の気持ちを考える
配色への配慮
・アジア人の20人に1人が色覚異常の特性を発現しているようです。
私の同級生にも色盲の方がいましたが、桃色がグレーに見えるらしいです。
→このような見え方の人に対して柔らかい雰囲気の表現に暖色を使わないという配慮も取れるかと思います。
先の記事で示した通り、世界観は文字の形でも表現することは可能です(場合によるかもしれませんが)

ちなみに、日本人は世界中で一番緑の色調さを見分けることのできる種族のようです。
このような見え方を参考にしてもいいかもしれません。

デザインはロジカルで楽しい

デザインは美しければそれでいいと思う時期があって、素材がきれいでないとダメ、
配色センスがないとダメ、みたいな考え方でいたのですが、表現したいもの、それを伝えたい相手のことを具体的にすることで
自然とデザインはロジカルになることに気がつきました。

こちらの書籍も大変為になるので、興味ある方はぜひ読んでみてください。

エンジニアのための理論でわかるデザイン入門 ThinkIT Books Kindle版

kindle unlimited契約で無料とな👀✨


引用
ユニバーサルデザイン - Wikipedia
Material Designからアイコンをお借りしました
navi.dropbox.jp


(飲食店ネタは尽きている)

UI・ユニバーサルデザインについて思う事をメモしておく。

こんにちは!
記事毎にテンションのムラがある人です。無理しないがモットーなので、極力品質を落とさず見に来てくれる方に新たな知見を見出していただけるような記事を書くことにします🐶笑



今回は緩めな内容ですが、個人的に気になっているUIについてのメモです。

グラフィックデザイナーの為のユニバーサルデザイン実践テクニック51
上記の本を読んだので、共感したポイントや、実際に現場で活用していきたいテクニックをまとめます。

UIを気にしている背景

個人的なポイントは主に2つあります。
①その機能の意図は正しくユーザーに伝わっているか
②そのUIは競合よりもユーザーに受け入れられるものか


①その機能の意図は正しくユーザーに伝わっているか


あるシステム会社で目にした案件の例です。卸業者と顧客がチャット機能を介し、注文が完結するようなシステムの改修に携わったことがありました。
UIはFBのmessengerに似ています。下の見た目に設定や注文ボタンがくっついているようなイメージです。

FacebookのチャットUI
FacebookのチャットUI(5年前)
しかし、チャットから注文フローに行く為に少し癖のあるポイントがあって、注文方法が2パターン存在するものになっていました。注文のステータスによってボタンの文言も変わるので、ユーザーは今自分が何をしていて、このフローのゴールまでのどの位置にいるのかがわかりづらかったようでした。
この機能のリリース後、CSチームはユーザーからの仕様説明に追われる事になり、CS側が機能の把握のキャッチアップに追われたり、開発側でもそもそもこの機能は誰の為、何の為にリリースされたの?という話し合いが持たれたりなどしました。


この事実を重く見た上司は、(チャットルームに入室かつ一度もメッセージを送っていない)ユーザーに対してチュートリアルの展開を実施し、視覚的に用途の説明を促したのでした。
これが功を奏してCSチームに別添えの説明書に載っているような問い合わせは激減したわけです。
文字面ベースの説明ではなく、インタラクティブに動くギミックであることが重要です。
それでも直感的な操作に慣れていない人や、ブラウザによって見方が変わってしまうユーザーに対しては別途の対策を取る必要があります。

②そのUIは競合よりもユーザーに受け入れられるものか

この世にはいろんなアプリケーションが溢れかえり、同じ指向性を持った多数のプロダクトが存在しています。
よくレッドオーシャンなどと例えられますが、その中で差別化を図るポイントは、機能性と同格に位置付けられる見た目にあると思います。

①で説明したように、人はわからんものを敬遠してしまうところがあります。年齢を経ると、予測できないものに対する左記の性質がさらに強化されるとも言われています。
書いてあることが同じでも、分厚い辞書と章毎に分けられた英単語の冊子であれば後者の方が手に取りやすいですし、学習の予測も立てやすいです、個人的には。


さらに言えば、ユーザー層によって好まれる装飾や世界観があります。

飲食店のメディアサイトであれば暖色系のUIが好まれるかと思います。一般的に寒色系の色はビジネスや清涼さを表現するものだからです。また赤に近い色は人の食欲を増進すると言われています。食べログさんやRettyさんは基調色がオレンジ色のUIですよね。


上記の例で言えば、飲食店の情報を求めてやってくるユーザーは掲示されている情報の値踏みをします。
webページの見た目の情報はテキストと画像で構成されていて、ユーザーは目視で到達意欲をそそる飲食店の情報を抽出し、これらの内容を素早く直感的に判別し、必要な情報のみ精査する動きをするかと思います。


下記にあげてある画像は世界観に関しての比較画像です。イメージはタイトルの通りですが、文字・画像・付加要素(罫線、スタンプ)により情報が整理されているのがわかります。
やわらかい印象を与えるフォントを使用する事で、幼さや可愛らしさを表現することができます。
ゴシック調のフォントを使用すればリッチな印象、情報の確実さを助長するような表現ができます。

これはこの記事を目にするユーザー層によって使い分ける事で、プロダクトを選定する基準にもなります。


週刊誌の連載グルメコーナーのイメージ
週刊誌の連載グルメコーナーのイメージ

女子向け雑誌のおすすめグルメコーナーのイメージ
女子向け雑誌のおすすめグルメコーナーのイメージ

ユニバーサルデザインを大事だと思う理由

私はもともと福祉系の仕事をしていました。障害のある方と内職をこなしていく仕事でありましたが、情報伝達は言語だけではなく、視覚や聴覚から得られる情報は彼らにとって非常に有用なものであります。(なんなら聴覚ベースよりも箇条書きの文書を見せただけで仕事の工程を一瞬で記憶する人もいます。)


この部分に私は面白さを感じました。自分の思う相手の感じ方をいくつも想像して、その人に合った集中法を考え、実践するのはとてもやりがいがありました。相手の感じ方にうまく寄り添うことができれば、相手にとって苦手意識の克服や、自己強化の良い思い出になりますし、新しい事に挑戦する自信をつけてもらうことができるのです。


少し話が逸れてしまいましたが、専門学校ではユニバーサルデザインというものを学びました。

wikipediaより

世界初のユニバーサルデザインの提唱は、米ノースカロライナ州立大学デザイン学部・デザイン学研究科(College of Design)のロナルド・メイスによるものである。カリフォルニアにあるユニバーサルデザインセンターの長でもあった彼が1985年に公式に提唱した概念[1]とされる。

「できるだけ多くの人が利用可能であるようなデザインにすること」が基本コンセプトである。デザイン対象を障害者に限定していない点が「バリアフリー」とは異なる。

小学校の時に鉛筆の握り方を矯正する器具を使ったことがありますか?あれは治具というものですが、あれもユニバーサルな設計が取り入れられています。指先の発達が未熟な為に、鉛筆の握りが困難な人の為に作られた製品です。

鉛筆を握られなければ昔は文字を書くことができませんでした。しかし、今では発声から文字入力を手伝うデバイスもありますし、パネルから指で書いた文字を推測し、変換してくれるミドルウェアもあるでしょう。


表現方法は多様化し、普及しつつあります。
それでもその高速な進化を遂げたメソッドの扱い方に戸惑いを覚え、人の利益の発展や幸せの為に設計されたプロダクトを使用するところまで行き着かず、
一線を引かれてしまう事例もこれから出てくるのではないかと考えます。


私個人としてはこれが残念に思えて仕方がないのです。
見方や使い方に工夫をする事でアプリをシェアすることが出来、そこから得られる素晴らしい体験を出来ない人たちがいるというのは寂しいことです。

抵抗や偏見を排し、安全に使用できるプロダクトを生み出していくのはエンジニアの使命だと感じる部分があります。

抜粋実践テクニックは次の記事から始めます🙇‍♂️🙇‍♂️🙇‍♂️


引用
www.recode.net

SQLアンチパターンを読んだのだが、論理設計編のまとめがようやく終わる。

サボっていたらだいぶ日が空きました、DB論理設計編のまとめです。
結構散文化としてしまっていますが、よろしければ引き続きご覧くださいませ🐶

ようやく完結、DB論理設計編。

1. ジェイウォーク(信号無視)
2. ナイーブツリー(素朴な木)
3. IDリクワイアド
4. キーレスエントリ
5. EAV(エンティティアトリビュートバリュー)
6. ポリモーフィック関連


EAV(エンティティアトリビュートバリュー

select date_reported, COUNT(*)
from Bugs
group by date_reported;

これはバグテーブルからdate_reported毎に集計した数を出力しています。
ただし、日付のフォーマットが異なる為にこれを整備できないとしたらどのような方法を取るのがベターなのでしょうか?


可変属性をサポートしたい場合

オブジェクト指向設計になぞらえるならば、基底のモデルを拡張してサブクラスを立てることができます。
インスタンスは同じ基底クラスを持ち、サブタイプのインスタンスでもありますが、
あるサブタイプの持つ属性は基底型や他のサブタイプに存在するとは限りません。
このような例を1行のレコードに格納したい場合、自ずとカラムの定義が揺らぐことになります。

アンチパターンの実現例

属性テーブルの用意
1つのモデルに対し、属性(カラム)を内包したテーブルを作成します。
これが実現するパターンは、カラムの存在意味と名前がロジックに基づき固定されている場合であり、
無闇に列を増やしていけば管理がさらに複雑になることが想定されます。

投げるクエリが複雑になる

単純にデータのidと報告日が見たい!
select issue_id, date_reported from issues;
EAV設計の場合
select issue_id, attr_value as date_reported
from IssueAttributes
where attr_name = 'date_reported';

データ整合性の保ち方

date_reportedが設定されていない場合の運用が決定されていない
報告書がまとめられない…
date_reportedが設定されていないデータのためにクエリを投げて検査結果をメールで寄越す?適当な日付を入れてしまう?

SQLのデータ型扱いづらい問題

このattr_nameはStringで定義されているため、日付型でないデータも許容します。
計算結果を挿入するデータをBIGINTなどで定義してから、うっかりDECIMALやUNSINGEDなデータが投げられてしまったら、
このテーブルはデータ更新を拒否するかもしれません。

参照整合性を強制できない

薄々感づくところもあるかもしれませんが、attr_nameが外部キーであった場合に、
他のテーブルでも同じ型でこのデータを参照する必要があり、かつこのデータに一致することが強制されます。
attr_dateが文字列型であるのに、外のテーブルからTIMESTAMP型としてこれを参照することは出来ません。

(データを参照するためにjoinの手間がかかる…)

ソリューション

サブタイプのモデリングを行う

シングルテーブル継承(Single Table Inheritance)
 基底クラスと関連データを一つのテーブルにまとめ、タイプでサブクラス識別できるように設計する。
 タイプ毎に使用するカラムを定める。Ruby on RailsActiveRecordがこの設計を採用している。

基底クラスとそのサブクラスをSTIに則って設計する図

具象テーブル継承(Concrete Table Inheritance)

 サブタイプ毎にテーブルを設計する。サブタイプを判別するカラムを入れずに設計できる。
 基底型に設定されているデータかの判別がしづらく、共通部に新たなカラムを加えたい場合に共通テーブルの変更が必要になる。
 サブタイプに関わらずデータを取得したい場合、UNION句の使用によりビューを作成することで実現できる。

クラステーブル継承(Class Table Inheritance)

 オブジェクト指向に則り、一つのテーブルを一つのクラスとみなして設計する。
 サブクラスは基底クラスのidを参照し、外部キーで関連性が保たれる。
 基底クラスからサブクラスへは1対1のリレーションが強制される。

半構造化データ

 頻繁に新しい属性が追加され、基底クラスの定義が揺らぐ場合やサブクラスの数が多い場合はLargeObjectを追加し、 
 属性名と値をjsonxmlでtext型に格納する。
 拡張性が高く、各行に異なるサブタイプを格納することも可能。

 ※ SQLがLOBにアクセスできる術がない為、アプリ側でデータをselectした後に分解する必要がある。

CloudDataStoreでこんなの見たな。ここからインスピレーション受けたのかしら…


ポリモーフィック関連

サブクラスそれぞれに紐つくCommentsテーブルが欲しいけれども、どう実装しよう?

同じ基底クラスを持つBugs, FeatureRequestsですが、新たなCommentsテーブルの実装にはひとひねりが必要そうです。
同じ外部キーを通して関連性を持つことはできない為、ポリモーフィック関連(Polymorphic Associations)というテクニックを使います。
プロミスキャス・アソシエーションという別名は、複数のテーブルを参照できる為に無差別な関連という意味で使用されます。


ポリモーフィック関連の定義

Commentsテーブルには、サブクラスを判別するissue_typeが定義されます。
その他の外部キーはaccounts_id一種のみです。
ポリモーフィック関連の特徴は、参照整合性制約を定義できない部分にあり、
言い換えればissue_typeに定義されている種類も、親のissue_idも、本当に親テーブルで定義されているものかはわからないのです。

-- データを抜くときの注意

issue_idはBugs, FeatureRequestsの両テーブルに同じ値の主キーを持つ可能性を孕んでいます。
正確に紐つくデータを抜き取るには、issue_typeも同時に使用することが重要です。
両方のテーブルを参照したい場合は外部結合を使います。


まとめてみてどうだったか

事例まで挙げるとひたすらに長い。読者が疲れない程度に情報を分割することも重要。
この辺は自分の知識不足もあるので、SQL意外で置き換えられるように知識を反復して吸収することも大事。
 -> 👿👿👿

発行するSQLはぼやっとしている
 -> SQLのバリエが少ない。HavingとかSQLの関数についてもっと知れるとアプリ側の実装のバリエも広がりそう。

効率的にテーブルを舐める設計がうまくいかなかった
 -> 設計(経験)あるのみなんじゃないか

これらが実際にSQLを書きながらなんとなくでも前に進めた実感はある
 -> ◎