vivid_muimui

サーバーサイド勉強会(2017年5月)


東京スタジオのエンジニアの小山です。

この記事では、5月中に行われたサーバーサイド勉強会の内容を紹介したいと思います。
サーバーサイド勉強会の紹介や4月分の内容は前回の記事を見てください。
https://developer.aiming-inc.com/study/server_side_study_201704/

5/11 LT

月初のLTです。

今回は全体的に真面目な勉強ネタという感じではなく、ゆったりとしたものが多かったです。(公開できるスライドが少なくてすみません><)

記号でRuby

社内である日突然出された以下の問題の解説でした。

Ruby (2.3.x あるいは 2.4.x) で以下の条件の下に Hello という文字列を標準出力に出力するプログラム、
あるいはそのようなプログラムを出力するプログラムを書きなさい。

アルファベット、数字、スペース、\u007f 以上のコードポイントの文字を利用してはならない
つまり↓の文字のみを使ってよい
解答時に、レイアウトの都合でプログラムの意味が変わらない程度の改行の挿入は許可

!"#$%&'()*+,-./:;<=>?@[]^_`{|}~

(回答の例はこちらです。)

解説されている間はなんとか理解できている気がするのですが、魔術を説明されているようでとても難しかったです><
解説のスライドは公開できませんでしたが、ぜひ皆さん挑戦してみてください。ちなみに僕は解けませんでした!

5/18 code smellを検出するreekのチェック項目を読む

reekというコードスメルを検出するgemのチェック項目を読む回でした。

Reek is a tool that examines Ruby classes, modules and methods and reports any code smells it finds.

https://github.com/troessner/reek/blob/master/docs/Code-Smells.md
このページにチェック項目一覧があるので、上から順番に眺めていきました。

どれもチェック項目として納得いくものばかりですが、実際運用することを想定したときに、

  • 全部デフォルトだと厳しい
  • ケースバイケースなのでどこに基準を設定するのか難しい
  • 養成ギプスとしては良さそう

というのが全体的な感想でした。
あまりプログラムを書くことに慣れていない・Rubyに慣れていないという場合には設定するとメリットが大きそうです。そうでない場合には、Reekの設定のメンテコストや指摘箇所の対応コストが発生し、メリットよりもデメリットのほうが大きくなりそうという印象です。
ただ、こういうコードスメルがある事自体はちゃんと認識しておく必要があるので、たまに思い出したときに初心に返る気持ちで見直したいなと思いました。

5/25 react-rails の入門ハンズオン

@yhirano55によるreact-railsの入門ハンズオンでした。
@yhirano55がこのハンズオンのために用意した資料を見ながら進めました。react-rails gemに特化した内容ではなく、Reactに触れてみよう、ReactをRailsで使ってみよう、という内容のチュートリアルでした。
資料がとても良くできていて、1時間という短い時間でしたがとりあえず動かすことができて基礎も理解できました。恐る恐るレビューしていたReactのコードも今はちょっと読めるようになりました!
資料は口頭での解説がなくても十分できるようになっていると思いますので、興味ある方はぜひやってみてください。

おわりに

5月はGWがあったので3回分だけでした。
今月はReactのハンズオンが個人的にとても良かったです。Reactに関する情報は色んな所で見聞きしてはいましたが、実際に触ったことがなく、なんとなく怖いという印象を持っていました。ですが、今回実際触ってみると全然怖くないなって思いました!
情報を見聞きして満足するだけでなく、実際触ってみることが大事だなと改めて痛感した回でした。


syoshino

AssetBundleGraphTool を触ってみました


エンジニアの吉野です。

先日アップデートされたばかりの AssetBundleGraphTool v1.3 をこれまた先日リリースされた Unity 2017.1 に入れてみました。

AssetBundleGraphTool の bitbucket ページ
日本語マニュアル

今回はゲームで使用する Asset がどの AssetBundle に入っているかのテーブルデータをカスタムノードで作成したのでかいつまんで紹介しようと思います。

概要

ゲームで Asset を読むときに、開発中はローカルから、実機では AssetBundle を使いたいということが良くあります。
(Unite 2017 で紹介されていた Addressable Assets が入ればいらなくなるはずなので、それまでのつなぎで…)
これを満たすための仕様としては、おおむね以下の図のようになると思います。

asset load flow

この図の AssetBundleTable で使う AssetPath → AssetName 変換用のデータをカスタムノードで作ります。

完成したGraph図はこのようになります。

graph sample

カスタムノードの作り方は日本語のマニュアルの「カスタムノードを追加する」を見てください。
以下、作成したノードの要点を解説していこうと思います。

入力/出力するノードのタイプを指定する

今回は、「AssetBundle 名と AssetPath が設定されたノード」(Grouping)と 「AssetBundle をビルドするノード」(BundleBuilder)の間に入れたいので、以下のようにします。


    public override Model.NodeOutputSemantics NodeInputType
    {
        get
        {
            return Model.NodeOutputSemantics.AssetBundleConfigurations;
        }
    }

    public override Model.NodeOutputSemantics NodeOutputType
    {
        get
        {
            return Model.NodeOutputSemantics.AssetBundleConfigurations;
        }
    }

インスペクター上から AssetBundleTable を指定できるようにする

Inputされた情報を書き込む AssetBundleTable を渡せるようにします。
指定はエディタ拡張でおなじみの OnInspectorGUI(…) 部分に追加します。


public override void OnInspectorGUI(
    NodeGUI node,
    AssetReferenceStreamManager streamManager,
    NodeGUIEditor editor,
    Action onValueChanged)
{
...
    tableAsset = EditorGUILayout.ObjectField("AssetBundleTable Object", tableAsset, typeof(AssetBundleTable), false) as AssetBundleTable;
...
}

ビルド時に AssetBundleTable を更新する

Graph をビルドすると、カスタムノードの Build(…) が呼ばれます。この時に受け取った情報をTableに設定します。


public override void Build(
    BuildTarget target,
    Model.NodeData node,
    IEnumerable<PerformGraph.AssetGroups> incoming,
    IEnumerable<Model.ConnectionData> connectionsToOutput,
    PerformGraph.Output Output,
    Action<Model.NodeData, string, float> progressFunc)
{
...
    tableAsset.Clear();
    foreach (var ag in incoming)
     {
         foreach (var assetGroup in ag.assetGroups)
         {
             foreach (var inputAsset in assetGroup.Value)
             {
                 tableAsset.Add(new AssetBundleLoadPath(assetGroup.Key, inputAsset));
             }
         }
     }
     EditorUtility.SetDirty(tableAsset);
     AssetDatabase.SaveAssets();
...
}

AssetBundleTable 自身も AssetBundle にする

実機で使うので、AssetBundleTable も忘れずに AssetBundle にします。
幸いこの後に AssetBundle をビルドするノードがあるので、Output に追加して流します。


public override void Build(
    BuildTarget target,
    Model.NodeData node,
    IEnumerable<PerformGraph.AssetGroups> incoming,
    IEnumerable<Model.ConnectionData> connectionsToOutput,
    PerformGraph.Output Output,
    Action<Model.NodeData, string, float> progressFunc)
{
...
    EditorUtility.SetDirty(tableAsset);
    AssetDatabase.SaveAssets();

    if (Output != null)
    {
        var dst = (connectionsToOutput == null || !connectionsToOutput.Any()) ?
            null : connectionsToOutput.First();

        // 上流のノードから流れてきたものをそのまま渡します。
        foreach (var ag in incoming)
        {
            Output(dst, ag.assetGroups);
        }

        // AssetBundleTableを追加して渡します。
        var additionalOutput = new Dictionary<string, List<AssetReference>>();
        additionalOutput.Add(settings.tableAssetBundleName,
            new List<AssetReference> { 
                AssetReference.CreateReference(AssetDatabase.GetAssetPath(tableAsset), typeof(AssetBundleTableListData))
            }
        );
        Output(dst, additionalOutput);
    }
}

これで、作成した Graph がビルドされるたびに AssetBundleTable が更新されて、AssetBundle にまでなってくれます。
日本語のわかりやすいマニュアルがあるおかげで、すんなりと実装できてしまいました。

使ってみた感想

ノードの拡張機能があるおかげで Asset を読んで加工してなにかする、という機能をグラフィカルかつ低コストで作成できる素晴らしいツールだと思います。
カスタムノード以外にもいろいろな機能があるのでぜひマニュアルを見てみてください。
いろいろ応用できそうなので今後も活用していこうと思います!


水島 克

スマホゲームのUI仕様書


ゲームデザイナの水島です。

Aimingでは定期的に社内勉強会をやってます。

自分は若いプランナー向けにゲーム開発の基礎的な話をすることが多いのですが、新しいメンバーが増えてくると、何年か置いて同じ話を繰り返しすることもあります。手抜きといえばそのとおりなんですが、自分の中でも定期的に見直す良い機会だと思ってまして、今回もそんなお話です。

5年前に行った勉強会のスライド「企画が考えるスマホUIデザイン」は、現在27万viewと多くの方にみていただきました。

でもいま見返すと古いと感じるところも結構あります。当時はブラウザのソーシャルゲームからの移行期で、スマホネイティブのゲームも今ほど多く無かったため、いろいろ手探りの状態だったな~と思い出します。弊社の話でいうと、制作のパイプラインなんかは、その後だいぶ改善されたと感じてます。

そこで今回はもうちょっとテーマを絞って、UI仕様書について話してみることにしました。

スライドの中でも触れてますが、プランナーが書く仕様書の位置づけはチームによってバラバラ。しかも人によってはこだわりを持つ部分でもあるため、時に議論のたねになります。例えば、エクセル方眼紙のメソッドは宗教論争みたいになることもあって、傍から見てると面白い。

今回はもうちょっとマイルドに、「チーム毎に仕様書の項目の優先度をつけて書いてみてはどうか」という提案を盛り込んでみました。これが正解!というつもりもなく、選択肢の一つになるとよいかなと思います。

スマホゲームのUI仕様書

ちなみに5年前のスライドはこちらです。

企画が考えるスマホUIデザイン


Unity 2017.1.0 BetaでInspectorの入力ができなくなる問題を回避する方法


こんにちは。大阪スタジオ エンジニアの西村です。

現在開発中のプロジェクトではUnity 2017.1 Beta版を使用しています。

Unity 2017.1.0b3~Unity 2017.1.0f1のWindows版でInspectorの入力ができなくなるという不具合が発生していて作業に支障が出ていました。

人によっては不具合が発生しておらず、調査の結果Microsoft IMEを使っている場合のみ発生する事がわかりました。

回避方法

Unity使用時、キーボード設定をMicrosoft IME以外に設定する。

Google 日本語入力やUSキーボードを使用している人は不具合が発生していませんでした。

うっかり入力できなくなった時の対処方法

Componentメニューを開いて閉じるだけでInspectorに入力できる状態に戻ります。

不具合はUnityに報告済みで、いずれ修正されるでしょう。


吉田 正広

ルームの機能をモジュール化して、もうこれ以上コピペしなくて済むようにした話


はじめまして!

東京スタジオでエンジニアをしている、吉田と申します。

リリース後も、アップデートを繰り返していくオンラインゲーム。
安定したサービスを提供しつつ、常に新しい遊びを創造していくというのは、なかなか難儀なものです。

アップデートで機能追加をする度に、プログラマを悩ませるのが、

  • 安全のために、動作実績のある既存のプログラムはできるだけ変更したくない。
  • でも、コードの保守性や可読性のために、共通機能を関数化/クラス化するなどのリファクタもしたい。

こんなジレンマ。エンジニアのあなたも、身に覚えがありませんか?
それとも、「動いているコードは触ってはいけない」というルールを頑なに守って、リファクタを避けてはいないでしょうか?

でもそれだと、既存の仕組みに縛られて、新しい機能の実装が難しくなるし、アップデートと共に少しずつ大きくなって、今やなんの機能なのかわからないクラスなどがあると、バグの対応にも一苦労ですよね。

その上担当者も変わったりして、もう誰も中身を把握していない・・・、なんて状態になる前に、上手にリファクタしつつ、安全性も保ちながら、コードを保守していきたいものです。

先日4周年を迎えた「幻塔戦記グリフォン」(以下グリフォン)では、C++で書かれた、リアルタイム通信機能を担うサーバーがあります。
やはり4年もたつと、古いソースも多々あり、上記のような問題に常に直面しています。
今回は、新しい機能を実装するにあたって、私が行った取り組みについて紹介します。

現状のソース

グリフォンでは、いろんなタイプのクエストやバトルがあり、それぞれがクラスで表現されています。

CRoomBase          -共通で使う基本的な処理
  +- CQuestRoom         -シナリオなどのクエスト
  +- CPvPRoom           -定期的に開催されるPVP対戦
  +- CMockBattleRoom    -いつでもバトルが試せる、模擬戦
  +- CBattleRoyalRoom   -バトルロイヤル
  +- CColosseumRoom     -コロシアム

+- は継承を意味します。

CRoomBaseには、共通機能(主にゲーム内のオブジェクトの管理)が入っています。

それぞれの子クラスには、大まかに

  1. 入室までの処理
  2. ゲーム開始までの処理
  3. ゲームのルール処理
  4. ゲーム戦績の保存
  5. ゲーム終了後の処理

こんな機能が実装されています。

現状のソースコードを眺めてみると、こんな状態になっていました。

  • CPvPRoomCMockBattleRoomは、入室してゲーム開始するまでの流れが違うが、ゲームルールは一緒
  • CBattleRoyalRoomは、CMockBattleRoomをコピペし、一部機能を修正して作ったっぽい
  • その後、CMockBattleRoomにも独自の機能が追加されてるっぽい
  • その他、同じ様でちょっと違う処理が随所にみられる

だんだんつらくなってきた・・・もう既存のソースは見たくない・・ってなりました。
エンジニアの方なら、こんな気持ちをわかってくれるはず!!

そして今回

新しいゲームを提供するため、新たにルームクラスを作ることになりました。(仮にCNewBattleRoomとします)
その要件は、

  • 入室&ゲームスタートまでの流れはCBattleRoyalRoomとだいたい一緒
  • ゲームルール、戦績保存は、CQuestRoomとだいたい一緒
  • 加えて、今回初めて実装する機能

さてどうしたものか・・・
まず簡単に思いつく方法は、

  1. CBattleRoyalRoomをコピーして、CNewBattleRoomを作る。
  2. できたCNewBattleRoomのうち、いるものだけ残していらない物は削除する(もしくは使わないなら放置)
  3. CQuestRoomの一部機能をコピーしてCNewBattleRoomに入れる
  4. あと、足りない機能を入れる

こんな感じでしょうか。またコピペが増える・・・・
このアップデートをもって、サービス終了! ならこれでいいのですが、グリフォンはまだまだ続くのです・・!!

じゃあ、共通の機能を1つにまとめる? でも、共通化できそうな機能も、それぞれのルームで微妙に違ってたりするし(どうしてこうなったのか、もう分からないし)
これもつらいのです。

—-そして悩んだ結果、
よし、今回だけは、コピペを許そう。ただし、今後はコピペしないで済むようにする。

と決めました。

そのために、各機能をモジュール化して、そのモジュールたちを付け替える事で、ルームを表現できるようにします。

新しいクラス構成は

CRoomBase               -共通で使う基本的な処理
  +- CModularRoomBase        -各モジュールを乗せるためのベースクラス
      +- CNewBattleModule    -新しいルーム特有の機能を実装したモジュール
      +- CPvPCommonModule    -対戦共通モジュール
      +- CCommonModule       -共通モジュール

今回だけは、既存ソースからコピペして、各モジュールを作ります。

そして、モジュールを組み合わせたルームを生成するためのテンプレートクラスを

template <typename... Modules>
class CModularRoom : public virtual CModularRoomBase, public Modules...
{
...
};

こんな風に定義します。

例えば、Common,PvPCommon,NewBattleの3つの機能を実装した CNewBattleRoom を作成するには、

typedef CModularRoom<
    CCommonModule,           //テンプレート引数に、入れたいモジュールを羅列する
    CPvPCommonModule,
    CNewBattleModule>
        CNewBattleRoom;

こんな感じです。

こうしておけば、例えば今後、新しいルームクラス CHogeBattleRoom を作るときには、CHogeBattleModuleを作り、CNewBattleModuleと差し替えて、

typedef CModularRoom<
    CCommonModule,
    CPvPCommonModule,
    CHogeBattleModule>       //←ここだけ差し替える
        CHogeBattleRoom;

とすればいい訳ですね。

もし、CHogeBattleRoomを作るなかで、「CNewBattleRoomのこの部分は共通化したい」となった場合は、新しい CFugaCommonModule を作って、機能を分離すれば良いのです。

typedef CModularRoom<
    CCommonModule,
    CPvPCommonModule,
    CFugaCommonModule,     //←CNewBattleModuleから一部機能を分離
    CNewBattleModule>
        CNewBattleRoom;

typedef CModularRoom<
    CCommonModule,
    CPvPCommonModule,
    CFugaCommonModule,     //←分離して作ったモジュールをこっちにも入れる
    CHogeBattleModule>
        CHogeBattleRoom;

こうなります。

ところで、class CModularRoom がいろんなモジュールを多重継承してるけど、ひし型継承問題が起こるんじゃ?と思いましたか?

そんな時のために、C++には仮想継承という機能があります。

各モジュールに

class CHogeModule : public virtual CModularRoomBase
{
};

こんな感じで virtual 指定で継承すれば、ひし形問題は起こらずに済むんですね。

終わりに

今回の記事では、アップデートを繰り返していると必ず直面する、安全性 vs 保守性 のジレンマに対する弊社での取り組みについて紹介させて頂きました。
予測不能?なプランナーさんの考える企画を、リスクを回避しつつ、最大限の効果が得られるように、どうやって実現するか? エンジニアの腕のみせどころです。
Happy Programming!


mewlist

uGUI 描画優先度のチートシート


皆様,こんにちは!
株式会社Aiming の 土井と申します!
リードソフトウェアエンジニアをやっております!

ここ数年は,業務で Unity の uGUI を使って UI 開発をする機会が多いのですが、
Order in Layer, Sorting Layer, ヒエラルキ上の並び順……(つд⊂)ゴシゴシ
Unity では重なり順を指定する項目が多いですよね。
これらの項目間の優先度が実際にどうなっているのか理解していなかったため、調査を兼ねてチートシートを作ってみました!

描画優先度を指定するものを列挙してみた

どうやらこれらの関係を全て調べ上げれば良さそうです。

チートシート

調べました。
画像は実際に Unity の GameView で表示されたもののキャプチャです。

これで、もう UI の重なり順で悩まない!

解説

カメラ毎の優先度

  • Canvas に設定された Camera による優先度
    • ScreenSpace: Overlay 設定のものが最優先
    • 次いで Depth 値が高いものが優先

同じカメラに設定されたキャンバス同士

  • SortingLayer が高い Canvas が優先
    • 同じ SortingLayer 同士では、 Order In Layer の値が高い Canvas が優先
      • さらに同じ Order In Layer 同士では、Z 値が低い(カメラに近い) Canvas が優先

Mesh や パーティクルなど UI 以外の Renderer について

  • SortingLayer や Order In Layer の値による重なり順の制御ができる
  • ただし、SortingLayer と Order In Layer が同じ値を持つ Canvas がある場合、ヒエラルキ上の並び順による重なり順のソートは行われないので、 固有の Order In Layer 値を設定しよう

Render Queue について

  • UI の描画は、 RenderQueue = “Transparent” にて行われるため、独自のマテリアルを使用する場合は RenderQueue の値に 2501 以上を指定する必要がある

最後に

  • UI のレイヤーの間に 3D モデルを表示したりエフェクトを出したりといった要件のときには、まず全体の UI のレイヤー構成を整理して仕様化しましょう。行き当たりばったりで重なり順をいじっていると混迷を極めます
  • MeshRenderer などは標準でインスペクタ上から SortingLayer や Order In Layer が設定できません。
    • https://docs.unity3d.com/ja/current/ScriptReference/Renderer.html
    • 自前でスクリプトから設定する必要があります
      • (Order In Layer は sortingOrder というプロパティです)

おしまい。


oguma

ハートビーツさんと懇親会でLTをしました ’17 06/16


どうも、こんにちわ。

SNS幽霊部員ビリティ高めなOgumaです。
AimingではインフラをAll layerで担当しています。

先日6/16に、そのインフラに関係するMSP (Management Service Provider) である
ハートビーツ さんに 数名で 遊び 懇親会に行かせていただきました。

その際に後輩の趙くんと共にLTをやらせていただきました!!!

国内 (海外は担当が異なる) の公式サイトや、それらと連動するゲーム内から呼び出されるwebView向けのサーバなどをCephFS上に載せてみた話をしました。

さすがハートビーツさんっっ!!
いつもブログ等で勉強させていただいてる高いスキルをもった方々がいらっしゃいますね。
いろんな貴重なお話をさせていただいて、大変嬉しかったです。

また、発表した資料にさすがプロと言える鋭い質問をいくつも頂けました。

例えば

  • なぜCephなのか、Glusterではなかったのか
    • Glusterの方が高速に動いたからGlusterの方を選択した前例があったとのこと

など。 (お酒が回ってて、これ以上は思い出せませんw)

資料には書かれていないことなので、ここで補足という形で
我々がCephFSを採用した理由をまとめますと以下になります。

  • 今回の場合、I/O速度を求めなくて良いようなところに使用した
    • そのように設計した & なっている (I/0が必要なところはDB関係のみ)
  • CephがOpenStackで実績が積まれていて大部分が枯れている (LTSの安定に期待が持てた)
  • CephFSを使ってみたかった
    • 使ってみたら安定していた
  •  (今回の資料には書けていないところもありますが)高速化方法が色々把握できた
  • Kubernetes のPersistent diskでも対応している
  • スケーラビリティの高い分散ストレージClusterが必要
    • webViewや、イベントのアクセスが大量に来ることがあるため
  •  我々のGluster Storage (Redhatに買収されてからRHGSになった)の利用経験、実績がない

といった点です。

その他弊社からは
アプリケーションエンジニアより、昨今注目されているPrometheus についてLTがありました。

好評の触ってみたシリーズで、最後の刺さる点を共有してくれたところも勉強になりました。

hbstudyというITインフラ業界では有名な勉強会を開催している憧れの会社/エンジニアさんがいる会社で、スキル高いなーと再認識しました。
(人気が凄くてなかなか参加できていませんが、かなり前に個人的にもhbstudyに参加したことあります)

とても貴重で楽しい体験をさせていただけたハートビーツさんに
この場を借りて、心から感謝と敬意を表させていただきます。


菅野 明洋

社内でエンジニア読書会をやってみた!


はじめに

初めての人は初めまして!
前回の記事(第2回 Game Gatling LTに登壇してきました!)を見てくれてる人は、お久しぶりです!

大阪スタジオ インフラチームの菅野明洋です。
業務では、主に大阪スタジオのサービスインフラを担当させていただいております。

今回は、読書会を開いてみましたので、その話をまとめました。

読書会について

読書会は、集団で読書や読書に関するコミュニケーションを図るイベントです。
弊社では興味がある話題や本ごとに幾つかの読書会が開かれております。

開催してみた読書会について

今回は、SQLアンチパターンと言う本を題材にしております。
この本の読書会をするキッカケとしては、弊社の若手のエンジニアが最近読み始めたと言うことで話題に上がったことと、他のエンジニアと意見交換出来たら面白いと言う事で開いてみました。

読書会のルールについて

基本的に参加自由

  • 参加者は8〜12人程

開催時間

  •  定時後の45〜60分
    • 子育てで忙しい人も参加しやすくするために短めに設定
    • 経験上、1ページ2分換算で調整
  • 時間内(15〜20分程度)に章の全てを読みきれない場合は2日に分ける
    • 2日に分ける場合の例
      • 1日目にアンチパターンの問題点を黙読し他班に説明
      • 2日目にアンチパターンの解決策を黙読し他班に説明

用意したもの(書籍以外)

  • 付箋、筆記用具
    • 質問や意見を記入
  • ホワイトボード
    • 書籍の内容の説明や上記の付箋を並べるのに使用
  • キッチンタイマー(スマホアプリ)
    • 時間調整に使用

やり方

読書会の流れ

事前にやること

  • 読書会の日時、場所を決める

ステップ1(班分け)

  • 参加者を2班に分ける
    • 現在の決め方は座った席を順で分ける

ステップ2(読書フェーズ:アンチパターンの確認)

  • 各自担当箇所の章を黙読
    • 最近は読む際に付箋を配り、気になった点や質問したい内容を記入
    • ページ数に応じて変更しますが、大体15〜20分を目安にしています

ステップ3(説明フェーズ)

  • 読んだ箇所を別の班に説明
    • 説明する際は、図説する際はホワイトボードも使用
    • 章ごとに10分程度(計20分)の説明する

ステップ4(質問・討論フェーズ)

  • 全体を通して質問、討論を行う
    • 気になる点、分からない点を確認し解消する
    • 討論時にはアンチパターンに対してどのようにアプローチすべきなのか、他に方法が無いのかなど参加者の想いや考えなどのやり取り
    • 過去の話とかで盛り上がることもあります

読書会の様子

弊社の藤野がSQLアンチパターンの5章EAVについて説明している様子

読書会中に書き留めた付箋を集めてホワイトボードに貼っている様子(5,6章)

読書会中に書き留めた付箋を集めてホワイトボードに貼っている様子(3,4章)

ものすごく盛り上がっている時はホワイトボードにびっしり文字や図説が書かれていることもあったのですが、写真を取っていなかったため、現在記事を書きながら後悔しております。

読書会での試みと効果(参加者のフィードバック)

課題1:短時間で効果的に理解を深めたい

  • 対応策
    • 黙読後、読んでいない人に説明する
  • 効果
    • 説明する際に一度情報を整理するため、理解を深めやすくなった

課題2:質疑応答の敷居を下げる。意見を拾い上げやすくする

  • 対応策
    • 付箋を配布し、記入してもらう
  • 効果
    • 気軽に質問しやすくなった
    • 付箋を並べることで、他の参加者の質問(悩み)が見えやすくなる
    • 類似する意見があることで、他の参加者も同じ疑問を思っている等の安心感を覚える
    • 最初から質問・意見の数がわかるため進行の調整が楽になった

最後に

読書会を通して他のエンジニアと意見が交換できたので、とても参考になりました。
技術的な話のみだけではなく読書会の運用方法なども含め様々な意見を頂き、とても勉強になりました。今回の読書会では、まだ未完成な部分もあり進行が安定していないため、ブラッシュアップをしていかなくてはいけないと考えております。
毎回試行錯誤の繰り返している状態ではありますが、今後もこのようなイベントを続けて、より完成度を高めていきたいです。


vivid_muimui

サーバーサイド勉強会(2017年4月)


東京スタジオのエンジニアの小山です。

Aimingでは勉強会や読書会などがいろいろな形で行われているのですが、そのうちの1つにサーバーサイド勉強会という取り組みがあります。
この記事では、サーバーサイド勉強会自体の紹介と、4月中に行われたサーバーサイド勉強会の内容を紹介したいと思います。

サーバーサイド勉強会とは

サーバーサイド勉強会は、東京スタジオの主にrailsを書いているメンバーを中心とした勉強会で、週に1回1時間を業務時間中にとって行われます。(大阪スタジオでもサーバーサイドのメンバーを中心とした勉強会は行われています。)
内容や形式に関しては、「月初はLTを行う」というのが決まっていますが、それ以外は毎回違います。リリースノートを読んだり、ハンズオンをしたり、その時々で興味あるものホットなものをネタにやっています。

少し変わった取り組みとして、毎回常に Google Hangouts を使って社内のみですが配信をしています。忙しくて勉強会の会議室には行けないけど聞きたいという人や、大阪スタジオの人が見れるようにするためです。

参加人数は、会議室・Google Hangoutsそれぞれに10人弱ずつぐらいという規模で行われています。

4/6 LT

月初のLTです。LTの時間は5分でやっています。

  • Google Cloud Container Builderの話
  • ChainerRLを触ってみた話
  • UNIXコマンドの基礎
  • ズルいUI
  • 色の話
  • 美しい Slack 通知を飛ばす美しいコマンド
  • OSS Gateに参加した話

この記事を書くことになったのがLTの発表後だったため、公開できるように作られてないLTが多かったのですが、2つ公開できたので紹介します。

美しい Slack 通知を飛ばす美しいコマンド

https://rastamhadi.github.io/slides/slack_notification_command/

reveal-jsで表示されています. ?を押すとキーボードショートカット, sでスピーカーノートが表示されます

色の話


この回のLTは全体的にクオリティが高いものでどれも為になったのですが、個人的にUI/色の話がとても勉強になった回でした。
絵やデザインといった分野はとても苦手で避けてきたのですが、LTを聞いて頑張れば少しはできるようになるのでは?やってみよう、という気持ちができてきました。LTのあとの雑談で紹介された「ノンデザイナーズ・デザインブック」は速攻で注文し少しずつ読み進めてます!

4/13 Google Cloud Functions で Slack のスラッシュコマンドを作ろうハンズオン

https://cloud.google.com/functions/ 「Google のインフラストラクチャに基づくサーバーレス アプリケーション」

AWSでいうところのAWS Lambdaなのですが、そのCloud Functionsを使ってサーバーレスでお手軽にslackのスラッシュコマンドを作ってみよう、というハンズオンです。
ほかのサービスを連携したりせずに、ハードコードされたリストからランダムに選択しslackに返す、という実装をしました。

実際作られたものの一部が↓です。(どちらも僕が作ったものではありません>< )

シンプルな実装ではありますが、slackとgcpの画面をポチポチ設定して、少しのコードを書くだけでスラッシュコマンドが作成できて、本当にお手軽でした。
ハンズオンではやらなかったのですが、 Firebase Realtime Databaseを使ったスラッシュコマンドの作り方も紹介されました。

とてもお手軽だし便利で最高でした!
ですが、どんなスラッシュコマンドを作るかのアイディアが出ずに僕はまだ何も作れてないです!

4/20 Mastodonのコードリーディングとかアーキテクチャを覗いて見よう

流行りのMastodonのコードリーディングをする回でした。
https://github.com/tootsuite/mastodon
最初にMastodonがどういうものかという話がされ、rake stats -> Gemfile -> schema.rb -> modelを少し、という順に眺めていきました。
大半はGemfileを眺める時間に費やされましたが、知らないGemが多くrubyのエコシステムの充実さスゴイなと改めて思いました。

実装の詳細は全然見れなかったですが、「このgem知らなかった!便利!」とか「この書き方いいね」「この命名なるほど!」など十分有意義なコードリーディング回でした。

4/27 RailsGuideのActiveSupportのページ読み

RailsGuidesの「Active Support コア拡張機能」のページを上から眺めていくという回でした。
本家翻訳版

blank?tryなどのおなじみのが多いですが、上から順番に眺めていくと知らなかったものも結構ありました。
知らなかった中でぼくが便利そう!と思ったのは

この2つでした。

Object#instance_valuesはその名の通りinstanceのインスタンス変数をハッシュにして返してくれます。

class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}

使う機会はそんなに多くはないかもしれないですが、ActiveRecordの#attributesと似た振る舞いですし色々使いみちはありそうです。

String#squishString#stripと似てるのですが、冒頭と末尾のホワイトスペースを除去するString#stripの挙動に加えて、文字列中の連続したホワイトスペースを一つに減らしてくれます。

" \n  foo\n\r \t bar \n".squish # => "foo bar"

RailsGuidesは全体通すとボリュームが多いですが、見るたびに既に見たことが有るページでも新しい発見があるので、定期的に読み直さなきゃなと改めて思いました。

おわりに

月イチでLTを行う現在の勉強会のスタイルなって半年ほどなのですが、正直なところLTのネタ出しは毎回苦戦しています。
ですが、
LTをする -> 勉強会・LTを通して新しいことを知る -> ネタ出しのために勉強する -> LTをする(最初に戻る)
という良いサイクルが自分の中に出来上がりつつあって、現在の勉強会のスタイルは個人的にとてもありがたいスタイルだなと感じています。

まだ勉強会で吸収することばかりですが、そのうち新しいものを伝えていく側になれたらと思っています!


Webブラウザ版 『剣と魔法のログレス』のサーバーマシンリプレイスのお話し


はじめまして、大阪スタジオのサーバーエンジニアの太田と申します。

Webブラウザ版 『剣と魔法のログレス』(以下ログレス)は2011年にリリースして、おかげさまで今年で運営6年目になります。

そんなログレスも、そろそろマシンの老朽化やスペック不足が気になり始めたので、2017年3月にサーバーマシンのリプレイスを実施しました。

今回はそのお話しになります。

リプレイスの目的は?

  • 経年劣化によるハードウェアトラブルの回避
    • 全サーバーマシンを新しいハードに乗せ替える
  • 物理サーバーから仮想サーバーへ乗せ替え
    • サーバーの追加や削除が簡単に行える。
    • トラブル時の復旧も楽になる。
  • サーバーOSのバージョンアップ
    • OSのサポート期限が切れるため
  • 最新のクラウドサービスへ移行する
    • セキュリティの強化、保守性の向上
    • 構築や設定コストの削減

リプレイスに向けてのスケジュールと準備内容は?

  • 5か月前から準備開始
    • リプレイス内容の決定
    • タスクの洗い出し
    • スケジュールの決定
  • 4~3か月前
    • 物理サーバーと仮想サーバーでの各種ベンチマーク比較
    • 必要スペックの洗い出し、費用の見積もり
    • 動作検証用環境での各種動作チェック
  • 2か月前
    • 新クラウドサービス契約
    • OSのセットアップ、ネットワーク設定
  • 1か月前
    • ゲーム環境の構築
    • 各種動作チェック(課金認証等)
    • 本番当日のタイムスケジュールの作成
  • 1週間前
    • ステージング環境のリプレイス
  • 当日
    • 本番環境のリプレイス
    • DBとログの引っ越し
    • 本番環境での各種動作チェック

苦労したこと

  • バージョン違い問題
    旧環境で動作していた各種サーバープログラムが、OSバージョンやソフトウェアバージョンの違う新環境で同じように動作しませんでした。
    使用してるライブラリが新しいOSでサポートされておらず、対応に苦労しました。
  • 仮想化で発生した不具合
    仮想サーバーに乗せ替えてから、ゲームサーバー内の全てのスレッドがスリープ状態になる不具合が発生しました。
    調査するとスレッドをスリープする処理とウェイクアップする処理に問題があり、タイミングによっては今回の症状が発生する可能性があることが判明しました。
    物理サーバーではCPUのコンテキストスイッチの動作が安定していて問題が起こりませんでしたが、仮想サーバーにすることで不安定になって、問題が表面化しました。

良かったこと

  • 新たに契約した新クラウドサービスは、ネットワーク転送速度が10Gbpsなので、ファイルの転送速度が速くなり、メンテナンス作業が高速化しました。
  • マシンのスペックアップに伴い、必要マシン台数が減り、結果的に運用コストが軽減しました。
  • 利用できるメモリが増え、今後のゲームコンテンツの拡張がしやすくなりました。

まとめ

私にとってはサーバーのリプレイスは初めての経験でしたが、時間をかけて事前の動作検証や当日の作業準備などを行った結果、ログイン障害や課金障害等の大きな問題もなくリプレイスを終える事が出来ました。

今回の経験を通して、改めて事前の入念な準備と動作検証が重要だと思いました。

以上、ログレスのサーバーマシンリプレイスのお話でした。