株式会社モバイルファクトリーのブログ - TECH PLAY

TECH PLAY

株式会社モバイルファクトリー

株式会社モバイルファクトリー の技術ブログ

228

概要 こんにちは! モバイルファクトリー Advent Calendar 2018 10日目担当の shioiyan です。 9日目の記事は @isaoeka さんの 草ウィジェットを作った🤔 でした。 本記事では @mattak さんが開発された、UnityでReduxのような状態管理が行えるようになる Unidux を使って簡単なゲームサイクルを実装してみます。 この記事を読んでわかること Uniduxを使った画面遷移が実装方法がわかる PageとSceneの紐付け方 PageとSceneの状態管理のやり方 PageとSceneの状態の監視方法 Pageの変更のやり方 Pageへのデータの持たせ方 ※会社で開発しているアプリ/プロジェクトとは関係がありません。 動機 ゲームジャムなどで簡単なゲームを作っていると、いつもタイトル画面->ゲーム画面->リザルト画面->タイトル画面...という簡単な画面遷移を実装するのにそれなりの時間がかかっていることに気がつきます。 タイトル画面やリザルト画面はゲーム制作の本質的な部分ではなく、特に限られた時間で行われるゲームジャムでは、できれば時間をかけずに作りたいところです。 また、ゲームの規模が大きくなるに従い、少ない画面数ならなんとか管理できていたものがだんだん管理しきれなくなっていきます。 画面遷移の仕組みはどんなゲームを作るにしても必要です。 あらかじめ実装方法を確立しておき、ゲーム開発で本質的な部分に注力して開発できるようにしておきたいところです。 解決策 UniduxのSceneTransitionを使えば、拡張性の高い画面遷移が実装できます! やや作業量は多いかもしれませんが、1度実装しておけばあらゆるアプリケーションで使えるはずです。 今回作るもの タイトル画面->ゲーム画面->リザルト画面->タイトル画面...と遷移する ボタンを押すと画面遷移が行われる タイトル画面で選択した難易度がゲーム画面で表示される ゲーム画面から遷移する時にスコアが渡されてリザルト画面でスコアが表示される github.com   開発環境 Unity v2018.2.16f1 Unidux v0.3.4 UniRx v6.2.2   実装 ※ Uniduxの使用例にあるSceneTransitionの実装を参考にしています。 ※ Unidux自体やUniRxの使い方についてはここでは触れません。 PageとSceneの紐付け まずは使用する Sceneを作成 します。 今回は、どのPageにも常に存在するBaseというSceneと、Pageによって切り替わるTitle、Game、Resultの3つのSceneを作成します。 Uniduxでは1つの画面のことをPageと表現します。 Pageは1..n個のSceneの集まりです。 作成したSceneは enumで同じ名前で定義 しておきます。   今回はこれらのSceneを使って3つのPage(タイトル画面、ゲーム画面、リザルト画面)を作るので、こちらも enumで定義 しておきます。 次に SceneConfig.cs というスクリプトを作り、各PageにどのSceneが必要かマッピングしていきます。 SceneCategoryというパラメータがあり、Permanentに設定されたSceneは常に表示されるようになります。 今回は各PageにBaseと対応するそれぞれのSceneが表示されればいいので、CategoryMapでBaseのSceneCategoryをPermanentに設定し、PageMapで各PageとSceneをマッピングします。 もしHeaderやFooterといったSceneが必要ならそれぞれPageに紐付けると良いでしょう。   SceneとPageの状態を管理 ゲームの状態を管理するクラスに SceneStateとPageState を持たせます。   SceneWatcherとPageWatcherの作成 SceneStateとPageStateの変更を監視して実際にUnity上のSceneを変化させる SceneWatcher と PageWatcher を作成します。 ここで使われている SceneUtil でUnityお馴染みの SceneManager.LoadSceneAsync() が実行されています。   Pageを変更する これでSceneStateやPageStateを変更するActionが発行されるとそのActionに応じてSceneやPageが変更されるようになりました。 次にButtonが押されたらPageが変更されるようにしてみます。 例えば、 リザルト画面からタイトル画面に戻るボタンのスクリプト は以下のように実装します。   using GameCycleSample.Config; using Unidux.SceneTransition; using UnityEngine; using UniRx; using UnityEngine.UI; namespace GameCycleSample.UI { [RequireComponent( typeof (Button) )] public class ReturnToTitleButtonDispatcher : MonoBehaviour { void Start() { this .GetComponent<Button>().OnClickAsObservable() .Select(_ => PageDuck<Page, Scene>.ActionCreator.Push(Page.TitlePage)) .Subscribe(action => Unidux.Dispatch(action)) .AddTo( this ); } } } PageDuck<Page, Scene>.ActionCreator.Push(Page.TitlePage) というActionをDispatchすることでタイトル画面に必要なSceneを表示させています。 また、 PageDuck<Page, Scene>.ActionCreator.Pop() というActionも用意されており、前のPageへ戻ることも行えます。   Pageにデータを持たせる UniduxではPageをPushする時にPageにデータを持たせることができます。  PageDuck<Page, Scene>.ActionCreator.Push() の第二引数にIPageDataを継承したクラスを渡すことができます。 今回はタイトル画面で難易度を選択できるようにし、ゲーム画面で選択した難易度が表示されるようにしました。 まずは IPageDataを継承したクラス を実装します。 using System; using GameCycleSample.Type; using Unidux.SceneTransition; namespace GameCycleSample.Struct { [Serializable] public class GamePageData : IPageData { public DifficultyType DifficultyType; // ゲームの難易度 public GamePageData() { } public GamePageData(DifficultyType difficultyType) { this .DifficultyType = difficultyType; } } } タイトル画面で難易度を選択するボタンのスクリプト は以下のようになります。 using GameCycleSample.Config; using GameCycleSample.Struct; using Unidux.SceneTransition; using UnityEngine; using UniRx; using UnityEngine.UI; namespace GameCycleSample.UI { [RequireComponent( typeof (Button) )] public class TitleButtonDispatcher : MonoBehaviour { public GamePageData GamePageData; void Start() { this .GetComponent<Button>().OnClickAsObservable() .Select(_ => PageDuck<Page, Scene>.ActionCreator.Push(Page.GamePage, this .GamePageData)) .Subscribe(action => Unidux.Dispatch(action)) .AddTo( this ); } } }   Inspector上で各ボタンに応じた GamePageData (の DifficultyType )を設定します。 あとは PageDuck<Page, Scene>.ActionCreator.Push(Page.GamePage, this.GamePageData) と渡してあげると PageState.Data に GamePageData が格納されます。    次にPageDataを参照してTextとして表示してみます。 表示したいTextGameObject(今回はTextMeshProUGUIを使っています)に 以下のスクリプト をattachします。 using GameCycleSample.Business; using GameCycleSample.Struct; using TMPro; using UnityEngine; using UniRx; namespace GameCycleSample.UI { [RequireComponent( typeof (TextMeshProUGUI) )] public class DifficultyTypeTextRenderer : MonoBehaviour { public TextMeshProUGUI DifficultyTypeText; void Start() { Unidux.Subject .Where(state => state.Page.IsReady && state.Page.IsStateChanged) .Where(state => state.Page.Data is GamePageData ) // Page.Dataの型チェック .StartWith(Unidux.State) .Subscribe(state => this .Render(state)) .AddTo( this ); } private void Render(State state) { GamePageData pageData = state.Page.GetData<GamePageData>(); this .DifficultyTypeText.text = pageData.DifficultyType.ToString(); } } } state.Page.GetData<GamePageData>() で指定した型のPageDataを取得できます。 GamePageData型のPageDataが存在することを保証するために .Where(state => state.Page.Data is GamePageData) で現在の Page.Data が GamePageData である場合だけ参照するようにしています。 また、 .Where(state => state.Page.IsReady && state.Page.IsStateChanged) とすることで、ゲーム中に難易度が変更されても検知して再描画するようにしています。 同様にして、 ゲーム画面からリザルト画面に遷移する時にスコアを渡して 、 リザルト画面でスコアを表示 するようにしています。   まとめ Uniduxを用いて簡単なゲームサイクルを実装できました。 画面遷移のロジックは実装者によってバラバラな実装になりがちですが、Uniduxを使うことで統一感のある実装になるため、複数人開発する場合にも特におすすめです。 UnityでReduxライクに状態管理が行えるUniduxはとても素晴らしいので、ぜひ皆さんも使っていきましょう!   モバイルファクトリーではゲームジャム部という部活があり、文字通りゲームジャムを開催して自由にゲームを作ったりしています。   モバイルファクトリー Advent Calendar 2018 11日目は id:toricor さんの記事です。 今年もテストの話のようです。楽しみですね!!
これは モバイルファクトリー Advent Calendar 2018 6日目の記事です。 前日の記事は @koropicot さんの ブロックチェーンの学び方 でした。 こんにちは、新卒ソフトウェアエンジニアの id:mp0liiu です。 吉祥寺.pm#16で「Perlにおけるクラスの実装パターン」というタイトルでLTをしたのですが、 この記事では紹介したクラスの実装パターンのうち、個人的に気に入っている InsideOutオブジェクト(資料でいう18~21P)について詳しく掘り下げてみてみます。 吉祥寺.pm#16で発表した資料はこちらです。 InsideOutテクニックとは?  インスタンスのアドレスを数値として評価し、それをキーとしてパッケージローカルなハッシュ変数などにインスタンス変数を格納することで、完全なカプセル化を実現するクラスの実装パターンです。 Perl Best Practiceで推奨されている方法ですが、あまり普及しませんでした。 メリット インスタンス変数を完全にクラスの外部から隠蔽し、カプセル化を実現する 拡張性がある カプセル化を実現しているクラスの実装パターンのなかでは速度が最も速い デメリット インスタンス変数の呼び出しに比較的時間がかかる 毎回blessしているオブジェクトのアドレスを数値に変換する手間がかかるため(高速化のテクニックもあります) この実装パターンを知らない人にとってはコードが何をやっているのかかなり理解しにくい メモリを開放する処理を自前で実装しなければならない インスタンスが必要なくなってもGCがメモリを開放するのはインスタンスの領域だけで、 各インスタンス変数のデータはパッケージローカルな変数に残り続ける デバッグ、シリアライズがしづらい Hash::Util::FieldHash  クラスビルダーというよりかは、InsideOutテクニックでクラスを作るのをサポートするようなユーティリティを提供するモジュールです。 特徴としては、 インスタンス変数に相当する値へのアクセス、メモリ解放を自動でやってくれる コアモジュール(perlv5.9.4から) コンストラクタやアクセサは手書き このモジュールで提供される機能を用いてクラスを作る場合は、以下のようになります。 package Point { use Hash::Util::FieldHash qw( fieldhash ) ; fieldhash my %x_fields ; fieldhash my %y_fields ; sub new { my ( $class , $x , $y ) = @_ ; my $self = bless \( my $anon ), $class ; $x_fields{$self} = $x ; $y_fields{$self} = $y ; $self ; } sub x { my $self = shift ; $x_fields{$self} ; } sub y { my $self = shift ; $y_fields{$self} ; } } my $p = Point->new( 1 , 2 ); fieldhash 関数で登録したハッシュにインスタンス変数に相当する値を格納しておくと、インスタンスのメモリが開放されるとタイミングで、そのインスタンスのインスタンス変数も自動的に開放されるようになります。 クラスを作る手間はハッシュベースクラスを1からつくるのと同程度になりそうです。 コアモジュールしか使えない環境でInsideOutクラスを作りたいような場合、選択肢に入りそうです。 CPANTSで直接調べられなかったので、CPAN上にあるモジュールでHash::Util::FieldHashに依存しているモジュールの数は正確にはわかりませんでしたが、 perl5.10以前のperlにも対応させたHash::Util::FieldHash::Compatというモジュールに依存しているモジュールの数は、 19個 でした。 Object::InsideOut  Object::InsideOutは非常に多機能なInsideOutクラスのクラスビルダーです。 特徴としては、 メモリ解放を自動でやってくれる コンストラクタ、アクセサの自動生成機能を提供 コンストラクタでの引数チェックの機能を提供 インスタンス変数の型制約をサポート Storableでのシリアライズをサポート インスタンス変数をハッシュでなく配列に格納させることができるので、他のクラスビルダーと比べてインスタンス変数へのアクセスが高速にできる エラー出力が丁寧 attributeを多用する Object::InsideOutでクラスを作る場合は、以下のようになります。 package Point { use Object::InsideOut; my @y_fields : Field # InsideOutオブジェクトのインスタンス変数格納に使用し、この配列に登録されたインスタンス変数の開放処理は自動でされるようになる : Type( 'Numeric' ) # 数値しか受け付けない : Accessor( 'y' ); # 'y' という名前の読み書き可能なアクセサを生成 my @x_fields : Field : Type( 'Numeric' ) : Accessor( 'x' ); # コンストラクタでどのような引数を受け付けるかの設定 my %init_args : InitArgs = ( x => +{ Mandatory => 1 , # 必須の引数 Type => 'Numeric' , # 数値しか受け付けない }, y => +{ Mandatory => 1 , Type => 'Numeric' , }, ); # オブジェクトの初期化 sub init : Init { my ( $self , $args ) = @_ ; $self->set ( \ @x_fields , $args->{ x } ); $self->set ( \ @y_fields , $args->{ y } ); } } my $p = Point->new( x => 10 , y => 20 , ); コードをMooseに匹敵するほど多機能なことがなんとなくわかるかと思います。 しかしattributeを多用しているため、Perlに詳しくない人にはとっつきにくそうです。 また、PSGIアプリやmod_perlでの利用に不安がありそうです。(ドキュメントを見た限りではmod_perl上での実行はサポートしているとのことでした。) CPAN上にあるモジュールでどれほど利用されているか調べたかったのですが、 不具合で調べられないようでした 。 Class::InsideOut Class::InsideOutの特徴は、 メモリ解放を自動でやってくれる コンストラクタ、アクセサの自動生成機能を提供 継承ツリーを汚さない Storableでのシリアライズをサポート attributeを使うクラスビルダー(Object::InsideOutなど)とは違って、PSGIやmod_perlアプリでもきちんと動作する Class::InsideOutでクラスを作る場合は、以下のようになります。 package Point { use Class::InsideOut qw( new public readonly private ) ; # read / write 可能なアクセサの生成し, このハッシュに登録されたインスタンスのインスタンス変数の開放処理は自動でされる public x => my %x_fields ; # read only なアクセサの生成し, このハッシュに登録されたインスタンスのインスタンス変数の開放処理は自動でされる readonly y => my %y_fields ; # アクセサは生成せずに、インスタンスのインスタンス変数を保持するだけのハッシュを作ることもできる # private memo => my %memo_fields; } my $p = Point->new( x => 10 , y => 20 , ) Mooseなどのように、普通の関数でアクセサの生成を行ったりしているので、コードはだいぶ読みやすいなと思いました。 CPAN上にあるモジュールでClass::InsideOutに依存しているモジュールの数は 23個 のようです。 (Moose|Moo)X::InsideOut  Moose, あるいはMooのバックエンドでInsideOutクラスを使うようにするモジュールもあります。 使い方は簡単で、(Moose|Moo)をuseしたあとに(Moose|Moo)X::InsideOutをuseするだけです。 次のコードはMooでの例です。 package Point { use Moo; use MooX::InsideOut; has x => ( is => 'ro' , required => 1 , ); has y => ( is => 'ro' , required => 1 , ); __PACKAGE__ ->meta->make_immutable ; } my $p = Point->new( x => 10 , y => 20 , ) 簡単にInsideOutクラスによるカプセル化が有効になり、かつMoose系のモジュールの機能が利用できてとても良さそうです。 しかし、インスタンス変数に相当する値が our で宣言されたハッシュに入っているため、外部からインスタンス変数を操作することができてしまいます。 Mooだと、具体的には以下のようにしてカプセル化を破ることができます。 my $p = Point->new( x => 1 , y => 4 ); say $p->x ; # -> 1 $ MooX::InsideOut::Role::GenerateAccessor:: FIELDS{$p}->{ x } = 100 ; say $p->x ; # -> 100 なぜ our にしてあるのかはわからないですが、個人的にはせっかくのカプセル化の利点がなくなってしまっているので使う理由はあまりないのでは、という気がしています。 とはいえハッシュベースクラスのインスタンスほどカジュアルにカプセル化に違反することはできませんし、そもそものちゃんとしたInsideOutクラスでも強引にカプセル化を破ることはできなくもないので、これを利用するかどうかは状況によって判断が変わってきそうです。 なお、CPAN上にあるモジュールでMoox::InsideOutに依存しているモジュールの数は 3個 で、MooseX::InsideOutに依存しているモジュールの数は不明です。 その他 Hash::FieldHash id:gfx 氏によって高速化&シンプルにされた Hash::Util::FieldHash のようなモジュールです Class::Std Damian Conway氏作のPerl Best Practiceで利用を推奨していたクラスビルダーです attributeを利用してアクセサやインスタンス変数格納用のハッシュを作ります 昔流行していたためか、けっこうClass::Stdに依存しているモジュールは多くて、 55個 ありました Dios これもDamian Conway氏作のInsideOutクラスのクラスビルダーです これを利用して書かれたクラスの外見はまるでPerl6のクラスのようになります 実験的なモジュールのようで、残念なことに最近のバージョンのPerlでは動かないようです。。 おわりに  InsideOutクラスのクラスビルダーはたくさん種類があるのですが、やはり広く利用はされていないんだなあ、と感じました。 個人的には、どうしてもInsideOutクラスを作りたい場合、読みやすくてかつ機能がそろっているClass::InsideOutを使うのが良さそうと思いました。 コアモジュールにInsideOutクラスの作成を支援するモジュールがあったのは意外でした。 7日目の担当は yunagi さんです。お楽しみに。
こんにちは、 2018年モバイルファクトリーアドベントカレンダー 12/7担当の id:yunagi_n です。 はじめに 個人的な趣味で、 Firebase と Nuxt.js でブログを作っています。 そのことについて、いろいろ話します。 なお、 会社で開発しているアプリ・プロジェクトとは一切関係ありません 。 前提 以下の環境で開発、動作確認を行っています。 Firebase (Blaze プラン) Node.js 8.12.0 Windows Subsystem for Linux (WSL) Ubuntu 16.04 Nuxt.js 2.3.4 TypeScript 3.2.1 Firebase と Nuxt.js のプロジェクトは作成済み 本題のその前に なぜ nuxt generate で生成した静的ファイルを使わないのか、についてです。 あくまで個人的な思いなのですが、 記事を Git 管理したくない 記事を publish するために、いちいち (たとえ CI であろうとも ) ビルド & デプロイを行いたくない という理由がありました。 とくにビルド時間というのはそこそこかかるので、やらなくても良いのならば、やらないに越したことはないです。 作るブログ ブログとして最低限の機能のみの実装です。 Firestore の制約上、記事の検索は出来ないので要件に含めていません。 記事を投稿できる URL は ID ではなく、 yyyy/MM/slug 形式で自由に設定できる 例: 2018/12/my-favorite-music 記事にはカテゴリを複数個付けられる カテゴリで絞り込みが出来る 投稿月で絞り込みが出来る 投稿数が分かる カテゴリ名 (投稿記事数) 、 yyyy/MM (投稿記事数) の形式で表示する 実装 Firestore の設計 Cloud Firestore は NoSQL データベースのため、 RDB のような SELECT COUNT を用いたカウントは行えません。 また、読み取ったドキュメント数によって課金が行われるだけではなく、読み取る数が多くなるとレスポンスも悪化するので、 一度の操作で読み取るドキュメント数は、できる限り抑えるべきです。 そのため、投稿数などは次のようなドキュメントに記録しました。 // カテゴリー export interface Category { name: string ; count: number ; } ドキュメントへの記事数の記録は、後述する Cloud Functions の Cloud Firestore トリガー を使って行います。 ブログ記事は単純な、以下のドキュメントにしました。 export interface Entry { slug: string ; title: string ; body: string ; created_at: Date ; // 実際は秒数が降ってきます categories: string [] ; } Cloud Functions Cloud Functions では、記事の投稿・更新・削除をトリガーに集計を行う処理と、ページの描画処理を登録します。 例えば記事を投稿したときの処理は import * as firebase from "firebase-admin" ; import * as functions from "firebase-functions" ; module . exports = functions.runWith ( { memory: "256MB" , timeoutSeconds: 30 } ) .firestore. document ( "entries/{entryId}" ) .onCreate (async ( snapshot ) => { const entry = snapshot.data () as Entry ; for ( let name of entry.categories ) { const category = await firebase.firestore () .collection ( "categories" ) .where ( "name" , "==" , name ) .limit ( 1 ) . get() .docs.shift (); if ( category ) { // すでにあればカウントアップ await category.ref.update ( { count: ( category.data () as Category ) .count + 1 } ); } else { // 無ければ作る await admin.firestore () .collection ( "categories" ) .doc () . set( { name , count: 1 } ); } } } ); となります。 更新・削除も同様の処理を記述していけば OK です。 Nuxt.js と Cloud Functions での SSR は以下の通り。 buildDir プロパティは、うっかりソースコードからの相対パスで書いてしまうと、何も返ってこなくなります。 import * as express from "express" ; import * as functions from 'firebase-functions' ; import { Nuxt } from "nuxt" ; const app = express (); const nuxt = new Nuxt ( { dev: false , buildDir: "./lib/.nuxt" , // package.json がある場所からのパス build: { publicPath: "/assets/" } } ); async function handleRequest ( req , res ) { return await nuxt.render ( req , res ); } app.use ( handleRequest ); module . exports = functions.runWith ( { memory: "256MB" , timeoutSeconds: 20 } ) .https.onRequest ( app ); Firebase Hosting firebase.json を編集して、 Firebase Hosting のリライトルールを変更します。 基本的には全てのリクエストを Cloud Functions の関数を呼び出すように設定します。 { " hosting ": { " public ": " dist/client ", " ignore ": [ " firebase.json ", " **/.* ", " **/node_modules/** " ] , " rewrites ": [ { " source ": " ** ", " function ": " render " } ] } } Nuxt.js npx create-nuxt-app で作ったものをそのまま使います。 プリセットにある Tailwind CSS を使うと、CSS が苦手でも悩まされることなく UI を作れるのでオススメです。 Nuxt.js の Firebase の初期化は、 plugins/firebase.ts で行います。 これは Firebase の初期設定ページに表示されているものをそのままコピペしてきます。 import * as firebase from "firebase" ; if ( ! firebase.apps.length ) { const config = { apiKey: "xxxxxxxxxx" , authDomain: "xxxxxxxxxx.firebaseapp.com" , databaseURL: "https://xxxxxxxxxx.firebaseio.com" , projectId: "xxxxxxxxxx" , storageBucket: "xxxxxxxxxx.appspot.com" , messagingSenderId: "1234567890" } ; firebase.initializeApp ( config ); } export { firebase } ; そして、 nuxt.config.js の plugins プロパティに plugins/firebase.ts へのパスを追加しておきます。 plugins: [ "~/plugins/firebase.ts" ] Firestore からデータを持ってきて、 SSR もしくはページ遷移時に取得するには、 asyncData メソッドを使用します。 ファイル名・ディレクトリ名を /_year/_month/_slug.vue のようにすることで、 引数として context が渡されるので、 その中の params プロパティ経由で、 year , month , slug といったパラメータを受け取ることが出来ます。 // SFC の script 部分のみ import { Component , Vue } from "nuxt-property-decorator" ; import { firebase } from "~/plugins/firebase" ; @Component export default class extends Vue { public async asyncData ( { params } ) { // const { year, month, slug } = params; でパラメータ取得できます。 const entry = await firebase.firestore () ... ; // 記事取得 return { entry } ; } } asyncData メソッドの返り値は data メソッドの返り値とマージされるので、あとは通常の Vue SFC のように テンプレートや他のメソッドなどを書くだけで OK です。 ブログサイドメニューにあるような、カテゴリ一覧や月別アーカイブは、 store でデータを取得しました。 // 必要な部分のみ const actions = { // ページ遷移でサイドメニュー更新しなくても良いので nuxtServerInit メソッドを使っています async nuxtServerInit ( { dispatch } , context ) { await dispatch ( "fetchArchives" ); // ... } } ; export default () => new Vuex.Store ( { actions , // ... } ) あとは、この値を Getter や store プロパティ経由で取得・設定することで、サイドメニューの表示が実装できます。 まとめ 簡単にですが、 Firebase と Nuxt.js を使うことで、個人でもブログのような Web アプリケーションを作る事を紹介しました。 明日は @umaaaaa さんの記事です!
こんにちは、シニアブロックチェーンエンジニアを名乗っている @koropicot です。 これは 2018年モバイルファクトリーアドベントカレンダー 5日目の記事です。 前日は 元モバイルファクトリーの @karupanerura さんの 非TLS時代のセキュアなデバイス認証の思い出 でした。 はじめに モバイルファクトリーは2018年より本格的にブロックチェーンに参入し、ブロックチェーン上の分散型アプリケーション(DApps)を広めることを目指すUniqysプロジェクトというものを進めています。 このプロジェクトの中で、ブロックチェーンを勉強しブロックチェーンを作るに至りました。 プロジェクト自体の話は サイト などに譲るとして、この経験を元に、ブロックチェーンの技術領域のそれぞれについてどう学ぶかを共有します。 ブロックチェーンの全体像を学ぶ まず、個々の技術領域に触れる前に、ブロックチェーンの全体像をざっくり把握します。 なぜなら単にブロックチェーンといっても、他の多くのシステムと同じく、多くの構成要素が関連しあうことで全体で満たしたい要件を実現しているからです。 では、ブロックチェーンとは何でしょうか。 実は最初に把握したいこの全体像が、ブロックチェーンにおいて1番わかりにくい部分かもしれません。 なぜなら、立場やプロジェクトによってブロックチェーンをどう定義し何を重視するかが異なり、それぞれが何の話をしているのか混乱するためです。 そのため、例えばBitcoinについて学んでブロックチェーンを理解した気になっても、別のプロジェクトについて調べた途端に何も分かってなかった気分になります。(なりました) これを乗り越えるためには、どのようなレイヤーが存在しそれぞれがどこの話をしているかを意識するとわかりやすいです。 ざっくり書こうと思ったのですが、以下の記事によくまとまっていたので委譲します。 https://magazine.ginco.io/post/kisochishiki_blockchain_ecosystem/ この記事における、ビジネス・事業領域と技術開発領域が、エンジニアの関わる領域となります。 それぞれについて見ていきましょう。 アプリケーション(DApps)領域を学ぶ ビジネス・事業領域では、エンジニアはこれまでのアプリケーションの開発と同じように、サービスを実現するために使える技術を把握して選択し、それらを用いてアプリケーションを実装することが求められます。 そのため、この領域の学習は既存のアプリケーション開発における技術の習得と同じ方法が有用です。 人によってやりやすい方法があると思いますが、自分の場合はどうしていったかを記します。 選択肢を学ぶ 既存のサービス、例えばWebアプリケーション開発でも、OS・サーバ・DB・言語などの技術を適切に選択するためには、それら自体やその長所・短所を幅広く知っている必要があります。 これはブロックチェーンを用いたアプリケーションでも変わりません。 自分の場合は、事業として技術開発領域にも挑みたいということから、競合としての既存のDAppsプラットフォームについて調べましたが、事業領域でアプリケーションを開発する場合にも、選択肢を事前に把握しておくと良いでしょう。 索引として、DAppsを開発するうえで知っておきたい、選択肢になりうるブロックチェーン(レイヤー2を含む)についてざっくり示しておきます。 Ethereum 現在DAppsを実現するプラットフォームとしては最も人気でコミュニティも活発 パブリックチェーンは(現在のところ)PoWを用いており処理時間と実行にかかる手数料が課題 UX的に受け入れられるアプリケーションでは第一の選択肢 Hyperledger Fabric 主にコンソーシアムやプライベートチェーンを実現するための基盤 大手企業がプロジェクトに参入 既存のビジネスにブロックチェーンを適用する場合には有力な選択肢 Uniqys Kit (知っておきたいに入れるのは半分ポジショントーク) Ethereumのサイドチェーン(レイヤー2)としてスケーラビリティの改善と容易な開発を目指し開発中 サイドチェーンとPBFTベースのコンセンサスによりアプリケーション毎の素早い処理が可能 Ethereumをそのまま使うだけではUX的に問題のある場合に選択肢となる Loom Network Uniqys Kitと結果的に同じような感じ My Crypto HeroesというDAppsが利用 素早い処理が可能でEthereumをそのまま使うだけではUX的に問題のある場合に選択肢となる EOS パブリックなDAppsのプラットフォームとしては中国などで人気 DPoSによりEthereumよりも高速な処理を実現し開発者がリソースの費用を負担することで利便性を向上 Ethereumに比べると発展途上なのと情報が日本だとまだまだ少ないのが課題 他にも関連するブロックチェーンやソフトウェアも多くありますので、上記の選択肢と比較すると理解しやすく、ユースケースにおいて適切な選択肢が見えてきます。 とはいえ、Webアプリケーションなどに比べればまだまだ発展途上なことや、ブロックチェーン特有の課題から、最適な選択肢が見つからないかもしれません。 そのような場合は、一旦下のレイヤー(プロトコルレイヤー)に降りて見ると、ブロックチェーンとしてどのようなトレードオフがあるかが見えてきて、選択の手助けになります。 開発を学ぶ DAppsの実装は、それぞれのブロックチェーンによってプログラミング言語やアーキテクチャ、開発ツールが異なるのでそれらに合わせて学ぶことになります。 Ethereumを用いる場合は、 CryptoZombies という学習サービスが有名です。 アプリケーションによっては検証可能にするためコードを公開しているものも多く、これらも参考になります。 例えば、CryptoKittiesというEthereum上のDAppsのコードは ここ で確認できます。 また、ブロックチェーンとやり取りするクライアントとしてはWeb3というものがデファクトスタンダードで、バージョン1.0が絶賛開発中で、インターフェイスが変更されているので、今から始めるならこちらがおすすめです。(ただしバグも多いです。コントリビュートチャンス!) またこれは宣伝ですが、Uniqys Kitを使う場合はDAppsを既存のWebアプリケーションのように作成できます。 そのため最初の学習のハードルは低くできていると自負しています。 いずれにしても、この領域は結局のところ既存のアプリケーションの学習とほぼ同じです。 開発だけなら特に仮想通貨もいらないので、実際に作ってみるのが良いと思います。 ただし、特有の注意点として、サービス自体や全体の設計に関わる以下の特徴は最初から意識しておくと良いです。 パブリックチェーンの場合は処理は誰でも確認できてしまうこと チェーンによって異なるが処理に数秒から数十分かかること チェーンとの接点となるノードは信頼しないといけないこと(場合によっては管理下にノードを構築する) アカウントの認証は多くの場合秘密鍵に依存していてその管理は自己責任であること ブロックチェーン外の情報は基本的に扱えないこと 誰にも操作されない乱数も容易には実現できないこと サービスを展開する地域の法律(日本の場合は資金決済法など)によっては規制があること プロトコルレイヤーを学ぶ 技術開発領域はプロトコルレイヤーとも呼ばれ、コンセンサスアルゴリズムなどの分散システムや暗号理論、インセンティブ設計、オフチェーンやサイドチェーン、コントラクト検証などの数多くの部分からなります。 これらの領域は課題が多く存在していて、チャレンジのしがいがありますが、一方で事業には直結し辛い部分のため人口も少ない印象があります。 しかし、課題を解決しないことには事業を含めたブロックチェーンの発展に限界があるため、ぜひとも多くの人に興味を持ってほしい領域です。 この領域を学ぶ場合は、理論を学ぶことと、それらをどう実装していくかの両面が必要です。 理論を学ぶ 理論を学ぶ際には、まずは何はともあれBitcoinの原論文を読むと良いです。 PDFを こちら から読むことができます。 また、日本語での解説も多くあります。 ここで注意しなければいけないのは、前述したようにBitcoinがブロックチェーンの全てではないということです。 しかし、Bitcoin以後に登場したブロックチェーンはBitcoinの課題を解決したり適用範囲を広げるために変化しているので、基準として知っておくのは有用です。 この次に何を学ぶかですが、概要さえわかっていればより深い部分は興味や必要がある場合に応じて進めていけばいいと感じています。 例えばUniqys Kitを作る上では、スケーラビリティの課題を解決する必要があったことから、レイヤー2の部分を調べ、必要に駆られてコンセンサスアルゴリズムについて学ぶという過程を経ました。 それ以外の部分は、何のためのどういうものかと言うのを知っている程度です。 では、それらをどのように学ぶのが良いでしょうか。 分散システムや暗号理論、形式的検証などはブロックチェーンの登場のはるか以前から存在している分野です。 またインセンティブ設計などもゲーム理論として捉えることができるでしょう。 そのため、これらの分野の既存の論文を当たるのが良いと考えています。 プロジェクトのホワイトペーパーなどを読むのも良いですが、やはり理論はちゃんとした土台があってこそ活きてきます。 また、今後のブロックチェーンの発展のためにはいかに既存の専門家をブロックチェーン界隈へ連れてくるかが重要になってくると思います。 実装を学ぶ 理論が理解できても、それを現実にしなければ利用することはできません。 また、理論も実際に手を動かしてみるとより理解できることもあります。 これらの実装の理解には、近しいプロダクトのソースコードが1番勉強になります。 ペーパーやドキュメント、参考書を読んでも理解できない部分や、腑に落ちないことはどうしてもあります。 そういったときに、もっとも具体的で、現状を反映しているのがソースコードです。 自分がUniqys Kitを実装した際にも、EthereumやTendermint, NEOといったブロックチェーンのソースコードを読んで参考にしました。 とはいえソースコードを読むためには、大規模すぎて取っ掛かりが分からなかったり、言語やプロダクトの文化や歴史が分からなかったりするなど難しい部分もあります。 そこで、これも宣伝なのですが、Uniqys Kitの実装は比較的分かりやすい(らしいという id:odan3240 さんの意見)ので、ぜひとも参考にしてほしいと思います。 まとめ ブロックチェーンは複数の領域からなるのでどの領域についての話かを意識して学ぼう ブロックチェーン上のアプリケーションはいままでと同じように手を動かせばわかる 理論に興味あれば既存の研究をちゃんとちゃんと追って巨人の肩の上に立とう やっていきましょう。 明日は6日目 id:mp0liiu さんです!
2018年モバイルファクトリーアドベントカレンダー 12/3担当の id:yashims85 です。 前日は id:odan3240 さんの NuxtMeetUp#5 でnuxt-i18nを用いたwebサイトの多言語化について話してきました でした。 まえがき 2018年今日において、クロスプラットフォーム(以降: X-PF)界隈を改めて見てみると、大手各社がそれぞれアーキテクチャを提供をしており、X-PF戦国時代の様を呈しています。 今回はその中でもKotlin/Native(以降: K/N)とFlutterに絞って比較を行いたいと思います。 確認した環境はそれぞれ2018/12/03時点で最新である以下です。 Kotlin - 1.3.10 (Kotlin/Native Beta) Flutter - v0.11.13-beta 実のところ、両X-PFを触る前は何を書こうか迷っていたのですが、K/N、Flutter、及び他のX-PFを触ってみて感じるのは、どのX-PFにも長短があり現時点での銀の弾丸は無いという事です。 そこで、今回はKotlin/NativeとFlutterの比較を行いそれぞれの長短を把握してもらうことで、自分の状況にあったX-PF選びの参考にしてもらえたらと思います。 今回やらないこと Getting Started 各PFのGetting Startedが引っかかる部分も無かったので、そのとおりにやったら良いと思います 最強のX-PFはコレだ! X-PFについて Android/iOSの両モバイルOSの登場以来、古今東西様々なX-PFが生まれては消えていきましたが、現在X-PF界隈に置いては、大手デベロッパーを背後に持つX-PFに淘汰されて来ています。 一例をあげてみましょう。 X-PF 主開発社 言語 特徴 Xamarin Microsoft C# X-PFとしての歴史、VisualStudioを使用した快適な開発環境、各PFそれぞれのUI実装 Unity Unity C# リッチコンテンツに強み、共通UI、独自ライフサイクル、ゲームエンジンベース ReactNative Facebook JS Reactと同じノリで作れる、共通UI Kotlin/Native JetBrains Kotlin AndroidStudioをIDEとして使用できる、各PFそれぞれのUI実装、まだBeta Flutter Google Dart Google系サービスならポン付け実装できる、独自ライフサイクル、基本は共通UI、まだBeta この中でもKotlin/NativeとFlutterはAndroidエンジニアにとって馴染みの深い2社が開発していることもあり、 気になっている方も多いんではないでしょうか? Kotlin/Native 現在のAndroidの標準開発言語であるKotlinを開発したJetBrains社が主導で開発を進めています。Kotlin 1.3からBeta機能としてKotlin/Nativeが提供されています。 K/NはKotlinという言語に対してX-PF機能を付加するアプローチをとっています。 K/Nは以下のような特徴があります。 宣言を実装を分けることができる言語仕様と各PF用のビルドシステムによって実現 AndroidではJVM言語として、DalvikVM、ART上で実行される iOSではLLVMで機械語にコンパイルされ、iosのframeworkとして吐かれる frameworkにはK/Nコードのシンボルがヘッダファイルとして包含されているため、Swift側からもK/Nのコードを参照できる UIの共通化機能は提供されておらず、それぞれのPFで実装する必要がある Flutter Googleが主導で開発を進めています。こちらもBetaですが、Betaとは思えないほど機能やドキュメントが充実しています。 Flutterは純粋に開発環境の共通化を目的として作るアプローチをとっています。 Flutterは以下のような特徴があります。 Dartは滅びぬ!何度でも蘇るさ! Android/iOSともに機械語にコンパイルし実行する UIパーツが多数提供されており、独自性の強いデザインを押し出さなければ爆速開発が見込める Reactに影響を受けたアーキテクチャ設計 各OSの機能とは遠い 開発環境 Kotlin/Native Flutter Android Studio / IntelliJ IDEA Android Studio / IntelliJ IDEA, VSCode 当然といえば当然ですが、どちらもAndroid Studioがそのまま使えるのが面白いですね。 どちらもBetaなので細かくは言及しませんが、現段階ではK/Nはディレクトリを作ったりbuild.gradleをいじったりと結構手作業で環境を構築する必要があり、若干の敷居の高さを感じます。 対してFlutterは、ASにPluginを導入するだけでFlutter環境をセットアップできるので、拍子抜けするほど楽ちんです。 またX-PF開発ではXcodeを触る時間をいかに少なくするかが鍵だと私は考えています。 この点においてもFlutterは現段階で一歩リードしており、Signing周りをポチポチするだけです。 対してK/NはBuildPiplineに手を加える必要があり、AppleのBuild周りの知識を要求されます。 言語 Kotlin/Native Flutter Kotlin Dart Kotlin/Native 言語的好みで言えば圧倒的にKotlinなのですが、X-PFを前提としたときK/Nは複雑性が上がり、可読性やメンテナンサビリティの低下につながる可能性があると感じました。 例えば、K/NではX-PF実現のために、1つのクラスを基本的には common に実装しますが、 必要に応じて宣言だけをcommonで行い、実装は Android iOS ... と複数のファイルに分割できるようになっています。 逆に、各PFの実装からcommonの処理を呼び出すこともできますので、きちんと設計を行わないと簡単にスパゲッティーコードを生み出すことができてしまいます。 また、非同期処理周りでも制約があり、現状ではCoroutineでの実装をおすすめしているようです。Rxなどは各言語の実装によるため異なる挙動を示す可能性があるためでしょう。 このへんの設計の難しさをクリアすれば、クライアントのみならずサーバともビジネスロジックを共有できるため、夢が無限に広がっていきます。 Flutter Flutterでは各PFの実装が処理の途中に挟まる事がないので、挙動の差異を気にする必要は最小で済むかなという感じです。 ドキュメント Kotlin/Native ドキュメントはありますが、ごちゃっとしていて全体像を理解するのに少し苦労します。とはいえ、不足していると感じるシーンは無く必要十分ではあります。 Flutter ドキュメントの整備度合いはFlutterに一日の長がありそうです。 Dart初心者に対してもEffectiveDartも準備されており、言語的マイノリティーに対してある程度の安心感があります。 周辺ライブラリ どんなライブラリが揃ってるかざっと見るのはawesome探すのが一番ですね。 Kotlin/Native Flutter awesome-kotlin-native awesome-flutter Kotlin/Nativeのawesomeが全然awesomeじゃないよ。。。 依存管理 Kotlin/Native Flutter Gradle Gradle どちらもASで開発できるので、必然的にGradleになるでしょう。わかる。 システム設計 まず、Kotlin/NativeやFlutterの特性を見ていく前に、プロダクト全体に対して与える影響をそれぞれ考えてみましょう。 Kotlin/Native K/Nは逆に設計に注力する必要がある、ある程度の規模が見込まれるプロダクトに向いています。 Clientだけでなく、サーバサイドまで1コードで実装できるのはとても魅力です。 K/Nは各PFで積み上げた資産やライブラリを有効活用しつつ、ビジネスロジックを共通化するアプローチをとれるとれるので、 システム設計の観点ではK/Nだから生まれる制約というのは特に無く、それぞれのPFの制約に依存する感じになります。 Flutter Flutterはミニマムで最速にリリースするのに向いています。 ただし、その分設計の自由度は少なく、他のアプリと差異を出すために特殊なことをしだすとFlutterのメリットは途端に消滅していく印象です。 サーバサイドについてもGoogleのサービスであれば一通りライブラリは揃っているけど、離れるほど少なくなる印象です。 サーバレスアプリケーションも(Googleのサービスベースなら)作りやすいんじゃないでしょうか。 ソフトウェア設計 それぞれのX-PFを採用したとき、それぞれどのようなソフトウェア設計が行えるでしょうか?X-PFは抽象化度によって、取りうるソフトウェア設計の幅に差が出てきます。 Kotlin/Native K/NではBetaになって日も浅いこともあり、めぼしい設計アーキテクチャは見当たらない印象です。 Pure-Kotlin向けならありますが十中八九JVMに依存しており、そのままK/Nで使用できるとは限らないため判別が付きません。 また、K/Nは言語の項目で言ったとおり設計の難しさがあり、特に多人数で開発するプロダクトでは注意が必要です。 基礎設計を行う時間を取れるプロダクトでは選択する価値がありますが、大規模でとにかくリーンというプロダクトではそれなりの負債を覚悟しなければなりません。 逆にそこがクリアできるのであれば、設計の自由度は高く、好きなように実装できると思います。 Flutter Flutterに関してはReactにインスパイアされたfluxアーキテクチャで実装されており、モダンなアーキテクチャを強制されます。 また、先行事例も多く参考を得やすいでしょう。 UI設計 UI設計に置いてはどういった長短があるでしょうか?近年の開発現場では非エンジニア職が直接UIの実装を行うシーンもしばしば見られます。 そうしたとき、UIの設計/実装のしやすさは判断基準の一つになります。 Kotlin/Native K/NではUIは各PFで実装する事になります。それぞれのPFに適したUI設計ができる反面手間ではあります。 現在Android/iOSともにGUIでデザインできる機能が備わっているので、それがそのまま利用可能です。 Flutter Flutterではレンダリングも独自で行っており、HotReloadに対応してるのが強みです。 UIパーツはWidgetという単位で公式/非公式問わず公開されており、ありものを拾ってくるのが容易です。 UIもコードで表現されるので、UIの修正が手間な印象を受けます。 ただし、Flutter自体がfluxアーキテクチャで動いており、そのへんの流れを知ってないと大規模なUI設計は難しい印象を受けます。 まとめ いかがでしょうか?個人的な印象としては K/Nは選択肢としては選択可能であるが、現段階では自由度が高い半面、開発難易度も高い。 Flutterは開発効率は高いが融通の効かない部分も多く、将来的に手詰まりになる可能性はある という印象を受けました。 まとめとしては、まえがきに書いた事の繰り返しになってしまいますが、X-PFにおいて銀の弾丸は無いので、 自身の開発内容にあった特性のX-PFを選択していきましょう。 明日は id:karupanerura さんの 「非TLS時代のセキュアなデバイス認証の思い出」 です。
こんにちは、ソフトウェアエンジニアの id:odan3240 です。 モバイルファクトリー Advent Calendar 2018 2日目は、 NuxtMeetUp#5 でnuxt-i18nを用いたwebサイトの多言語化について話してきたので、nuxt-i18nの紹介をします。 発表資料は、こちらです。 speakerdeck.com nuxt-i18nとは i18nとはinternationalization(国際化)の略で、ソフトウェアを様々な国や地域に対応することを指します。vueでこのi18n対応を行う場合は、vue-i18nというライブラリを使用するケースが多いです。 nuxt-i18nは、 vue-i18n のtranslation機能をnuxtのモジュールとして提供しています。具体的には、このモジュールを導入すると、 I18n クラスのインスタンスや t 関数がinjectされます。 他にもi18nで対応する言語に応じたルーティングの自動生成や、SEO対策を行ってくれます。 nuxt-i18nの機能 vue-i18nにはないnuxt-i18nとしての機能を紹介します。 ルーティング自動生成 nuxt-i18nでは、対応したい言語に応じて自動的にルーティングを生成してくれます。 設定ファイルに、nuxt-i18nの設定を次のように記述します。ここでは日本語と英語の設定をし、デフォルトの言語は英語を指定しています。 index.vue, about.vue というpage があるとします(下図参照)。 すると、各言語をprefixにしたpathが生成されていることがわかります。今回の設定ではデフォルトの言語が en のため、 / にアクセスすると、英語ページの index.vue の内容が表示されます。 便利な関数 nuxt-i18nを導入すると、次の2つの関数がグローバルに展開されます。 localePath localePath 関数は言語に応じたpathを返します。 switchLocalePath switchLocalePath 関数は、指定した言語への切り替えを行います。 SEO対策 Webサイトが多言語に対応している場合、検索エンジンのクローラーにそのことを教えてやる必要があります。これを行うには hreflang 属性などで指定する必要があります。nuxt-i18nではこれらの属性を設定ファイルから自動的に生成してくれます。 ハマった点 ここでは実際にnuxt-i18nを導入してハマった点について紹介します。 SEO対策を有効にすると
 headタグ内が壊れる SEO対策用の属性を自動的に生成してくれると、先程紹介しましたが、この設定を有効にすると <head> タグ内のいくつかのタグが消え、開発者が用意したjsファイルやcssファイルが読み込まれないという問題が報告されています。 github.com 開発中にこの問題に遭遇し、調査を行いましたが原因が判明しませんでした...。 https://uniqys.net では、nuxt-i18nのseoフラグを無効化し、手動で hreflang などの属性を生成しています。 ルーティングの自動生成の戦略の少なさ nuxt-i18nでは prefix_except_default と prefix の2つのルーティングの自動生成の戦略が用意されていました。 対応する言語が ja と en で、デフォルト言語が en のとき、この2つの戦略は以下のようなルーティングを生成します。 しかし、webサイトとしてのあり方を考えると、この3つのパスに対して200を返して欲しくなります。 そこで、このすべてのpathに対して200を返す戦略を実装しPullRequestを投げたところ、マージされました。 github.com この戦略は https://qurage.app で実際に使用されています。 まとめ nuxt-i18nの機能を一部紹介しました vue-i18nを利用したtranslation機能 対応する言語に応じたルーティングの自動生成 対応する言語に応じたSEO対策用の属性生成 多言語化を行う必要のあるwebサイトを作成する場合にはnuxtとnuxt-i18nの使用を検討してはいかがでしょうか
こんにちは、コーポレート・コミュニケーション室 シニアエンジニアの id:kfly8 です。 モバイルファクトリー Advent Calendar 2018 1日目は、 モバファクの社内勉強会について紹介します。 社内勉強会は会社ごとに色々なカラーがあると思いますが、モバファクの場合「業務時間に1日1時間、自由形式」で運用しています。 1日1時間 毎日2部屋予約しておき、いつでも気軽に勉強会開催できるようにしています 開催ネタが無ければ、開催しない日もありますが、だいたい何かやっています 直近の11月の開催数は11回、10月は14回、9月は16回だったようです 自由形式 勉強会の開催形式は、開催する人の好きにしてもらっています 例えば、講義、LT会、読書会、ワークショップなどの形式があります 直近だと、次のような書籍の読書会や、 VueFes のフィードバック、HPCの行列積計算の話、結婚式プロフィールムービーの作り方の話がありました:D オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング) 作者: バートランド・メイヤー 翔泳社 Amazon UXデザインの教科書 作者: 安藤 昌也 丸善出版 Amazon カイゼン・ジャーニー たった1人からはじめて、「越境」するチームをつくるまで 作者: 市谷 聡啓 , 新井 剛 翔泳社 Amazon なぜ勉強会をするのか? 成長のため、スキル向上のため、です。 勉強会なので「成長」は当たり前の答えかもしれませんが、 成長することは、例えばプロジェクトが捗ったり、将来やりたいことが実現の助けになったりと、良いことずくめです。 勉強会で成長促進出来るのであれば、良いことだと思っています。 成長のために、気づきは大切です。 勉強会参加者に気づきがあれば良いですが、多くの場合、主催者の方が気づきが多いです。 開催ネタを言語化し、フィードバックを得ることで、効率的に気づきを得られます。 こういったアウトプットの効用については、はてなさんの はてなエンジニアに期待する「アウトプット」 に綺麗にまとまっています。 どんなネタが良い? 主催者が、知りたいこと、関心のあることが良いネタだと思います。 むしろ「良いネタを話さないといけない」と縛られないで欲しい、 アウトプットをせず、気づきの機会を失う方が良くないと思っています。 例えば、業務に「今」必要なことに縛られる必要もないです。 むしろ、投機的に勉強していくことの方が大切で、その方が将来の変化に対応できると思っています。 また何か特定のスキルを身につけることや、職種の対象も限定していません。 例えば、ディレクター、デザイナーの話を、エンジニアが聞いたりと、異なる職種間で話すことで得られる気づきがあると思っています。 勉強会の文化 そもそも、アウトプットして、お互いに話すことって楽しいですよね。 大げさですが、そういう文化が良いと思っています。 私が新卒入社して8年くらい経ちますが、それ以前からこんな感じでやっているようです。 (開催ハードルが上がり、開催が少なかった時期もあったり色々変化はあるのですが、それは別の機会があれば...) お金を支払えば、研修を実施することもできるかもしれませんが、 そうではなく、自分たちがどうありたいか、何が良いと思うか、 自由に発想できる場が、モバファクの社内勉強会です! モバイルファクトリーは、技術好きなエンジニアを募集しています。
はじめまして。コーポレート・コミュニケーション室の id:kfly8 です。 このたび、モバファクの技術ブログをはじめることになりました!日頃の開発で得られた知見など書いていければと思っています。 どうぞよろしくお願いします。 先日、研修の一環で、社内ISUCONを開催しました。ここでは、簡単に様子の紹介と問題を作るにあたって考えたことを述べます。 ソースコードはこちらです。 GitHub - mfac/mfac-isucon 課題アプリケーション 課題は、地図上にメモを残す、位置情報を使ったアプリケーションでした。具体的には次のようなことができます。 テキストのメモを位置情報と紐づけ投稿できる メモの閲覧ができる 投稿順 メモに紐づけられたハッシュタグと関連したメモ メモの位置情報のご近所 メモに絵文字でリアクション 実装の概要について書きます。フロントエンドはVue.jsでSingle Page Application(SPA)な構成にし、地図の表示にはOpenStreetMapとleaflet.jsを利用しています *1 。バックエンドで用意した言語は、PerlとGolangの2つです。サーバは ConoHa のVPSを利用しました。ConoHaはシンプルな使い勝手で使いやすいですね! 初期データは、メモを約10万件程度用意し、それに紐づくリアクションを同程度用意しました。 テーマ・背景 今回、弊社で社内ISUCONを開催した際、気軽に参加しやすくする為、チームでなく、1人参加としました。また普段の開発の振り返りになるように、とっつきやすいような問題設定を考えました。具体的には次のようなことを考えました。 構成は簡素にする サーバは1台構成にする 迷い道を減らす為、アプリケーションの振る舞いは少なくする 競技の体裁を保つため、位置情報関連記述の知識によって、優劣が発生しないようにしたい 近傍探索の問題をまじめに(?)解く必要がないようにする→データを小さくしてしまう *2 参考実装では、余計なことはせず、mysql の buffer pool に載せるで十分解でした。 本物のISUCONでは避けているような「データをメモリに乗っけておしまい」「言語選択による差異が出る」という状況が起きやすい問題設定だったと思いますが、社内ISUCONだったのでそれも一興とし許容しました。 また、運営の負担を減らす為に、次のようなことを考えました。 *3 フロントエンドの実装を共通にする ビジネスロジックは、SQLに寄せることで、言語移植を簡単に済ませる 認証なしのSPA構成にして、ベンチマーカーのシナリオ実装を json.Unmarshal するだけに寄せる こういったことは運営側になってはじめて気づくことができ、面白かったです。 社内ISUCONの様子 実際の社内ISUCONの様子はこんな感じでした。 社内ISUCON初代チャンピオンの様子。 寿司の様子。美味しい。 これは今日行われた社内ISUCONの様子です pic.twitter.com/r9VvVJxn4d — odan (@odan3240) 2018年9月11日 まとめ 社内で、地図にメモを残すアプリケーションのISUCONを実施した ISUCONは、運営側を体験することでも気づきが得られる ISUCONは楽しいですね! モバイルファクトリーは、技術好きなエンジニアを募集しています。 *1 : ベンチマーカーが外部サービスに負荷をかけない為に、SPA構成だったことは都合がよかったです *2 : データが大きい場合のデータの間引く方法の一例はこちらを参照 2015年のYAPC::Asia のランチセッション で紹介しました *3 : 運営負担を減らすのであれば、過去実装を使えば良かったかもしれないですが、魔が差しました