feature image

2019年12月22日 | ブログ記事

部内製チャットサービス「traQ」UIのこれから 【AdC2019 53日目】

この記事は東京工業大学デジタル創作同好会traP アドベントカレンダー2019の53日目の記事で、traQのUI記事シリーズの後編です。

traQって何?という人は、前編にあたる『部内製チャットサービス「traQ」UIのこれまで』から読むといいかもしれません。


こんにちは、sigma (twitter:@unipota) と申します。

traPではSysAd班とグラフィック班に所属しています。

SysAd班はサークル内サービスの開発・運用を行っているチームで、自分はtraP独自のコミュニケーションサービス「traQ」のフロントエンド開発に参加しています。

UIやデザインを考えるのが大好きなので見えるところをガンガンよくしていくとテンションが上がる人間です。

traPのサークルロゴやSysAd班のチームロゴを作ったりもしてます。

Frame-2-1

この記事ではtraQ開発プロジェクトの今後について、実際に採用していく予定の具体的な技術を交えて語っていくつもりです。

なぜこれからか

現在traPで運用中のtraQは二世代目、v2です。(開発コードネームはtraQ-R)

去年の冬から今年の春にかけてフルスクラッチで書き直されたv2はVue.jsというフレームワークの力を手に入れて猛スピードでリリースに至りました。

しかしUI設計と並列して実装が進むことによる見通しの無いデザインや、属人的なコードの乱立が目立ち始め、開発の続行にしんどさが現れ始めたのです。

つまりデザインと技術の負債です。

(この辺りの詳しい経緯は『部内製チャットサービス「traQ」UIのこれまで』をぜひ。)

また同じ開発者がロングスパンでノウハウを維持できる企業プロダクトとは異なり、主要開発者が次々と卒業してしまうという学生サークル特有の問題も明らかになり始めました。(自分も来年には消える身です)

サークル内のコミュニケーションの中核として必要とされているサービスだからこそ、安定的に機能追加・運用が行われるべきです。

そういった危機感を元にtraQプロジェクトの再度のフルスクラッチリニューアルに踏み切りました。

開発コードネームはtraQ-Sです。

まだ動き始めたばかりですが、開発チームには2019年入学の一年生も参加していて、毎年のtraQスクラッチ開発はもはや技術的式年遷宮の様相を呈しています。

一から作るなんて無駄が多いと思うかもしれませんが、技術的モチベーション駆動の人間ばかりが集まっているtraPにおいては技術継承の点でもそれなりにいい方法なのではないでしょうか。

実現したい新機能

サークルメンバーから望まれつつも、現行バージョンのtraQ-Rでは実装を見送っていた新機能のアイディアがいくつもあります。

これら新機能をコード的にもデザイン上でも破綻なく実装することもプロジェクトリニューアルの大きな動機です。

一例ですが、現在出ている案は以下のようなものがあります。

実装予定の新機能

SlackやDiscordといったメジャーなチャットツールにあるようなリッチな機能から、サークル内の文化によって生じた需要に応えるような機能まで様々です。

おそらくtraQ-Sのリリース時に全ての機能を揃えることは難しいでしょうが、今後機能拡張を行われることを前提にしたコード設計をやっていくつもりです。

欲しいものをすぐに作れる体制を整えて維持することって、とっても難しいんですね。

体験の再設計

コミュニティの運営やそのあり方を左右する要素の一つにコミュニケーションツールがあることは、きっと多くの人に同意してもらえると思います。(特に技術系コミュニティの文脈では)

メンバーの人数、組織構造、リテラシーの程度などによってあるべきツールの形は様々です。

サービスを内製している自分達だからこそ、そのユーザー体験が組織のあり方に適しているのかを考え続けなければいけないと自分は考えています。

我らがtraPは立ち上がって5年目の大学サークルですが、その規模はかなりドラスティックな変化を辿っています。

初期には内部にいる人間が隅々まで見通せるような人数だったのが、今やサークル連合と言って差し支えないレベルに。

当然サークル内のコミュニケーションの様相も次第に変わってきます。

そこでtraQの使われ方の変化に合わせて、提供するべき体験を見直そうと開発メンバー(@spa)と話し合ったことのうち2つを紹介します。

巨大すぎるチャンネルツリー

サークル規模の変化に伴って各種プロジェクトやトピックごとに多くのチャンネルが建てられるわけですが、もはや一人が全チャンネルを把握することは不可能になってきます。(現在のチャンネル総数は1,318)

これまでのtraQでは常にチャンネルツリーの全てを見せていて、そこからチャンネルを選択して遷移するフローになっていました。

ツリーが巨大になるにつれ、大きな階層構造から目的のチャンネルを探す大変さが増すのは想像に難くないですよね。

その対策として現行のtraQ-Rではショートカットとして使えるチャンネルのお気に入り機能を導入していましたが、せっかくの階層構造をフラットに切り取ってしまうことで全体のどこに位置するチャンネルなのかが分からなくなっているのが残念でした。

そこで次期traQ-Sではこれまでに存在していなかったチャンネルへのJoinという概念を導入し、ツリーの中でJoinしているチャンネルだけを部分木として表示するビューを用意するつもりです。

子チャンネルだけにJoinしている場合は親を半透明で表示し、全体の情報量を減らしつつも階層を意識できるような見せ方を考えています。

そして未読メッセージの存在するチャンネルリストと合わせて、新しく「ホーム」タブを用意しました。

いろいろ考えた結果、一周回ってSlackと同じUIが生まれたのは面白いですね。

とはいえユーザーDMやお気に入りチャンネルは切り分けられているので、SlackよりもスケールするUIになっている自信はあります。

---

水平移動の導入

チャンネルで会話をしているとき、関連する他のチャンネルへ移動したいと思うことがよくあると思います。

あるプロジェクトの雑談チャンネルからサーバーサイドについて話すチャンネルへ、といった具合に。

せっかくtraQでは組織ごとにチャンネルがまとまっているのだから、兄弟チャンネルへもっと楽に遷移できるUIを提供したいということになりました。

一つのチャンネルにいながら、同じ部屋にある他のチャンネルが目に入るような体験が理想です。

----

技術構成

現在のtraQ-RではVue.jsとVuexを用いて、公式のスタイルガイドに従いながらJavaScriptで開発していました。

一部のStoreやAPI呼び出しにTypeScriptによる型定義が存在しているといった感じです。

またTemplateにはPug記法、CSSはSass記法を採用していました。

これらのインデントによるネストの表現は個人的に大好きだったのですが、そもそも難しいVue.jsのSFCにおけるlintやフォーマット支援の問題に拍車をかける要因になっていました。

以上を踏まえて基本方針は最大限TypeScriptの型の恩恵を享受し、lintやフォーマッタによるコードの治安維持を目指すというものです。

副次的にコードのリーダビリティやテスタビリティの向上も期待できます。

TypeScriptの全面導入

実現したいこと/は以下の通りです。

Composition API

Vue.jsはSFCやAPI設計に起因する学習コストの低さが魅力の一つのフレームワークです。

しかし大きなプロジェクトにおいてはロジックの使い回しが難しい、データとロジックが分離されていることによるコードの分散などが発生し、新規に開発に加わる人が辛くなる原因になっていました。

この問題を解決すべく提案されているのがComposition APIです。

実際上記の問題はtraQプロジェクトでも発生していて、アプローチを考えているところでした。

Vue.js 3.xで導入されると目される機能を先んじて採用することで技術的資産の形成を目論んでいます。

JSX

SFCがVueの特徴であることを認識しながらも、それを捨ててtemplateをJSXに移行することを考えています。

これには複数の要因があり、第一にtemplateでのType Errorをコンパイル時に検出する為です。

コンポーネントのPropsにしかるべき値が渡っていないときVueは一定範囲内でランタイム時に警告してくれますが、JSXならばコンパイルで引っかかってくれますし、エディター上でも間違いに気付くことができます。

他にもrender関数を用いることでコンポーネントをcomponents: {}に登録することなく呼び出せたり、setup関数からtemplateに渡す必要がなくなったりなどコードを減らすメリットも存在します。

ここまでやるならReactでいいのではとも思えるかもしれませんが、サークル内にはVueの経験者が圧倒的に多いこともあり、Vueに乗っかりつつも開発体験を最大化する試みです。

Vuexの型付け

Vuexで型推論を効かせる方法については多くの人が悩んでいると思います。

以前別のプロジェクトでは外から型付けを行う手法であるこちら( https://github.com/takefumi-yoshii/ts-nuxtjs-express )の方法を試したのですが、interfaceの定義を逐一書く必要があり面倒でした。

Storeの実装をソースとして推論して欲しいと考えていたところ、Vue.js Newsで紹介されていたdirect-vuexがよさそうだったので採用しました。

vuex-smart-moduleのように実装がクラス記法になったりしないので移行コストも低めに見積もれそうです。

ヘルパー関数を用いて実装を行うと、それを元にフィールドや引数の型を持ったラッパーを作ってくれます。

import Vue from "vue"
import Vuex from "vuex"
import { createDirectStore } from "direct-vuex"

Vue.use(Vuex)
const { store, rootActionContext, moduleActionContext } =
    createDirectStore({
        // ここに実装    
    })
export default store
store.dispatch.myAction(myPayload)

前述のComposition APIとも相性がよいので期待しています。

Swaggerによる型定義生成

traQのAPIはSwagger Specificationにしたがってドキュメント化されています。

そのAPI仕様を元に型定義を提供するパッケージがnode-traqとして切り出されており、traQ APIを利用するBotなどの各種アプリケーションから利用できるようになっています。

こちらは既にtraQ-Rでも導入されていましたが、呼び出し側がTypeScriptの世界ではなかったため恩恵が薄くなってしまっていました。

Styled Components

VueのSFCをやめたときに問題となるのが、Styleをどこに書くのかということになってきます。

traQ-Rで感じた課題としてJSと連携したStyleの書きづらさというのがあり、Styleがcomputedの中に埋もれるなどの辛さがありました。

また今はCSS Variablesでダークテーマを実装していますが、より自由度の高いカスタムテーマ機能を実現する上ではCSS in JSへの本格的な移行の必要性を感じていました。

CSS in JSとして採用したのはvue-styled-componentsです。

持続するデザイン

前編でもあったように、traQ-RのUI設計は機能の増加に伴うスケールアップに失敗しました。

これは設計段階での想定不足もありますし、チーム内でUIへの責任を持てるメンバーの不足によるものでもありました。

機能が追加されるときどこにUIを配置すべきなのか、どこまでの変更が許容されるのか、といった判断を出来る人間が少なく、結果的にデザイン変更を伴うPRがずっとpendingすることになっていました。

開発者が従うべきルールを明文化することで、もっと開発スピードを上げられるはずです。

そのために現在デザインガイドラインの定義に取り組んでいます。

コンポーネントをルールベースで定義し、迷うことなく拡張が行えるようなガイドラインを目指します。

まとめ

まだ技術的にも開発方針としても手探りなため具体的な実装に触れることができませんでしたが、今後のtraQの発展に期待してください。



宣伝

@spa@to-hutohu@60@oribeと一緒に開発したWebサービスを最近リリースしました。

こちらもUI/UXもりもりに作っているのでよかったら見てください

🎉積読管理アプリ、ツンドクをリリースしました!!

買った本読まずに積んでいませんか?
ツンドクはそんな「未読負債」を可視化するアプリです!
登録なし&バーコードスキャンですぐに利用できますhttps://t.co/HUmDYc8rcM#積読 #ツンドク pic.twitter.com/YVSrUAanji

— うにぽた (@unipota) November 29, 2019
sigma icon
この記事を書いた人
sigma

デザインとWeb 外ではうにぽた

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2021年5月16日
CPCTFを支えたインフラ
mazrean icon mazrean
2021年4月2日
traQの検索機能が謎のエラーを吐いた話
toki icon toki
2019年12月21日
モデリングを始めてみたい君へ、MagicaVoxelのススメ
isak icon isak
2019年12月13日
ゲーム紹介「League of Legends」【AdC2019 44日目】
Yataka_ML icon Yataka_ML
2021年3月24日
traQのメンション・チャンネルリンク機能について【新歓ブログリレー16日目】
reyu icon reyu
2020年5月1日
爆☆誕 traQ-S【新歓ブログリレー2020 54日目】
spa icon spa
記事一覧 タグ一覧 Google アナリティクスについて