ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

保育業界に携わるエンジニアが考えていること。

こんにちは。エンジニアの田渕です。 GWで最大9連休!なんて声も聞こえますが、人が少ない時ほど働きたい天邪鬼です。 (いや、単純に電車が空いてるからって話ですが。。。)

ユニファのエンジニアブログも、気づけば開始から一年以上が経過しています。 今回は、保育業界に携わるエンジニアとしての、この一年ほどの自分の活動を振り返ってみました。

ちょうど一年前のこと。

ちょうど一年ほど前のことです。 この「ユニファ開発者ブログ」にて、こんな記事を書かせて頂きました。

tech.unifa-e.com

この4月から実際に適用が開始されている新「保育所保育指針」に関する内容でした。 読んで頂くと分かる通り、当時出たばかりの新「保育所保育指針」の原文を読んだり、解説している講座に足を運んだり、関連したブログやWeb上の記事を読んだりと、この頃から色々なことを始めました。 自社サービスを持つ会社のエンジニアである以上、ある程度は「顧客」=「保育士や保護者の方々」に対しての理解は必要です。 しかし、これまで黙々と開発していたWebエンジニアがある日突然、保育関連の省庁の文章などを読み出したのですから、前職からの知り合いなどからは「何やってんの?」と盛大に突っ込まれました。

「普通」ってなに???

突然そんなことを始めたのには、当然理由がありました。 当時、エンジニアとして様々な機能の要件を定義したり、開発したりしていましたが、自分の中のそれまでの「普通」が通用しないという現実をひしひしと感じていたのです。

「これ、こうしたら喜んでくれるんじゃない?」と思って作ったものが喜んでもらえない。
「こうしたら使いやすくなる。」と思って作ったものが、「使いづらい」と言われる。

明らかに、保育士の方々の感覚に合わせられていませんでした。 新しいプロダクトや機能を開発する際にはヒアリング、テストも行いますので、感覚として分からなくてもそこで調整することで良いものは作れます。 ですが、持って行ったものが全然求められていない/的外れである場合、そこから良いものにするまでには、長い時間と手間がかかってしまいます。 完璧ではなくても、出来るだけ始めから及第点に近いものを持っていけるようになりたい。

「肌感覚として保育士の方々に喜んでもらえるものが分からない」というのは、当時の私には致命的に思えました。

コーディングなどにも当てはまることですが、何かを修正する際、あまりに変更量が多い場合は作り直した方が早かったりもします。 「自分の感覚を保育士の皆さんの感覚に近づける」という行為は、私にとってはまさにそれでした。 ちょっと微修正で辿り着ける気は全くしなかったので、これは一度自分の中の「普通」を壊してやり直そう、と思ったのです。

そんなわけで、黙々と保育所保育指針を読み、関連書籍を漁り、社外の勉強会に参加し、保育士の方々の「普通」を知るため、活動を始めました。

始めから長期戦になるだろうなぁと思っていたので、地道に、コツコツと……。。。

良薬口に苦し

昨今、関連省庁からICTに関する補助金が出ている流れなどもあり、雑誌や勉強会などでも度々保育関連のシステムに関する話題が出ます。 勉強会では特に自分の身分を明かしている訳ではないので、一般的なシステムというものに対する保育士のみなさんの印象や感想をそのまま耳にすることもあります。

「うちの園では最近、なんかシステム導入したんだけど、使い慣れないから時間がかかって子供を見る時間が減った。」
「上の人たちが入れろって言うから入れたけど、全然良さが分からない。」
「これも世の流れなのかしらね。」

正直に言って、ネガティブな言葉の方が圧倒的に多いです。耳が痛い……と思うこともしばしば。 保育システム導入に関しての特集記事などを見ても、現場に近ければ近いものほど「これはもう、避けられない流れなのだから、頑張って受け入れよう!」という、どちらかといえば「諦めて受け入れよう」という論調が多い。 確かに、現時点で様々な技術を含むシステムが保育業界に対して出来ている貢献は、他業種と比べると圧倒的に少ないのです。

ですが、こうして地道な活動を始めて一年、始めた頃に書いた前述の記事を読むと、その頃に比べたら色々なことが感覚として分かるようになったなぁと感じています。 システムに対する印象がネガティブなものになりがちな理由も、わかってきました。

エンジニアが見る夢

最近思うのは、恐らくはシステムを作っているエンジニアが見ている夢が、正しく保育士の皆さんに伝わってないんだな、ということ。 ともすれば、相反し、敵対するものとさえ考えられています。 たぶん、保育関連システムの開発に携わっているエンジニアの中で「保育士さんの仕事を邪魔しよう」なんて考えて開発している人は一人もいないのに、そんな風になってしまう現実は悲しくもありますが、システムを作っている我々の不理解や、力量不足、説明不足な面もあると思っています。

システム化の先で我々エンジニアが夢見ているもの=「本来の目的や将来像」がひとめで伝わり、受け入れてもらえるプロダクトが作れればいいんですが、……なかなか簡単にはいかないものです。

今後も、現場の保育士の方々の声に真摯に耳を傾けながら、少しでもお役に立てるものを作っていけたらと考えています。

それでは。

Raspberry Pi と距離センサーでトイレセンサーを作ってみた

 皆様こんにちは。ユニファの赤沼です。ユニファでは様々な職種で採用を続けていまして、今年に入ってさらにメンバーが増えています。今のオフィスには昨年11月に移転したばかりですが、早くもスペースが埋まって来ました。人数が増えて困ることの一つがトイレ事情ですね。特に今のオフィスでは男性トイレの個室が一つしかなく、行ってみたけど使用中で戻ってくるのを繰り返す、ということも発生するようになって来ました。そこで多少でも状況を改善できないかと、手元にあった機材でトイレセンサーを作ってみました。

サービス構成

 サービスの全体像としては、個室の使用状況をセンサーで検知し、ステータスが変わった時に Slack に通知するというシンプルなものです。今のオフィスのトイレはドアの開閉は使用状況に連動しない(空室でもドアが閉めておける)のでどうやって使用状況を判定しようか迷ったのですが、電源を取れる場所の都合などもあり、ひとまず距離センサーで近くに何かを検知した場合は人が入って来たということで使用中のステータスとするようにしました。ステータスは空室(Vacant)か使用中(Occupied)のいずれかです。ネットワークへの接続はオフィスの AP が利用できる範囲だったので、 Wi-Fi で接続しています。

回路図

 まずは回路図です。下記の図では作図素材の都合上 Raspberry Pi 3 を使っていますが、実際は Raspberry Pi Zero W を使用しています。

www.switch-science.com

 距離センサーとしては今回は超音波センサーを使用しています。

www.switch-science.com

 また、見た目で稼働状況がわかるように LED を配置しています。それぞれ下記のようにGPIOピンを接続します。

【距離センサー】

  • VCC - 2番ピン(5V Power)
  • TRIG - 11番ピン(GPIO17)
  • ECHO - 13番ピン(GPIO27)
  • GND - 9番ピン(GROUND)

【LED】

  • アノード - 12番ピン(GPIO18)
  • カソード - 9番ピン(GROUND)

f:id:akanuma-hiroaki:20180426223016p:plain

スクリプト実装

 それでは上記回路をしようするためのコーディングです。今回は Python で実装してみました。まずは距離センサーを扱うクラスを下記のように実装しました。コンストラクタでは使用するピンやロガーの設定をしています。超音波センサーの仕組みとしては、TRIGピンから出したパルスが対象物に反射してECHOピンで受け取れるまでの時間から距離を計算します。詳細については先ほどの製品ページのサンプルなどもご覧いただくとしてここでは割愛しますが、かかった時間を計算する calc_duration() メソッドと、それをベースに距離を計算する distance() メソッドを用意しています。

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time
from logging import getLogger, FileHandler, Formatter, DEBUG
from timeout_decorator import timeout, TimeoutError

class DistanceSensor:
    TRIG_PIN = 17
    ECHO_PIN = 27

    DEBUG_LOG_FILE = 'logs/distance_sensor_debug.log'
    TIMEOUT_SEC = 3

    def __init__(self):
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.TRIG_PIN, GPIO.OUT)
        GPIO.setup(self.ECHO_PIN, GPIO.IN)

        self.debug_logger = getLogger(__name__ + '_Debug')
        debug_file_handler = FileHandler(self.DEBUG_LOG_FILE)
        formatter = Formatter('%(asctime)s:%(levelname)s:%(message)s')
        debug_file_handler.setFormatter(formatter)
        self.debug_logger.addHandler(debug_file_handler)
        self.debug_logger.setLevel(DEBUG)

    @timeout(TIMEOUT_SEC)
    def calc_duration(self):
        GPIO.output(self.TRIG_PIN, GPIO.LOW)
        time.sleep(0.3)

        GPIO.output(self.TRIG_PIN, GPIO.HIGH)
        time.sleep(0.00001)
        GPIO.output(self.TRIG_PIN, GPIO.LOW)

        pulse_off = None
        while GPIO.input(self.ECHO_PIN) == 0:
            pulse_off = time.time()

        if pulse_off is None:
            self.debug_logger.debug('pulse_off is None.')
            return None

        pulse_on = None
        while GPIO.input(self.ECHO_PIN) == 1:
            pulse_on = time.time()

        if pulse_on is None:
            self.debug_logger.debug('pulse_on is None.')
            return None

        duration = pulse_on - pulse_off
        return duration

    def distance(self):
        try:
            duration = self.calc_duration()
            if duration is None:
                return None

            distance = duration * 17000
            return distance

        except TimeoutError:
            self.debug_logger.debug('TimeoutError while calcurating duration.')
            return None

 また、 slack への通知処理も下記のようにクラスを分けて実装しています。APIのコールには Requests モジュールを使用しています。

#!/usr/bin/env python

import json
import requests

class SlackNotifier:
    def __init__(self, webhook_url):
        self.webhook_url = webhook_url

    def notify(self, fallback, text, username, icon_emoji, channel, color):
        headers = {
            'Content-Type': 'application/json'
        }

        payload = {
            'username':    username,
            'channel':     channel,
            'icon_emoji':  icon_emoji,
            'attachments': [
                {
                    'fallback': fallback,
                    'text':     text,
                    'color':    color
                }
            ]
        }

        response = requests.post(self.webhook_url, json = payload, headers = headers)

        return {
            'status_code': response.status_code,
            'text':        response.text
        }

 そしてこれらのクラスを使用して処理を行うメインのクラスを下記のように実装しています。1秒おきに距離を取得していますが、距離センサーの測定値にはばらつきがあり、温度や対象物の素材によっても音波を反射しやすいかどうかが変わってくるので、単発の測定値だけで判定するのではなく、直近10回分の測定結果から判定するようにしています。10回のうち8回以上閾値より近くに何かがあるという結果になったら使用中のステータスに変更し、2回以下になったら空室ステータスに変更します。3回〜7回の場合はステータスを変更しません。入室時や退室時は閾値を越えたり越えなかったりという感じになるので、その揺らぎを吸収するという意図もあります。閾値より近くに物を検知した場合は LED を点灯させます。ステータスが切り替わった場合には slack に通知します。

#!/usr/bin/env python

import distance_sensor
import slack_notifier
import time
import RPi.GPIO as GPIO
from logging import getLogger, FileHandler, Formatter, DEBUG

class RestroomMonitor:
    SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX'
    SLACK_USERNAME    = 'RESTROOM_TOKYO_MENS'
    SLACK_EMOJI_ICON  = ':restroom:'
    SLACK_CHANNEL     = '#tokyo_restroom_mens'

    LOG_FILE = 'logs/restroom_monitor.log'

    THRESHOLD_CM = 108
    OCCUPIED_THRESHOLD = 0.8
    VACANT_THRESHOLD = 0.2
    LED_PIN = 18

    def __init__(self):
        self.logger = getLogger(__name__)
        file_handler = FileHandler(self.LOG_FILE)
        formatter = Formatter('%(asctime)s:%(levelname)s:%(message)s')
        file_handler.setFormatter(formatter)
        self.logger.addHandler(file_handler)
        self.logger.setLevel(DEBUG)

        self.distance_sensor = distance_sensor.DistanceSensor()
        self.slack_notifier = slack_notifier.SlackNotifier(self.SLACK_WEBHOOK_URL)

        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.LED_PIN, GPIO.OUT)

        self.threshold_queue = [0] * 10
        self.occupied = False

    def notify_to_slack(self, occupied):
        fallback = 'Occupied' if occupied else 'Vacant'
        text = 'Occupied' if occupied else 'Vacant'
        color = 'warning' if occupied else 'good'
        res = self.slack_notifier.notify(
            fallback, text, self.SLACK_USERNAME, self.SLACK_EMOJI_ICON, self.SLACK_CHANNEL, color
        )
        self.logger.debug(
            'Notified to Slack. STATUS_CODE - {status_code}, MSG - {msg}'.format(
                status_code = res['status_code'], msg = res['text']
            )
        )

    def judge_occupation(self, distance):
        threshold_queue_value = 1 if distance <= self.THRESHOLD_CM else 0
        GPIO.output(self.LED_PIN, GPIO.HIGH if threshold_queue_value == 1 else GPIO.LOW)

        self.threshold_queue.append(threshold_queue_value)
        del self.threshold_queue[0]

        average = sum(self.threshold_queue) / len(self.threshold_queue)

        if average >= self.OCCUPIED_THRESHOLD:
            occupied = True
        elif average <= self.VACANT_THRESHOLD:
            occupied = False
        else:
            occupied = self.occupied

        self.logger.debug(
            'QUEUE - {queue} {distance} {average} {occupied}'.format(
                queue = self.threshold_queue, distance = distance, average = average, occupied = occupied
            )
        )

        return occupied

    def execute(self):
        while True:
            distance = self.distance_sensor.distance()

            if distance is None:
                self.logger.debug('Distance is None.')
                time.sleep(1)
                continue

            occupied = self.judge_occupation(distance)
            if self.occupied != occupied:
                self.occupied = occupied
                self.notify_to_slack(self.occupied)

            time.sleep(1)

設置

 実装が終わったら実際にトイレに設置します。個室内にAC電源があるのでそこから micro USB で給電し、トイレットペーパーホルダー上に配置します。ブレッドボードとラズパイの裏には養生テープを丸めて簡単に固定しています。

f:id:akanuma-hiroaki:20180426234619j:plain

f:id:akanuma-hiroaki:20180426234659j:plain

スクリプト実行

 設置したら ssh でログインしてスクリプトを実行します。

$ ./restroom_monitor.py &

 ログには下記のように出力されていきます。

2018-04-25 09:53:35,610:DEBUG:QUEUE - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 109.69352722167969 0.0 False
2018-04-25 09:53:36,924:DEBUG:QUEUE - [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] 106.19568824768066 0.1 False
2018-04-25 09:53:38,236:DEBUG:QUEUE - [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] 81.27307891845703 0.2 False 
2018-04-25 09:53:39,551:DEBUG:QUEUE - [0, 0, 0, 0, 0, 0, 0, 1, 1, 1] 80.18684387207031 0.3 False 
2018-04-25 09:53:40,862:DEBUG:QUEUE - [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] 75.01912117004395 0.4 False 
2018-04-25 09:53:42,174:DEBUG:QUEUE - [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] 80.32464981079102 0.5 False 
2018-04-25 09:53:43,486:DEBUG:QUEUE - [0, 0, 0, 0, 1, 1, 1, 1, 1, 1] 77.09026336669922 0.6 False 
2018-04-25 09:53:44,798:DEBUG:QUEUE - [0, 0, 0, 1, 1, 1, 1, 1, 1, 1] 73.83155822753906 0.7 False 
2018-04-25 09:53:46,110:DEBUG:QUEUE - [0, 0, 1, 1, 1, 1, 1, 1, 1, 1] 76.49850845336914 0.8 True  
2018-04-25 09:53:51,961:DEBUG:Notified to Slack. STATUS_CODE - 200, MSG - ok                     

 ステータスが切り替わると下記のように slack に通知されます。

f:id:akanuma-hiroaki:20180426235610p:plain

課題

 現状それなりに稼働させていますが、下記のような課題があります。

【精度】

 空室状態の時に誤検知して使用中と判定することはほぼないのですが、使用中なのに空室と判定したり、空室と使用中の切り替えを繰り返してしまったりということが多く、もっと確実にステータスを判定できるセンシングに変更したいところです。

【ネットワーク】

 オフィスの AP に届いてはいるものの、やはりそんなに電波は強くないので、状況によってはネットワークに接続できずにエラーになってしまうので、ネットワーク接続の安定性は改善したいと思っています。

【死活監視】

 いつの間にかプロセスが落ちて通知が止まっていることがあるので、プロセス監視を入れて落ちたら自動的に起動するなどの対応が必要です。

まとめ

 まだまだ課題はあるものの、センサー設置前と比べると便利になっているということで、メンバーにはそれなりに好評のようです。今まで色々センサーを試してみたりはしていましたが、やっぱりちゃんと役に立つものを作れると面白いですね。課題点については暇を見て改善していこうと思います。

座り仕事のエンジニアの悩み

ハイドーモ!QAの山岸です。

最近腰を痛めてしまい、通院しています! なかなか治りが悪く歳を感じています。

今回のブログは技術ブログと言いつつも普段からオフィスで仕事をしている人が誰しもが悩む肩こり腰痛をテーマに書こうと思います!!

そもそも肩こり、腰痛の原因は??

f:id:unifa_tech:20180419133706p:plainf:id:unifa_tech:20180419133644p:plain
オフィスで働く人が接骨院や整体に行くと怒られた!みたいな話を聞きます。

  • 同じ動作の繰り返し
  • 姿勢
  • 特定の筋肉への負担
  • 冷えからくる筋肉の萎縮
  • 眼精疲労
  • 座ったとき足が開く
  • 座るとすぐに足を組む
  • 携帯やパソコンを使うとき、画面に近寄り背中が丸まる
  • 運動不足
  • 冷え性
  • ストレス

などなどwebで紹介されている記事から見ても座席に座って仕事をしている人はほとんどの項目が該当するとおもいます。

肩こり、腰痛への対策と対応

f:id:unifa_tech:20180419133334p:plainf:id:unifa_tech:20180419133401p:plain

肩こり
肩こりの原因は運動不足による血行不良、眼精疲労や冷え性、普段の姿勢が主となっています。

ならないための対策となってしまったときの対処法

  • 【対策】背筋を伸ばす。姿勢をよくする。
    これに注意しないとマッサージ等を行ってもすぐ戻ってしまいます。
    仕事中にモニタに前のめりにならない、胸を張る、背骨がS字になるように心がけることが必要です。

  • 【対策】体を冷やさない。
    寒い時期に寒さで身体が強ばる、夏場のクーラーなど体が冷えると血流が滞り肩回りの血流も阻害され肩こりを引き起こす原因になります。また、暑い時期に冷たすぎる飲み物や食べ物を食べることも血流が滞る原因になりますので注意が必要です。

  • 【対応】ストレッチ
    最近の話題だと肩甲骨はがしストレッチが効果的となっています。 style.nikkei.com
    その他だとこちらのブログ記事に図解付きでストレッチ方法が紹介されています。
    stretchpole-blog.com
  • 【対応】セルフマッサージ
    肩こりに効くツボを指圧するのが一般的でしょうか。
    ここでは効果的な2つを紹介しておきます。
     ・合谷(ごうこく)
      手の甲にある万能ツボ。首コリだけでなく肩コリや手のしびれなどにも効果
      手の甲側の親指と人指し指の付け根を内側に向かって押します。
      やや強めに両手それぞれ約30回程度)
    f:id:unifa_tech:20180419154359p:plain
     ・天柱(てんちゅう)
      首のコリと目の疲れに効果のあるツボ。パソコン疲労を解消に
      首筋のやや外側、うなじの窪み周辺
    f:id:unifa_tech:20180419154944p:plain
  • 【対応】湿布、温湿布、磁気治療器具
    湿布に関しては患部が炎症(熱をもっている)している場合には効果的です。
    温湿布は以前、病院で肌にダメージを与えるだけで意味がないと言われたことがあります
    磁気治療器具は現時点では、医学的にはこの低磁力による効果は確認されていないとのことです・・・
    (科学的には立証されていなくても、「よくなる!」という思い込みで症状が改善されるなら)

腰痛
こちらも肩こりと同様の対策になります。

  • 【対策】背筋を伸ばす。姿勢をよくする。
    これに注意しないとマッサージ等を行ってもすぐ戻ってしまいます。
    仕事中にモニタに前のめりにならない、胸を張る、背骨がS字になるように心がけることが必要です。

  • 【対策】体を冷やさない。
    寒い時期に寒さで身体が強ばる、夏場のクーラーなど体が冷えると血流が滞り肩回りの血流も阻害され肩こりを引き起こす原因になります。また、暑い時期に冷たすぎる飲み物や食べ物を食べることも血流が滞る原因になりますので注意が必要です。

  • 【対応】ストレッチ
    こちらは私が学生時代に教えてもらったのは大腰筋のストレッチ(縦の股割り)がいいと言われました。
    右膝を地面につけて片膝立ちの姿勢に。左膝に両手を添え、そのままゆっくりと体重を前にかけていきます。
    体重を前にかけていくときに腰を反り過ぎないように注意してください。

  • 【対応】セルフマッサージ
    腰のセルフマッサージは自分では難しいと思うので割愛します。

    以上になります。同じ姿勢で仕事している時間が長くなれば長くなるほど、体には負担がかかります。

    座りっぱなしにならず、30分に一回程度、座席を立つことを意識してください。

Chromeのフォントサイズ制限と印刷画面

こんにちは、Webエンジニアのちょうです。

最近A4サイズでも印刷できるように画面スタイルの調整をしてます。ところが、Chromeだけおかしいな挙動がありました。

Chrome

f:id:unifa_tech:20180402112528p:plain

Firefox

f:id:unifa_tech:20180402112533p:plain

9px, 8px, 7pxのところに注目してください。なぜかChromeだと10pxとほぼフォントサイズが一緒になってるように見えないでしょうか。実際はどうなんでしょう。開発者ツールで見ると

f:id:unifa_tech:20180402112904p:plain

あれ、本当に10pxになっています。ちなみに、このような現象はChromeだけあります。Firefox以外に、SafariやEdge、IEまで普通に指定通りのフォントサイズになってます。もしかして、Chromeのバグ?

ありえないと思いながら、Google先生にきいてみました。実はChromeにこういう設定があります。

続きを読む

異邦人としてのデザイナー -UIデザインと現場理解のためのエスノグラフィについて-

こんにちは。ユニファのデザイナー佐々木 勇貴と申します。開発者ブログでは初の投稿となります。よろしくお願いします。

今回自身の投稿もさることながらデザイン系の記事の投稿がユニファ開発者ブログ初となります。

なので、今回はデザイナーの役割を俯瞰しつつ保育活動の支援をミッションとする企業でのインハウスデザイナーの役割は何なのかを考えてみたいと思います。

普段、保育事業に関わられている方サービス開発をされているデザイナーの方などいろんな方に興味を持っていただけたら幸いです。

多様化するデザイナーの役割

近年、ITサービスにおけるデザイナーの役割については大変議論が活発になされていて、「グッドイメージをクリエイションできるのは必須だ」だの、「コーディングやプログラミングもできるべきだ」だの、さらには「ビジネスにも造詣があって経営者と同じ視座で事業について話し合えるべきだ」だのさまざまな意見が飛び交っています。

「デザイナーはなんでもできないといけないのか?」というツッコミと疲弊感が方々から飛んで来そうですが、これについてはできるならどんなことでもできた方が良いというのが個人の感想です。

デザイナーに限りませんが、スタートアップの企業においては職種を超えてスクラムを組んで事業に取り組むことが少なくありません。その際、異なる職種で話し合えるためのプロトコルを持つということがとても重要になります。

デザイナーに求められるエンジニアリングやビジネスに対する理解というのもこのような他者の職種を理解し協働するためのプロトコルの要求と捉えることができます。(「じゃあデザイナーのことは誰が理解してくれるの?」という魂の叫びが聞こえてきそうですがそれはまた別の機会にでも考えたいと思います)

UIデザイナーとしての役割

さて、デザイナーの役割が多様化する一方で、webサービスの開発に携わるデザイナーの役割としてまず間違いなく求められるものがあります。いわゆるUIデザインと呼ばれるものです。

UIの定義に関しては専門家であればあるほど各々に存在しているかと思いますが、ここではサービスのタッチポイントにおいてユーザーが求めるアクションを適切に行えるインターフェイスの設計と定義したいと思います。

ユニファでも例に洩れずUIの設計はデザイナーが先導していきます。

ですが、保育園業務を支援するユニファのサービスでは現場での専門業務に特化したUIが求めれられます。そのため、一般的なwebサービスのUIフォーマットを参照することは少なく、現場での課題をデザイナー自ら発見して独自のUIに落とし込むフローが必要となってきます。

UIデザインの手がかりとしてエスノグラフィ

そこで現場への理解を深めるための手法としてデザイナー自身によるエスノグラフィ調査を取り入れるようにしています。エスノグラフィとはユーザーリサーチの手法のひとつで、主にクローズドのコミュニティの中に観測者自身が参加し、その行動様式や価値観を記録するための手法として生まれました。(同様の手法としてシャードイングがありますが、個人に帰属するような行動様式ではなく園や保育士職というコミュニティに対する理解を深める必要があるためここではエスノグラフィを推奨しています。とはいえ、作業的には大きく違いはありませんが)

通常、2C向けのサービスなどではドッグフーディングなどの手法で開発者自身がユーザーとなることでユーザーの行動を体験しより良いUIを提案していくことができますが、ユニファのサービスは保育園での特定の業務を対象としたものが多く、またその業務での行動を想像では補えない場面を多く含んでいるため、現場に入らせてもらいながら特殊な行動様式を学ぶところからはじめる必要があるのです。

ビヘイビアとインサイトの発見

現場に入らせてもらう際には、自社のサービスのヒアリングやテストは行わず純粋に活動を共にするよう注意がけています。また、その業務が行われている裏で同時に行われている作業や実際の空間など現実的に与えられた条件をよく観察するようにも努めています。

保育を支援するユニファのサービスの多くは、閉鎖的なweb空間での行動で完結するものではなく園児の生活に基づいた非常に有機的な業務サイクルの中で使っていただく内容になっています。

サービスを使ってもらうその空間では常に生きている子どもたちと生活を共にし、その子どもたちの生活を一番に考えたいという保育士さんのインサイトを尊重することがUIを設計する際にもとても重要になってくるのです。

エスノグラフィから見えるUI設計の課題

一方でエスノグラフィで見るものはユーザーの行動様式だけではありません。その行動を規定するような慣習やドキュメントもその観察の対象になります。

どのドキュメントがどのように書かれているかなどの詳細な言及は避けますが、ドキュメントの傾向とUI設計の課題となるポイントを端的に書き出しておきます(選んだ言葉は用語はとして定義さているものではありません)

モーダル:保育園での業務はそのほとんどがモーダルです。園児の生活リズムに合わせて業務が設計されていて、各業務を行う時間・取得する値・記入するフォーマットがはっきりと決まっています。

フォームレス:モーダルと矛盾するようですが、記入業務における書類などは園ごとでの互換性が形式を持たないフォームレスのものが多く見られます。

コンベンショナル:保育園での業務は園内のクローズドの環境で円滑に運用できるよう明示的ではないローカルルールが使われていることがよくあります。先のフォームレスとも通じますが、その園でコンベンショナル(慣例的)に使われているものが重要な意味を持つことがあります。

ここであげた3つの傾向はサービスのUIを設計する際に繰り返し出てくる現場固有の課題です。単純にこれらを解消したUIを提供するのが良いという訳ではありませんが、今後も引き続き向き合わなければいけないと思っています。

異邦人としての役割

さて、今回はUIデザインを行う際の課題とその観察のプロセスを取り留めもなく書いてみました。

サービスをつくる際には自らがユーザーになれるユーザーのコミュニティと近しい距離にいれるかがとても重要だと考えています。

しかし、保育士のような非常に場面が限定されている職域においてのサービスでは開発者が恒常的にユーザーになることは難しくもあります。そこで、サービスをつくる者として自らを異邦人の立場において観察することが意味を持つのではないかと思っています。

今回エスノグラフィについても触れさせてもらいましたが、エスノグラフィの元々の起源は文化人類学に遡り、その手法の根幹には全く異なった文化コンテクストの観察と理解が目的とされています。ですが、ここでは決して同化することは目指されていません

異邦人として内側に入りながら外部として振る舞い続けることで、そのコミュニティの慣習と行動様式を発見し、ふたたびそれを作り変えることが可能になるのだと思っています。行動様式の再設計はとてもデザイナー的な課題であり、異邦人として振舞うことでデザイナーはその真価を発揮できるのではないか。保育活動の支援をミッションとする企業でのインハウスデザイナーを通じてそのように感じています。

今回の記事は以上になります。ご拝読ありがとうございました。

またお目にかかれることを楽しみにしております。それでは。

JIRA + re:dash + Slackで運用にかかった工数を週次で通知してみる

こんにちは、Webエンジニアの本間です。 最近、ランニングを始めまして、業務後に家の近くを走っています。 走り終わると頭の中のもやもやスッと抜けてて、とても爽快です。1人でできるスポーツですし、今後も続けていきたいなーと思っています。

さて話は変わりまして、弊社ではチケット管理にAtlassian社の JIRA を使っています。 チケットは、要望や機能追加、不具合修正などのコード修正を伴うものと、障害調査やエンジニア作業などコード修正を伴わないものがあり、後者を「運用作業」として区別して管理しています。

「運用作業」は新しい価値を生み出さない時間であるため、0かそれに近い値になっていることが望ましいです。 これを減らすためには色々な対策が必要になりますが、まずは「エンジニア自身がどれだけ運用作業に工数を使っているか、日々意識する」ことが大事なのではと考えました。

これを実現するため、毎週どれだけ運用作業に工数を使ったかSlackに通知する仕組みを作ったので、紹介しようと思います。(下のグラフが毎週月曜日の10時にSlackに通知されます)

f:id:ryu39:20180319100536p:plain

続きを読む