UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

Vue.jsコミッターのkazuponさんをお招きして社内勉強会をしました

こんにちは!エンジニア(仮)のめる(@c5meru)です。
最近、弊社のフロントエンドエンジニアごーさんが、社内勉強会に立て続けにスーパーゲストを呼んでくださっています(第1回第2回 )。
上記に続いて今回はなんと、なんと、Vue.jsコミッターのkazuponさんこと、川口和也さんをお招きしました!🎉✨

続きを読む

Webの技術でYoutube Viewer作った

はじめに

この記事は、UUUM Advent Calendar 2018 20日目です。

12月から新入社員の takeokunn です。普段は LMND の開発をやっております。

UUUMに入った初日(9/18)、 クリエイター(youtuber)のことを全く知らず他の人と会話が合わずに詰みました。 そこでこの会社でこの先生きのこるには効率よくキャッチアップする方法が必要だと思ってUUUM Creatorの動画viewerを作りました。

木下ゆうか さん、ごはん美味しそうに食べるから好き

Effective Youtube Viewer

f:id:bararararatty:20181217152621p:plain

Electronは配布してないので自前でbuildしてください

使ってる技術

  • electron
  • webpack/babel
  • react
  • redux/redux-saga
  • service worker
  • CSS Grid
  • csscomb/eslint
  • CircleCI

よくあるweb frontendの構成です。

redux-saga 楽しい

サービスの質を決めるのはエラーハンドリングだと思っています。 web frontendにおいて、非同期処理、特にAjax周りのハンドリングは非常に面倒ですが、redux-sagaを使えば体感すっきり書くことができます。

この辺がわかりやすいです。 redux-sagaで非同期処理と戦う f:id:bararararatty:20181217160209p:plain

以下はyoutube channelを取得する action/reducer/saga の例です。

抜粋: src/actions/youtube.action.js

export const fetchChannelVideo = {
    request: channel_id => action(YOUTUBE.FETCH_CHANNEL_VIDEO_REQUEST, { channel_id: channel_id }),
    success: data => action(YOUTUBE.FETCH_CHANNEL_VIDEO_SUCCESS, { data: data }),
    failure: () => action(YOUTUBE.FETCH_CHANNEL_VIDEO_FAILURE)
};

抜粋: src/reducers/youtube.reducer.js

const channel_video = (state, action) => {
    switch (action.type) {
    case YOUTUBE.FETCH_CHANNEL_VIDEO_REQUEST:
        return { ...state, is_fetching: true };
    case YOUTUBE.FETCH_CHANNEL_VIDEO_SUCCESS:
        return {
            ...state,
            is_fetching: false,
            search_videos: action.payload.data.items.map(item => ({
                title: item.snippet.title,
                description: item.snippet.description,
                thumbnail_url: item.snippet.thumbnails.medium.url,
                video_id: item.id.videoId,
                comments: [],
                comment_count: null,
                dislike_count: null,
                favorite_count: null,
                like_count: null,
                view_count: null,
            }))
        };
    case YOUTUBE.FETCH_CHANNEL_VIDEO_FAILURE:
        return { ...state, is_fetching: false };
    }
};

抜粋: src/sagas/youtube.saga.js

function* handleFetchChannelVideo() {
    for(;;) {
        const action = yield take(YOUTUBE.FETCH_CHANNEL_VIDEO_REQUEST);
        const response = yield call(ajax.searchChannelId, action.payload.channel_id);
        switch (response.status) {
        case 200:
            yield put(youtube.fetchChannelVideo.success(response.data));
            break;
        default:
            yield toastr.error('失敗', '通信失敗');
            yield put(youtube.fetchChannelVideo.failure());
        }
    }
}

今後の展望

弊社ではクリエイター分析ツールの開発などもやっているのでそれと連携して拡張できたら良いなぁと思います。

また、新着のsubscribe(webpush)やそのクリエイターの詳細情報など載せられるともっともっと良くなるだろうなぁと

今はクリエイターの管理がjsonで手書きで書いていて雑なのでなんとかしたいのと、あまりテストを書けてないので充実させたいなぁと src/options/youtuber.json

最後に

木下ゆうか さんの動画をデバッグに使い始めてから体感開発効率は上がるわ、体感javascript力も上がるわ、体感リロード時間も早くなるわで良いことづくめでした。本当にありがとうございました。 ← チャンネル登録しよう

UUUMでは (任意の文字列)エンジニアを募集しているそうです。 www.wantedly.com www.wantedly.com

CSS3のkeyframesで はじめしゃちょーを走らせてみました

こんにちは!エンジニア(仮)のめる(@c5meru)です。
こちらの記事は、UUUM Advent Calendar 2018 19日目の記事です!

5日目の前回は、CSSでHIKAKINをかきました
HIKAKINときたので、今回もUUUMのクリエイターである、はじめしゃちょーを題材にしたいと思います!

続きを読む

日頃あまり使っていないAWSのサービスを使う!〜AWS IoT編〜

はじめに

こちらは UUUM Advent Calendar 2018 18日目の記事です。

こんにちは、エンジニアのいぐちです。 WEBアプリケーションを開発していくうえで、AWSと触れ合うことが多い今日この頃ですが、ものすごい数のサービスを提供しているAWSの一部のサービスしか利用できておらず、少し寂しい・・・ そこで、日頃仕事で使ったことのないAWSのサービスを使ってみようということで AWS IoT を使ってみることにしました。

今回はRaspberry Pi2台とAWS IoTのセキュアなメッセージブローカーの機能を利用して簡単なおうちハック的なことをしたのでそちらをつらつらと書いていきます。

AWS IoT

AWS IoTというのはその名の通りちゃんとしたIoTでの開発をおこなっていくうえで必要になってくる様々な機能をまとめたサービス群になります。

詳しくはAWSのドキュメントをご覧ください。

AWS IoT とは - AWS IoT

今回利用したメッセージブローカー機能というのは、 MQTT等のプロトコルで各IoTデバイス(今回はRaspberry Pi)同士のメッセージのやり取りをpub/subモデルで行うものです。 MQTTなどがよく分からない方は以下のリンクをご覧ください。

MQTT の基本知識

やったこと

AWS IoTを使って、 目覚まし時計 を作りました。

え?目覚まし時計にAWS IoTって何言ってるの?ん? と思われるかもしれないですがちょっと説明させてください。

今回AWS IoTを使って作った目覚まし時計は、 スピーカーとスイッチが分離された目覚まし時計 です。

スピーカー側を寝室に置いてスイッチを遠く離れた別の部屋に置くことで、うるさいアラームを止めるのに歩いてスイッチを押しにいかなければならず嫌でも起床することになるという朝が弱い我が家の 最終兵器 です。

構成

  • Raspberry Pi A
    • スピーカーのみ接続
    • 特定の時間になるとアラームが鳴る
    • AWS IoTでTopicをsubscribeしており、別のデバイスからメッセージがpublishされたらアラームが止まる
  • Raspberry Pi B
    • タクトスイッチのみ接続
    • タクトスイッチを押すとメッセージをpublishする。
  • ソースコード
    • それぞれのRaspberry PiにはPython3系で書かれた簡単なコードが配置されています。

f:id:rinjin5th:20181217121317j:plain

AWS IoTの設定

まず以下のとおりモノを作成していきます。 (2台のデバイスを使用していますがとりあえず今回は1つのモノを使いまわします。)

f:id:rinjin5th:20181217010750p:plain

f:id:rinjin5th:20181217010841p:plain

今回は必須項目のモノの名前だけ適当に設定します。 f:id:rinjin5th:20181217010927p:plain

誰でも簡単にメッセージを送受信できては困るので、証明書による認証でセキュリティを担保します。 証明書もコンソール上からすぐに作成できます。

f:id:rinjin5th:20181217011138p:plain

作成できたら、モノの証明書、プライベートキー、ルートCAの証明書をダウンロードしておきます。 また証明書を有効化しとりあえず完了をクリックします。

f:id:rinjin5th:20181217011155p:plain

次にポリシーを作成し、先ほど作成した証明書にアタッチします。 今回はAWSIoT以外操作しないのでiot:*を指定することでAWSIoTの全操作が可能なように設定しておきます。

f:id:rinjin5th:20181217011214p:plain

f:id:rinjin5th:20181217011234p:plain

f:id:rinjin5th:20181217011250p:plain

これだけで設定は完了です。

ソースコード

一部抜粋してソースコードを掲載し説明します。 フルバージョンはこちらで公開しておりますので、気になる方はご確認ください。

https://github.com/rinjin5th/remote-alarm/

ライブラリとして以下を使用しています。

  • AWSIoTPythonSDK
  • PyAudio

AWSIoTMQTTClientの初期設定

スピーカー側、スイッチ側両方共にAWSIoTMQTTClientの設定を行う必要があります。 重要な部分は以下の通りです。

  • ClientIDの設定
  • エンドポイントの設定
  • AWSのルートCA証明書、モノの証明書、プライベートキーの設定
class MQTTClient:
    def __init__(self, client_id, host, root_ca, cert, key):
        # client_idはスピーカー側とスイッチ側で別の値にする必要がある
        self._client = AWSIoTMQTTClient(client_id)
        # AWSコンソール上で確認できるエンドポイント
        # ex)xxxxx..iot.ap-northeast-1.amazonaws.com
        self._client.configureEndpoint(host, 8883)
        # ルートCA証明書、モノの証明書、プライベートキーファイルのパスを設定
        self._client.configureCredentials(root_ca, key, cert)

parser = argparse.ArgumentParser()
parser.add_argument("-e", "--endpoint", action="store", required=True, dest="host", help="Your AWS IoT custom endpoint")
parser.add_argument("-r", "--rootCA", action="store", required=True, dest="rootCAPath", help="Root CA file path")
parser.add_argument("-c", "--cert", action="store", required=True, dest="certificatePath", help="Certificate file path")
parser.add_argument("-k", "--key", action="store", required=True, dest="privateKeyPath", help="Private key file path")
parser.add_argument("-m", "--mode", action="store", dest="mode", default="alarm" ,help="Operation modes: %s"%str(ALLOWED_MODES))

args = parser.parse_args()
host = args.host
rootCAPath = args.rootCAPath
certificatePath = args.certificatePath
privateKeyPath = args.privateKeyPath

clientId = "client_" + args.mode
mqtt_client = iotclient.MQTTClient(clientId, host, rootCAPath, certificatePath, privateKeyPath)

スピーカー側

大まかな流れは以下の通りです。

  1. トピックをsubscribeする。メッセージ受信時に実行されるcallback処理(アラーム停止)を設定しておく。
  2. アラームをループして再生しつづける。
class Alarm:
    playing = False
    
    def __init__(self):
        self._audio = pyaudio.PyAudio()

    def play(self, filename):
        self.playing = True
        while True:
            if not self.playing :
                break
            with wave.open(filename, 'rb') as wf:
                stream = self._audio.open(format=self._audio.get_format_from_width(wf.getsampwidth()),
                                 channels=wf.getnchannels(),
                                 rate=wf.getframerate(),
                                 output=True)
                 
                data = wf.readframes(1024)

                while data != b'':
                    stream.write(data)
                    data = wf.readframes(1024)

                stream.stop_stream()
                stream.close()

    def stop(self, client, userdata, message):
        self.playing = False

class MQTTClient:
    def subscribe(self, topic, callback):
        self._client.connect()
        self._client.subscribe(topic, 1, callback)

alarm_obj = alarm.Alarm()
# アラームの停止処理をメッセージ受信時のcallbackメソッドとして設定する
mqtt_client.subscribe("remote/alarm", alarm_obj.stop)
alarm_obj.play(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'alarm.wav'))

今回はあまり複雑な作りにはしたくなかったため、こちらのプログラムを起床時間にcronで実行しております。

スイッチ側

大まかな流れは以下の通りです。

  1. スイッチの状態を監視する。
  2. スイッチが押されたらメッセージをpublishする。
class MQTTClient:
    def publish(self, topic, message):
        self._client.connect()
        message_d = {}
        message_d['message'] = message
        self._client.publish(topic, json.dumps(message_d), 1)
        self._client.disconnect()

def watch():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(24, GPIO.IN) 
    
    try:
        while True:
            # タクトスイッチが押されたらループを抜けて後続の処理を実行
            if GPIO.input(24) == GPIO.HIGH:
                break 
            time.sleep(0.1)
    
    except KeyboardInterrupt:
        pass
    
    GPIO.cleanup() 

watch()
mqtt_client.publish("remote/alarm", "stop")

こちらもまた複雑な作りにはしたくなかったため、こちらのプログラムを起床時間にcronで実行しております。

まとめ

今回は目覚まし時計という軽いモノだったため、AWS IoTのほんの一部の機能しか利用しておりません。 今後はもっと色々なものを作ってAWS IoTを極めていきたいなと思います。

さいごに

UUUMではAWSのサービス(IoTは多分使わないけど・・)を使ったWEBアプリケーション開発ができる方を募集しております! とりあえずお気軽にお話だけでもどうぞ!

www.wantedly.com

www.wantedly.com

全く技術がわからない人にプログラミングを説明してみた

おはこんばんちは!! 尾藤 a.k.a. BTO です

この記事は、UUUM Advent Calendar 2018 12日目の記事です。 (だけど遅れて13日目に公開しました。ごめんなさいごめんなさい)

UUUMでは新入社員に会社の事業を理解してもらうために、各ユニット長が自分たちが何をやっているのか新入社員に説明する事業説明会というのがあります。 そこでシステムユニットの説明をするのですが、1時間という限られた時間の中で技術のわからない人たちに僕ら開発部隊がやっていることを理解してもらうのには無理があります。そうすると結局開発しているツールの説明になってしまうのですが、会社の状況がよくわかってない新入社員にいきなりツールの説明しても理解できませんし、自分の職種に関係のないツールの説明を聞いてもわかりません。で、結局何もわからずに終わってしまいます。

せっかく新入社員の人に時間をとってもらっている貴重な機会なので有意義なものにしたいです。どうせツールの説明は業務を進めれば自ずと理解が進むんだし、事業説明会でもやらなくても大丈夫です。システムユニットは周りから何の仕事をしているのかわからないとよく言われます。じゃあ、技術のわからない人たちに少しでも僕らシステムユニットがどういう仕事をしているのかを理解してもらう試みをしてみようと考えました。僕らがやっているのはプログラミングです。なので技術がわからない人たちにプログラミングはどういうものなのか、なんとなく理解できるように説明してみました。

プレゼン資料

こちらがプレゼン資料です。ドドーン!!! プログラミングの説明のところだけ抜粋してます。

いくつかのポイントを説明していきます。

ゴール設定

ゴールは

  • プログラムを分かった気になる
  • システムユニットの仕事を分かった気になる

の2つです。プログラムを書くのがなんで大変なのか、なんでそんなに時間がかかるのか、といったことがなんとなくわかってもらえるようになることを目指します。

プログラミングに一番必要な科目は?

英国数理社の5教科のうち、プログラミングに一番必要なのはどの教科か? 僕はこれは 国語 だと思います(異論は認める)。

この質問をするとプログラム書いたことない人からの一番多い回答は 数学 です。知らない人からすると、プログラマはさぞかし難しそうな計算式を扱っているように思われているんでしょうね。でも実際にプログラムを書く時に使うのはせいぜい四則演算ぐらいです。もちろんそういった分野もありますが、僕らが開発しているようなアプリケーションはライブラリを使うことがほとんどなので、自分たちで難しい数式を扱うことはほとんどありません。

次に多い回答は 英語 です。でもプログラムを書くのにレベルの高い英語は必要ないですよね。せいぜいいくつかの英単語を扱うぐらいです。英語の文書を読むというのもありますが、なくてもなんとかなります。

この質問で回答が 国語 だというと、かなり意外な顔をされます。これで外から見たプログラミングのイメージもだいぶ変わるのではないかなと思っています。

コンピュータを小人に例える

コンピュータがよくわからない鉄の塊なので、もっと身近な存在として小人に例えます(小人が身近じゃないというツッコミは置いといて)。 小人は次のような特徴を持ってます。

  • 真面目
  • 作業が正確・高速
  • 24時間365日休み無し
  • 賃金が安い
  • いきなり死ぬ
  • 言われたことしかできない
  • 言われた通りにしかできない

だいたいコンピュータの特徴とあってるのではないでしょうか。

こういう特徴を持った小人さんにちゃんと働いてもらうためにはしっかりとしたマニュアルが必要です。マニュアルを書くには時間もかかるし、正確に記述するには国語力が必要です。逆にしっかりとしたマニュアルを書くことができれば、小人さんにいっぱい働いてもらってその恩恵を受けることができます。プログラミングはマニュアルを書くのに似ています。だから一見簡単そうに見えることでも書くのに時間がかかるのです。

実際に小人用のマニュアルを書いてみます

例として小人に水を飲んでもらうというタスクを設定しました。人間なら一言で済むことが、小人さんにやってもらうと随分面倒なマニュアルを書く必要があります。彼らは融通がきかず言われたことしかできないので当然ですね。これでなんとなく面倒臭さがわかるのではないかなと思います。

アンケート結果

気になるアンケート結果はこちら

満足度

満足度
満足度

理解度

理解度
理解度

ということで満足度も理解度もかなり高い結果になりました。一安心です。

結論

2018年 YouTube 国内トップトレンドに選ばれた動画は全て UUUM クリエイターによる動画でした!!!!

www.buzzfeed.com

タグ付きテンプレートリテラル <JavaScript の「なんだこれ・・・」その1>

前置き

序文

  • JavaScript の「なんだこれ・・・」シリーズの第一弾は、「タグ付きテンプレートリテラル (Tagged Template Literal)」です。

仕様

  • ES6 で追加された仕様に、テンプレートリテラル (Template Literal) があります。他の言語ではよく見られる機能です。この機能を使えば、変数の値を文字列中に埋め込みたい時に文字列連結演算することなくスマートにコード化できます。

  • 色々な言語のテンプレートリテラルを見てみましょう。自分が業務で扱ったことのある言語の例を挙げてみました。

# Ruby

love = '最愛の'
"#{love}嫁さん (^-^)"    # '最愛の嫁さん (^-^)'
// PHP

$love = '最愛の';
"{$love}嫁さん (^-^)"    // '最愛の嫁さん (^-^)'
# Python

love = "最愛の"
f"{love}嫁さん (^-^)"    # "最愛の嫁さん (^-^)"
// Kotlin

val love = "最愛の"
"${love}嫁さん (^-^)"    // "最愛の嫁さん (^-^)"
// Swift

let love = "最愛の"
"\(love)嫁さん (^-^)"    // "最愛の嫁さん (^-^)"
// Java

// テンプレートリテラルは存在しない   // "それでも最愛の嫁さん (^-^)"
  • Java にはテンプレートリテラルはありませんが、嫁さんへの愛は変わりませんでした。

  • 多言語を扱っていると、別プロジェクトの作業に移った際にちょっとした書式の違いにいつも悩まされます。コンパイラの構文解釈的な都合なのかなと考えてますが、一度その意図をコンパイラの作者に訪ねてみたいです。

JavaScript のテンプレートリテラル

  • それでは、ES6 で追加された JavaScript 版をみてみましょう。
// JavaScript

const love = "最愛の";
"${love}嫁さん (^-^)"    // "最愛の嫁さん (^-^)"
  • 方向性は Kotlin と同じようですね。嫁さんへの愛も同じです。

タグ付きテンプレートリテラル

  • 何かで調べ物をしている時に、「タグ付きテンプレートリテラル (Tagged Template Literal)」と出会いました。初めてコードを見た時、「( ) が抜けてるんじゃないの?」と、しばらくフリーズしたのを覚えてます。
// タグ関数を定義
function scaleTag(hashes, ...values) {
  return values
    .map((value, index) => hashes[index] + emphasize(value))
    .concat(hashes.slice(values.length))
    .join("")
  ;

  function emphasize(word) {
    if (!word) {
      return "";
    }

    return `<strong>${word}</strong>`;
  }
}

const love = "最愛の";

/*
 * 以下が「タグ付きテンプレートリテラル」の書式です。
 */
scaleTag `${love}嫁さん (^-^)`;
    // "<strong>最愛の</strong>嫁さん (^-^)"
  • 上のコード中で「scaleTag」がタグと呼ばれる箇所です。この書式を初めて見た時、まるで「ずっと昔の恋人の経年後の今を SNS で偶然見かけたような気分」で見つめていました。

  • タグとテンプレートリテラルの間に半角スペースを入れていますが、なくても動作するようです。

解説

  • テンプレートリテラルにタグを付与すると、変数を展開する際にその値を加工するための hook 処理ができるという仕様。使い所は難しいですが、以下の用途はいかがでしょう。
// 整数をカンマ区切りで表示するタグ
function commalizeTag(hashes, ...values) {
  return values
    .map((value, index) => hashes[index] + commalize(value))
    .concat(hashes.slice(values.length))
    .join("")
  ;

  function commalize(number) {
    return number
      .toString()
      .replace(/(?!^)(?=(?:\d{3})+$)/g, ",")
    ;
  }
}

const price = 2500;

commalizeTag `価格:${price}円`;    // "価格:2,500円"
  • 「price を commalize() で変換してから表示させる」という方法だと、文字列中に commalize(price) と記載することになりますが、その辺りのノイズが外出しされるので、文字列がどういう結果になるかを想定しやすくなるメリットはありそうです。
// どちらが良いか?
commalizeTag `価格:${price}円`;
`価格:${commalize(price)}円`;
  • 変数展開がひとつだけなら大差ないですが、例えば Excel のように金額がずらりと並ぶような表を Web ページで表示させる場合はどうでしょう。commalize() が価格表示の個数分だけ書くのに比べれば、テンプレートの直前に一回だけ記載する方法はスマートに感じます。

  • 他にもっと良さそうなサンプルを閃いた時は、随時追加していきます。

まとめ

  • JavaScript のコードに違和感を覚えてそこで立ち止まるのは、バグを探す目が自動的に反応しているのだと考えてます。超初心者の頃は、構文を知らずによく立ち止まっては「ああ、こんな構文があるのか!」と、感動して覚えたものでした。しかしながら、JavaScript で立ち止まってそれが新しい構文だったという感覚は、久しく体験していませんでした。

  • 街でふと昔の恋人を見かけて。見たことのなかった笑顔で歩いている様子に「ああ、今は幸せなんだね」と感じたような、そんな「なんだこれ・・・」でした。

  • UUUM では、技術にこだわりのあるエンジニアを募集しています!! 詳しくは以下のリンクをご覧下さい。

www.wantedly.com

www.wantedly.com

Electron で付箋紙ウィジェットを作る

この記事は、UUUM Advent Calendar 2018 6日目です。


エンジニアをしているナカハシ(@k_nakahashi)です。

付箋紙アプリ、自分に合ったものを使いたい(ので作りたい)

私は作業用のPCでは、デスクトップ上に付箋紙アプリを浮かべていることが多いです。ウィンドウっぽいものを起動せずに、とりあえずテキストを打てる領域があるって気軽でいいんですよね。

Macで仕事するようになってからは、デフォルトでインストールされているスティッキーズという付箋アプリを使っていました。

続きを読む