駆け出しWebデザイナーに向けて。UI・UXを考察するにあたってのアドバイス

自分なりにまとめてみた。けっこう抽象的な内容。

自然な流れにする

まず自然とはなにかということを考えると

  • 流行のUI・UXと同じ(あるいは模した)構造になっているか
  • アニメーションイージングなどで自然現象(摩擦や反動など)が考慮されているか
  • 文脈が正しいかどうか(突拍子のないプロセスとなっていないか)
  • サイト全体の文脈に逆らっていないか(同じUIで実現可能なのに例外を作っていないか。UIが統一されているかどうか)

など一般論や自然現象が成立しているかどうかである。
すべて重要な要素だが、特にアニメーションイージングの自然現象の考慮は後回しになりがちである。
マイクロインタラクションの領域でもあるのだが、僕が特に意識しているのがヘッダーメニューやフッターメニュー。
コーポレートサイトの場合にはすべてのページで同じヘッダーフッターを採用することになると思うのだが、サイト回遊でメインで利用されるリンクが集まっており、一番ユーザーが操作する領域である。
そのため、個人的にはヘッダーフッターでサイトの使いやすさの5割が決まるといっても過言でないと思っており、ヘッダーフッターメニューが快適に操作できないサイトはUI・UXが優れていないと断定できると思う。

考えるべきことを減らす

システム設計についても言えることだが、複雑な方程式は好かれない。
理解や操作が容易であることが大前提である。
具体的な判断材料は下記。

  • ユーザーの選択肢を(機能性を失わず可能な限り)少なくすること
  • 目標に至るまでのユーザーの操作手順を少なくすること
  • 操作手順を言語で簡単に示せること(言葉で説明しにくいものはUIが難しいことと同義)

スピードは命

UI反応速度、ページの表示速度はUXに直結する。
エンジニアの力量ではカバーできない領域もあり、デザイナー自身でも意識しなければいけない。
具体的な意識としては、

  • レイアウトを頑張らない(複雑なレイアウト、多種のレイアウトを作らず、設置する画像に注力する)
  • コンポーネントの種類・サイズを限定する(シンプルなコンポーネントの組み合わせでデザインする。Atomic Designを意識)

両者ともに言えるが、要するにシンプルなデザインにするということだ。
シンプルにすることによって、いくつかのメリットがある。

  1. CSSの軽量化・最適化(=表示速度の向上)
  2. 保守性の向上
  3. CSSコーディング時間の削減
  4. CMSの場合、エディトリアルの単純化(テンプレートファイルの削減)
  5. サイト全体のデザインの統一性の担保

特に2と3が大きい。
保守性が高くなることで、改修などでのCSSファイルの肥大化を減少させてくれる。
またフロントエンドエンジニアのリソースが少ない組織の場合、今のフロントエンドはJavaScriptに注力すべきであり、CSSコーディングになかなか力が入れられないため、この手間が軽減されることでエンジニアの評価はだだ上がりすること間違いなしである。

シンプルなデザインでも、よくあるスクロールに応じたアニメーションなどをつけたりなどすることで、複雑なレイアウトよりも効果的だったりするので、余った時間をそちらのリソースに割く方針のほうがなにかと都合がいいと思う。

適正なサイズ感覚を身につける

かっこ良さを追求するとコンポーネントサイズやフォントサイズを小さくするデザイナーがいたりするが、そういったことはUIにとって大抵悪影響である。
実際のブラウザ表示サイズで確認し、半目にして見えづらい状況で確認したり、遠くからみてみたりして、視認・操作がしやすいサイズかを検証してほしい。

余談だがデザイン学部時代、英語での表記を多様する学生がいて、見兼ねた先生がそいつに英語を使わずデザインするよう指示していた。
どうしようもなくデザインしようがない場合には、そういった小手先のテクに走ってしまうのも仕方がないが、それほど切羽詰まっていない場合には控えてもらうようデザイナーに伝えたいのがエンジニアとしての本音である。

ジェネレーターについて

個人的にReduxの非同期処理は基本はMiddlewareを使わずコンポーネントに処理を書くことが多いが、redux-sagaでなんとなく使っていたジェネレーターについて復習がてら筆を執った次第。

function* generator() {
  yield 'A';
  yield 'B';
  yield 'C';
  yield* ['D', 'E', 'F'];
  let test1 = yield 'G';
  let test2 = yield 'H';
  yield* [test1, test2];
}

const gen = generator();

console.log(gen.next()); // { value: 'A', done: false }
console.log(gen.next()); // { value: 'B', done: false }
console.log(gen.next()); // { value: 'C', done: false }
console.log(gen.next()); // { value: 'D', done: false }
console.log(gen.next()); // { value: 'E', done: false }
console.log(gen.next()); // { value: 'F', done: false }
console.log(gen.next()); // { value: 'G', done: false }
console.log(gen.next('I')); // { value: 'H', done: false }
console.log(gen.next('J')); // { value: 'I', done: false }
console.log(gen.next()); // { value: 'J', done: false }
console.log(gen.next()); // { value: undefined, done: true }
function* generator(count) {
  while (1) {
    yield count++;
  }
}

const gen = generator(0);
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: 4, done: false }

イテレーター、あるいは途中で止まる関数として非同期処理を順序良く実行するのに使用機会がある。

しょぼいエンジニアの特徴をひたすら挙げていく

常識がない

別業種の人からみるとエンジニアの作業はブラックボックス化されているが、実際はプログラムという言語を使って、機械が理解するためにわかりやすく、順序立てて説明することに等しい。
つまり第一言語でうまく説明したり常識的な回答を見い出せる人は、プログラミングも必ずうまくやれる(これが一般的なベンダーで文系プログラマーのほうが活躍できると謳っている理由)。
逆に言えば、常識がない人はプログラミングがうまくない。

ブラインドタッチができない

ブラインドタッチができないのは、プログラムを書いている時間が短いからに他ならない。
Qiitaで知識だけ得て手を動かさない頭でっかちが現場でできることはといえば、抽象的な仕様書を書き曖昧な指示を送ることだけだ。
口だけが達者なエンジニアは新しい技術情報を仕入れる際に、そのツールの名前や使い方を単純に覚えるだけだが、本当に必要なのはそういった選択肢が存在するという事実を理解し、その背景を把握することである。

特定の技術に固執している

新しい技術に積極的ではないとも言える。
現在自分ができる範囲から飛び出したものを学ぶ姿勢がなければ成長が難しい。
ストックがないから、プログラム上で個人の「こだわりの独自ルール」を適用してしまいがちになり、他人からはブラックボックスとなってしまう。

少し話がそれるが、2019年現在、Web系エンジニアが下記のいずれかで深い知識がないと優秀とはいえないと思う。

  • 機械学習
  • AWS(をすぐに使いこなせるようになるほどのインフラ知識)
  • ReactなどのいわゆるMVVMフレームワークとReduxなど状態管理フレームワークを使った開発
  • WebGLのシェーダー

それ以外のWAI-ARIAだったりレスポンシブ用のCSSコーディング、バンドラーの知識やWordPressなどは、結局のところ突き詰めて開発を進めていくと上記項目のいずれかを習得する必要がある。
機械学習とAWSはバックエンド向けだが、Reactやシェーダーに詳しいフロントエンドエンジニアがHTML・CSSなどの基礎技術が不自由であるとは考えがたい。
またAWSと書いたのは、バックエンドにマイクロサービス化(APIサーバー化)が求められる中で確実に一度は通る道だからだ。

本質を話さない(会話・文章内容が曖昧)

(エンジニアに限ったことではないが)本質の理解ができていないと適切なリファクタリングができない。
例えば、仕様についてディレクターなどプログラムに精通していない人にできる・できないの判断を仰がれるときに、自分の軸で話しているか、あるいは技術的なレベルでするか・しないかというケースに分けて会話しているかという点に着目すると、技術レベルがよくわかる(時間がなくイエスノーのみで答えてしまう場合もあるとは思うが)。

自分の書いたコードに責任を持っていない

Webで調べたものを動作検証などをせずコピペで済ませたり、引き継ぎの際に明確なドキュメントあるいは十分な言葉を渡さないなど、そのコードに責任を持っていない人は仕事にドライといえるだけでなく、作る際に何も考えていなかったために単純に思い出すのが困難だからである。
情熱を持ったエンジニアであれば、それを面倒とは思わず積極的に関わるであろう。
「これオレが作ったんだぜ!」って自慢できるようなプロダクトを毎回作れば自然とコードに責任が持てるようになる。


…と偉そうに書き連ねてみたが、他人から見たら自分はどうなんだっていう。。

ReactのsetStateの注意点

将来的な非同期レンダリングのため、setState内ではstateを読み込まない。

その代わりsetStateの第一引数に関数を指定するとその関数内で現在の値を取得できるため、それを利用する。

// stateがリテラルの場合
import { useState } from 'react';
const [stateCount, setStateCount] = useState(0);

<button type="button" onClick={() => setStateCount(beforeCount => beforeCount++)}>インクリメント</button>
// stateがオブジェクトの場合は関数でないとキーの一部を変更する処理ができない
import { useState } from 'react';
const [stateItem, setStateItem] = React.useState({title: 'hoge', text: 'hoge'});

const onChangeText = e => {
  const text = e.target.value;
  setStateItem(oldState => ({...oldState, text}));
}

<input type="text" value={stateItem.text} onChange={ onChangeText } />

Netlify Functionsのテスト方法

Netlify FunctionsとはNetlify版のいわゆるFaaS(ファース・Function as a Service)。

Netlify Functionsの使い方としてはnetlify.tomlという設定ファイルでNetlify Functionsの関数を置く場所を指定しファイルを置くとエンドポイントが自動で付与されるので、それを使用する感じ。

テストはnpmでnetlify-lambdaというパッケージが配布されているため、それを用いる。

$ npm init -f
$ npm install netlify-lambda

次に設定ファイルのnetlify.tomlを用意する。

$ touch netlify.toml
$ vi netlify.toml

[build]
	functions = "functions"

上記の設定により、functionsディレクトリ内にNetlify Functionsのファイルを置けるようになった。

次にsrcディレクトリ内に関数ファイルを設置する。

$ mkdir src
$ touch src/test.js
$ vi src/test.js

exports.handler = (event, context, callback) => {
  callback(null, {
    statusCode: 200,
    body: 'Hello World!!',
  })
};

そして下記のコマンドでテストしてみる。

$ npx netlify-lambda serve ./src/

そうするとコンソールに下記のような感じでポート番号が書かれるのでブラウザでアクセスしてみる(下記の例ではhttp://localhost:9000)。

Lambda server is listening on 9000

問題ないようであれば、package.jsonに下記のbuildコマンドを記述し、netlify.tomlにそのbuildコマンドを実行するように指定する。

$ vi package.json

~ 略
"scripts": {
  "build": "netlify-lambda build ./src/"
},
~ 略
$ vi netlify.toml

[build]
	functions = "functions"
	command = "npm run build"

functionsディレクトリはgit管理しないようにし、pushすると、自動ビルドされるようになる。
これで一旦ひと通りの流れは完了となる。

Netlify Functionsは内部的にはAWS Lambda(ラムダ)を使っているらしい。

無料版では2019年6月24日現在、月に125,000リクエスト、実行時間は100時間まで利用できるため、個人で使うぶんには問題なく無料で使えそう。
ただしURLはNetlify独自の形式から変更できない、メモリは128MB、実行時間は10秒までとなっている。

GithubでOSS参加するためのコマンド集

(1)Githubのforkボタンをクリック

(2)Cloneする

$ git clone https://github.com/isaxxx/~

(3)開発用ブランチの作成

$ git checkout -b develop
$ git branch
* develop
  master

(4)開発用ブランチで変更を加え、コミット・プッシュ

$ vi README.txt
$ git status
~
 modified: README.txt
~
$ git add README.txt
$ git commit
$ git push origin develop

(5)Branchをmasterに変更し、Fork元リポジトリをローカルで管理する

$ git checkout master
$ git remote add upstream https://github.com/~/~
$ git fetch upstream
$ git branch -a
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master
  remotes/origin/v1
  remotes/origin/v2
  remotes/upstream/master
  remotes/upstream/v1
  remotes/upstream/v2

(6)Fork元リポジトリの最新バージョンを取得し、ローカルのmasterを更新・pushする

$ git fetch upstream
$ git merge upstream/master
$ git push origin master

(7)ローカルのmasterと開発用ブランチをマージする

$ git merge develop

(8)Github上でPull Requestを送る

WordPressセキュリティ対策

wp-cron.phpを無効化

/* wp-config.php に追記 */
define('DISABLE_WP_CRON', 'true');

※wp-cron.phpを無効化した場合、予約投稿や通知機能などが動作しなくなるため、サーバーcronを利用

$ sudo vi /etc/crontab
# 1分ごとにcronを実行
* * * * * apache /usr/bin/php ~/wp-cron.php > /dev/null 2>&1

xmlrpc.phpのアクセス制限

# vi ~/.htaccess

<Files xmlrpc.php>
Order deny,allow
Deny from all
</Files>

wp-login.phpをアクセス制限

# vi ~/.htaccess

<Files wp-login.php>
Order deny,allow
Deny from all
Allow from xxxx.xxxx.xxxx.xxxx
Allow from xxxx.xxxx.xxxx.xxxx
...
</Files>

wp-login.phpにBasic認証を設置

# vi ~/.htaccess

<Files wp-login.php>
AuthType Basic
AuthUserFile ~/.htpasswd
AuthName "Please enter your ID and password"
require valid-user
</Files>

wp-comments-post.phpのアクセス制限

# vi ~/.htaccess

<Files wp-comments-post.php>
Order deny,allow
Deny from all
</Files>

wp-trackback.phpのアクセス制限

# vi ~/.htaccess

<Files wp-trackback.php>
Order deny,allow
Deny from all
</Files>

複数設定例

# vi ~/.htaccess

<Files ~ "^(wp-config|wp-cron|xmlrpc)\.php$">
Order deny,allow
Deny from all
</Files>

wp-adminディレクトリ以下(admin-ajax.phpを除く)をアクセス制限

# vi ~/wp-admin/.htaccess

Order deny,allow
Deny from all
Allow from xxxx.xxxx.xxxx.xxxx
Allow from xxxx.xxxx.xxxx.xxxx
...
<Files admin-ajax.php>
Satisfy Any
Order allow,deny
Allow from all
Deny from none
</Files>

wp-adminディレクトリ以下(admin-ajax.phpを除く)にBasic認証を設置

# vi ~/wp-admin/.htaccess

AuthType Basic
AuthUserFile ~/.htpasswd
AuthName "Please enter your ID and password"
Require valid-user
<Files admin-ajax.php>
Satisfy Any
Order allow,deny
Allow from all
Deny from none
</Files>

wp-config.phpのアクセス制限

# vi ~/.htaccess

<Files wp-config.php>
Order deny,allow
Deny from all
</Files>

メールアドレスがブラックリストに登録されているかどうかを判断する方法

サーバーから送信するメールがGmailで迷惑メール扱いになったときにDNSのSPF(Sendor Policy Framework)の設定やDNSの逆引き設定(IPアドレスからホスト名を調べられるようにする)や、PostfixのプロトコルをIPv4、メールの文言などをチェックしたけど、どれもできてるってときには、メールアドレスがブラックリストに入ってないかどうかを下記のサイトから調べてみる。

http://www.blacklistalert.org/

ヒットしたらListedの文字が確認できるので、そのリンクを押して解除申請を行う必要がある。

使用歴のあるドメインの場合は要注意。