RubyKaigi 2018 に参加した新卒のエモい話

IMG_4535.JPG

はじめに

こんにちは.2018年度新卒社員としてねこじゃらしに入社した開発部の村上です.

先日,RubyKaigi 2018 という Ruby の技術系カンファレンスに参加させて頂く機会がありました.

今までこのような技術系カンファレンスに参加したことは一度もなかったため,実際に参加するまで正直心臓バクバクでした.

学生時代は主に C++, Java, Python などといった言語を触っており,Ruby に関してはほとんど触ったことなく,RubyKaigi に参戦した時点の Ruby 歴はわずか2ヶ月.

右も左もわかりませんでした.

そんな私が RubyKaigi 2018 に3日間参戦して学んだことをまとめていきます.

全体を通した感想

RubyKaigi に3日間参戦して感じたことは 参加して本当に良かった ということです.

「おいおい,まだ Ruby のいろはもわかっていないやつが何言ってんだ」 と思うかもしれません.

しかし,私のとっての大きな収穫は Ruby に限らず,技術系スキル全般に対してもっと学びたいと思うようになれた ことでした.

モチベーションが上がった主な要因は以下の2つです.

  • 高い技術を持つエンジニアの講演を聞いたこと
  • さまざまなエンジニアと交流したこと

これだけではわからないと思うため,それぞれについて説明していきます.

高い技術を持つエンジニアの講演を聞いたこと

モチベーションが上がった要因の1つ目,高い技術を持つエンジニアの講演を聞いたこと

私は最初,RubyKaigi という名前を聞いたとき Ruby という言語に対して深く掘り下げがされるようなカンファレンスなのかなと思いました.

そのため,RubyKaigi では Ruby という言語そのものについての講演が中心になってくるのかなと勝手に想像していました.

しかし,実際の RubyKaigi は私が想像していたものとは少し様相が違っていました.

実際の RubyKaigi では Ruby という言語の話に終始することなく,各分野の内容を盛り込み,さまざまな業界を意識したものなっていました.

Ruby を使った深層学習プログラミングや組み込み,構文解析デザインパターンなど,RubyKaigi の講演を聞くだけで多くの分野の知見を聞くことが出来ました.

自分があまり関わって来なかった分野の知見を聞くことはとても新鮮で知的好奇心を非常にくすぐられました. しかし,それよりもエンジニアとしての圧倒的な技術力の差に打ちのめされることが多く,より一層学ばなければならないなという意識を植え付けられました

さまざまなエンジニアと交流したこと

RubyKaigi では開催期間中,毎晩 Drink-up Party というものが開かれており,エンジニア同士の交流の場となっています.

新卒で参加したこともあり,いろいろな方からエンジニアとしてどうあるべきかといったアドバイスを頂くことができ,エンジニアとして第一線で活躍されている方々がどのような姿勢で仕事をされているかといった話を聞くことが出来ました.

これが大きな刺激となり,技術を磨こうという意識に繋がりました

RubyKaigi は2部構成

RubyKaigi に参加して見えてきたことは RubyKaigi は2部構成の技術系カンファレンス だということです.

講演を聞く RubyKaigi昼の部 に過ぎず,夜の部 としてエンジニア同士の 交流会 が存在するということがわかりました.

RubyKaigi に初参加した私は毎日打ちのめされていました. 壇上の発表者とただ聞いているだけの自分を比較し,同じ人間とは思えないとも感じていました.

しかし,エンジニア同士の交流会に参加していく中で,先ほどまで別の生き物に感じていた人達と自分が普通に会話していることに気が付きました.

講演では技術面にばかりスポットが当たるので講演者が 得体の知れない何か に見えてしまいがちですが,交流会に参加するとその人の 内面 を知ること出来ます.

昼の部技術 を知り,夜の部人物 を知る. 他愛のない会話から,意外と普通の人なんだということを学び,自分もこんなふうになれるかもと思わせてくれる. とても追いつけそうにないと思っていた人物が具体的な目標へと変化する.

RubyKaigi にはそんな魅力がありました.

技術面精神面 を学べ,外的要因内的要因 によってモチベーションを上げてくれる RubyKaigi は間違いなく 2部構成の技術系カンファレンス だと言えるでしょう.

Ruby コミュニティ

RubyKaigi に参加して見えてきたこともう一つあります. それが Ruby コミュニティ の存在です.

RubyKaigi は,昼の部で 頭を酷使 し,夜の部で 身体を酷使 します. そのため,3日間フルで参加すると全身ものすごい 疲労感 を感じることになります.

今回,RubyKaigi に参加して思ったことは Ruby コミュニティの方々はこの 疲労感を楽しんでいる ということです.

みな同じくしてこの 疲労感 を感じることで,仲間意識 が生まれ,コミュニティの一員 であることを実感しているように見えました.

今回初参加した私も3日間フルで参加したため,とてつもない 疲労感 を感じていました. そのため,初参加でも Ruby コミュニティ というものをハッキリと感じ取ることが出来ました.

Ruby コミュニティの存在により, 「こんなすごい人たちに囲まれてるんだから,自分も頑張らなきゃ」 新米の私ですら強くと思わせられました.

Ruby コミュニティは RubyKaigi ひいては Ruby を語る上で欠かせないものだと思います.

新人エンジニアこそ技術系カンファレンスに参加すべき

今回,私が RubyKaigi に参加して強く思ったことは,新人エンジニアこそ技術系カンファレンスに参加すべき です.

「〇〇のことよく知らないし……」 「講演内容がわからなかったら参加する意味ないんじゃない?」 など,いろいろ思うところがあるかも知れません.

しかし,今回,新卒エンジニアとして何もわからない状態で技術系カンファレンスに参加した私はとても多くのものを持ち帰ることが出来ました.

とりわけ,RubyKaigi のような2部構成のカンファレンスに参加して得られるモチベーションはとても大きな財産になると思います.

また,2部構成のカンファレンスの昼の部と夜の部を通して参加することで,目標となる人物を見つけることができるかも知れないからです.

ここまでの話を聞くと,2部構成のカンファレンス以外に参加することは意義が薄いと感じられるかも知れません. しかし,2部構成のカンファレンスでなくても学べることはたくさんあります.

各日程の最初のセッションで行われる Keynote 講演は,俯瞰的な話が多くエンジニアとしての心構えのようなものが学べるため,新人エンジニアには特に良い刺激になります. また,細かい実装に関する講演で内容が理解できなかったとしても,話の構成やスライドの作り方など別の視点を持つことでさまざまな知見が得ることができます.

このような理由から 新人エンジニアこそ積極的に技術系カンファレンスに参加すべき だと私は考えます.

刺激を受けられる環境 に身を置くことがエンジニアとしての今後の 成長に繋がる のではないかと思いました.

最後に

入社してまだ2ヶ月しか経っておらず Ruby 歴も浅い,このような状況にも関わらず RubyKaigi に参加させて頂いた会社にはとても感謝しています.

RubyKaigi という技術系カンファレンスにせっかく参加させて頂いたのに,技術的な話ではなくエモい話中心になってしまったのは少し残念だなぁと自分自身反省しています. ただ,新人エンジニアにとってはこういったエモい話こそ重要なんじゃないかなぁとも思ったりします.

今回は技術力も何もない状態で参加しましたが,次回はもっと技術力を付けた状態で参加して,今年とはまた違った景色で RubyKaigi を楽しみたいと思います.

Android MVVM 設計 1

Android 担当の松下です。

Android アプリを作った時に Activity に全て詰め込んでしまった事はありませんか?
実は僕が Android アプリに join した時はそういう設計でした…。(リリースを急いでいたらしいので仕方ないですね 😓)
リリースが完了し少し落ち着いた頃に、大規模なリファクタリングを行うことが決まって、その時に 「MVVM」 にしようという話が出てきました。

そういった経緯で弊社アプリは MVVM の設計になりました。
今回は 「MVVM」 の恩恵を、経験に基づいて書いていこうと思います。

続きを読む

WCF で簡単にプロセス間通信

開発部の y-okubo です。

今回は C# の(正確には .NET Framework)WCF を使ってプロセス間通信を簡単に行ってみようと思います。

WCF の基本的な概念については以下の記事を参照してください。

www.atmarkit.co.jp

今回やりたい事を図にすると以下のような内容になります。

f:id:nekojarashi-Inc:20170814181814p:plain

WCF 関係コード

サービス実装

お行儀良くやるのであれば、インターフェイスの定義と実装は別ファイルにすべきでしょうが、ここはサクッと作ってしまいたいので単一ファイルに両方定義してしまいます。

using System.ServiceModel;

namespace Hoge
{
    [ServiceContract]
    public interface ISearchService
    {
        [OperationContract]
        void Execute();
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
    public class SearchService : ISearchService
    {
        public delegate void Searcher();

        public Searcher SercherDelegate;

        public void Execute()
        {
            SercherDelegate();    // 実装はデリゲートします
        }
    }
}

サービス起動(サーバ)

例外処理はかなりアバウトです。

SearchService service = new SearchService();
service.SercherDelegate = hogeForm.SearchRequest;    // デリゲート登録

serviceHost = new ServiceHost(
    service,
    new Uri("net.pipe://localhost/Hoge"));

try
{
    serviceHost.AddServiceEndpoint(
        typeof(ISearchService),
        new NetNamedPipeBinding(),
        "SearchService");
    serviceHost.Open();
}
catch (AddressAlreadyInUseException)
{
    MessageBox.Show("既にサービスは起動しています。");
}
catch (Exception e)
{
    MessageBox.Show(e.ToString());
}

サービス呼び出し(クライアント)

new ChannelFactory<ISearchService>(
    new NetNamedPipeBinding(),
    new EndpointAddress("net.pipe://localhost/Hoge/SearchService")).CreateChannel()
    .Execute();

サービス関連のハマり所

  • NetNamedPipeBinding() の引数はサービス側と呼び出し側で揃えないと例外が発生するので気を付ける。
  • EndpointAddress の指定を間違えないように気を付ける。
    • EndpointAddress は ServiceHost の URI と Endpoint を結合した文字列。
    • サービス側はこれらを別々に指定しているが、呼び出し側は結合した文字列を指定しているので注意。

Windows Forms 関係コード

実際にフォームを呼び出す

サービス起動時に登録したデリゲートメソッドです。

public void SearchRequest()
{
    // ここは必ず別スレッドで呼ばれる
    Invoke((MethodInvoker)delegate ()
    {
        MainForm_ShowSearchForm(this, null);
    });
}

フォーム呼び出し時のハマり所

  • メインスレッドで実行せねばならないので気を付ける。
    • 上記のメソッドはサービスのスレッド(バックグラウンド)から呼び出されることが分かっているので、InvokeRequired でのチェックを省略しています。

まとめ

WCF を使う方法について簡単に紹介いたしました。

プロセス間通信となるとかなり面倒なイメージがありますが、WCF を使えばサーバ・クライアント通信の様に行うことができます。

最近のアプリは役割毎に小さな粒度でプロセスを分けて緩やかに連携する、いわゆるマイクロサービス的な構成の物が増えているようですので、C# のみでアプリを構成するのであれば WCF は有力な選択肢になるかと思います。

WCF を使う上でこの記事がお役に立てば幸いです。

ねこじゃらしについて

ねこじゃらしでは C# に限らず Ruby (Ruby on Rails) や JavaScript での開発経験がある Web エンジニア、UI/UX デザイナを募集しております。

ご興味をお持ちいただけましたら、以下のリンクからお問い合わせください。

www.nekojarashi.com

シンプルなUIを作る

簡単なUIを作るために

開発部のiOS担当の林田です。 見た目上のUIがシンプルであっても条件が多い設計は実装に時間がかかり、文字や画像の多さ大きさなどでレイアウトが大きく変わってしまいます。 今回はスマホのUI設計をするときにシンプルで条件の少ないレイアウトを作っていきます。

このようなデザインがあったとします。

f:id:nekojarashi-Inc:20160825191953p:plain

これを要素ごと色分けをします。
ここでは各要素のマージンは8px(dx)として考えます

f:id:nekojarashi-Inc:20160825192220p:plain

要素としては

  • アイコン(黄色)
  • タイトル(緑)
  • テキスト(水色)

に分かれます。

iOSであればUIView、AndroidではViewと呼ばれる単位として分けます。 表示されるディスプレイの固定であれば問題ありませんが、スマホは端末によってサイズが異なります。

横幅の長い端末で表示するとこうなります。

f:id:nekojarashi-Inc:20160825192451p:plain

これはアイコンとタイトルの横幅が固定(Fix)になっており、背景とテキストの横幅が可変(Flexible)になっているためです。

f:id:nekojarashi-Inc:20160825192559p:plain

スマホのみならずブラウザでもよく見られるデザインで、固定値と可変値をもたせ、様々なサイズのディスプレイに対応します。

実はこのデザインには問題あります、タイトルが固定値となっているため、長いタイトルが入ると入りきれなくなります。
試しにタイトルをJectorからThe long title applicationに変更してみます。

f:id:nekojarashi-Inc:20160826154840p:plain

タイトルがテキストに被っているので、いくつか対応するレイアウトにしてみます。

  • タイトルの横幅がテキストの横幅より優先して表示される

f:id:nekojarashi-Inc:20160826155048p:plain

この場合条件は

  • タイトルの横は可変、縦は固定
  • テキストの横は可変、縦は可変
  • タイトルはテキストより先に横幅が決まる

ということになります。 非常に見難いレイアウトなっていますね。

  • タイトルは一定のサイズ以上になると後が省略される

f:id:nekojarashi-Inc:20160826155219p:plain

レイアウトは変わりませんが、もしタイトルがここでしか表示されないのであれば、ユーザーはすべてのタイトルは見えないことになります。

  • タイトルは、テキストの下に表示される

f:id:nekojarashi-Inc:20160826155330p:plain

この場合条件は

  • タイトルはテキストの下に表示される
  • タイトルの横は可変、縦は固定
  • テキストの横と縦は可変

とりあえずこれにしましょう。

ですがまだ問題があります。
先ほどタイトルはテキストの下に表示されるという条件を追加しましたが、テキストが少ない時にこうなります。

f:id:nekojarashi-Inc:20160826155452p:plain

条件を付け加えます

  • タイトルはテキストとアイコンのどちらか、縦幅の大きいほうの下に表示される
  • タイトルの横は可変、縦は固定
  • テキストの横と縦は可変

f:id:nekojarashi-Inc:20160826160023p:plain

これで正常に表示されました

ここまで変更するとタイトル上にあったほうが良いと思います

f:id:nekojarashi-Inc:20160826155917p:plain

  • タイトルの横は可変、縦は固定
  • テキストの横と縦は可変
  • アイコンの横と縦は固定

結構シンプルな条件になりました。

まとめ

  1. 要素ごと分ける
  2. 固定値と可変値を割り振る
  3. 最小値と最大値を決める
  4. 条件を付け過ぎると矛盾がおきたり、想定してなかったレイアウトになってり、実装に時間がかかったりする

お知らせ

ねこじゃらしではUI/UX デザイナを募集しております。

ご興味をお持ちいただけましたら、以下のリンクからお問い合わせください。

www.nekojarashi.com

Swift で MessagePack-RPC

ねこじゃらしの y-okubo と申します。

今回は、Swift で MessagePack-RPC を実現するライブラリの使い方を紹介します。

MessagePack-RPC については、こちらをご覧ください。

www.slideshare.net

ひとことで言えば、MessagePack (JSON) を使った RPC です。

各言語にライブラリが用意されており、異なる言語で作ったアプリ間でプロセス間通信をするのに便利です。

github.com

なぜか公式にはリストアップされていないのですが、Objective-C 版もあります(CocoaPods 対応がありがたい)。

github.com

今回は、コレを Swift から使ってみることにしました。

プロジェクトの作成

まず、Xcode で適当なプロジェクトを作成します。 今回は OS X - Application - Command Line Tool のプロジェクトを作成します。

f:id:nekojarashi-Inc:20160810182458p:plain

ターミナルでそのディレクトリまで移動して、以下のコマンドで CocoaPods をインストールします。

pod init

この後は、作成された Podfile に使用するライブラリを追加していきます。 Podfile を編集して、以下の内容を追加します。

pod 'MPMessagePack'

以下のコマンドを実行してライブラリをインストールします。

pod install

CocoaPods のライブラリを Xcode で使うには、先のコマンドで生成された .xcworkspace ファイルを開きます。

サンプルコード

簡単なコードを書いて動作確認をしてみます。

まずはサーバのリクエストハンドラを追加します。

RPC が呼び出されると必ずこのコードが実行されます。

メソッド名で分岐することで RPC 呼出しに対応したコードを記述できます。

今回は実験的なコードなので、そのような分岐はせず同じような戻り値を返しています。

func serverRequestHandler(messageId: NSNumber?, method: String?, params: [AnyObject]?, completion: (MPRequestCompletion)?) {
    if let method = method, let params = params {
        print("(Server) method:", method)
        print("(Server) params:", params)
    }
    
    completion!(nil, "Return from server(\(method))")
}

サーバを起動するコードを追加します。

リクエストハンドラを設定して、ポート 5001 番でサーバを起動してみます。

// Server

var server: MPMessagePackServer = MPMessagePackServer()

server.requestHandler = serverRequestHandler

do {
    try server.openWithPort(5001)
}
catch let error as NSError {
    print(error)
}

クライアントのコードを追加します。

こちらは非同期実行のコードになります。

var client: MPMessagePackClient = MPMessagePackClient()

client.openWithHost("127.0.0.1", port: 5001, completion: {error in
    client.sendRequestWithMethod("method_hoge", params: ["hoge", "42"], messageId: 1, completion: {error, result in
        if let error = error {
            print("Error:", error)
        }
    })
})

同期実行のコードは以下になります。 こちらは Exception を throw するので do ~ try ~ catch で例外ハンドリングをする必要があります。

client.openWithHost("127.0.0.1", port: 5001, completion: {error in
    do {
        try print(client.sendRequestWithMethod("method_fuga", params: [], messageId: 1, timeout: 2.0))
    } catch let error as NSError {
        print("Error:", error)
    }
})

注意点として、Command Line Tool でプロジェクトを作成している場合は、以下のコードも追加してください(このコードを追加しないと動きません)。

このコードで無限ループを回してクライアントからのリクエストを待ちます。

NSRunLoop.currentRunLoop().run()

では、コードを実行してみます。

2016-08-12 15:35:40.222 MsgpackRpcSwiftExample[11273:1429215] -[MPMessagePackServer connectionWithInputStream:outputStream:]:38: [Server] Client connected
(Server) method: method_fuga
(Server) params: []
(Server) method: method_hoge
(Server) params: [hoge, 42]

クライアントからの RPC 呼出しに対してサーバが値を受け取っているのがおわかりいただけるかと思います。

まとめ

MessagePack-RPC を Swift から使う方法について簡単に紹介いたしました。

他の言語についてもライブラリが存在するので、異なる言語間でプロセス間通信を行うような処理が必要になったとき、気軽に使えて便利です。

最近はマイクロサービス化によりコンポーネント疎結合化が加速しており、設計の都合やチームのスキルセットによって言語を使い分けるシーンも増えているのではないでしょうか。

そのようなときに、それらコンポーネントを繋ぐ方法として MessagePack-RPC は有力な選択肢になり得ると思います。

MessagePack-RPC を使う上でこの記事がお役に立てば幸いです。

お知らせ

ねこじゃらしでは Swift に限らず RubyJavaScriptプログラマ、UI/UX デザイナを募集しております。

ご興味をお持ちいただけましたら、以下のリンクからお問い合わせください。

www.nekojarashi.com