実践!クリーンアーキテクチャ + RxSwift

こんにちは、最近ほんのり?ふくよかになったオープンエイトの正原です。 ダイエットをしたいとは思ってはいるのですが、 「まだ寒い、まだ慌てるような時間じゃない」と自分に言い聞かせています。 そもそも一度に10kgのみかんが届くことなどないよう、ふるさと納税は計画的にすべきでしたね。

さて、今回のテックブログなのですが、 最近私が設計しているiOSアプリケーションにおけるクリーンアーキテクチャとRxSwiftを導入する際につまづいた点についてお話したいと思います。

クリーンアーキテクチャ

f:id:open8tech:20190310002048j:plain [引用元] : The Clean Code Blog

クリーンアーキテクチャはよく分からなくても「この図は見たことある!」という方も多いのではないでしょうか? 2012年にRobert C. Martin (Uncle Bob)氏がThe Clean Code Blogにて示した図です。 この図では主に「関心事の分離」と「依存性のルール」を表現しているのですが、 この図に関しては前述の本家のブログやその日本語訳版Clean Architecture 達人に学ぶソフトウェアの構造と設計、または多くのテックブログにて説明されているのでここでは割愛します。

Clean Architecture 達人に学ぶソフトウェアの構造と設計はソフトウェア開発における問題に対して、 クリーンアーキテクチャ(またはクリーンアーキテクチャで使われるテクニック)でどのように解消するかが分かりやすく書いてあるので、 一度は読んでおいて損はないと思います!ぜひぜひ!

どんな構成にしたの?

恐らく、多くの方が最初は私と同様に「理屈はなんとなく分かるけど、どのように実装したら良いかが分からない」といった状況になるのではないでしょうか。 私は多くのテックブログやgithub上にあるサンプルアプリケーションを参考にして以下のような構成にしました。

f:id:open8tech:20190310035102p:plain

以降ではこの構成を基に今回のトピックである「どのようにつまづいたり転んだりしたか」をみていきます。

参照と依存の向きによる違和感

クリーンアーキテクチャを勉強したら「実際に少し書いてみよう」となるでしょう。 しかし、実際に書くとなると何か参考になるソースコードが欲しくなると思います。 そんなとき、githubで公開されているサンプルアプリケーションが非常に役立ちます。

ビューコントローラとプレゼンター

では、まずエントリポイントとなるビューコントローラとプレゼンターを見ていきたいと思います。

// SomeViewController.swift
class SomeViewController: UIViewController {

    var presenter: SomePresenter?

    override func viewDidLoad() {
        super.viewDidLoad()
        presenter?.doByPresenter()
    }
}

extension SomeViewController: SomePresenterDelegate {

    func doByDelegate() {
    }
}
// SomePresenter.swift
protocol SomePresenter {

    func doByPresenter()
}

protocol SomePresenterDelegate: AnyObject {

    func doByDelegate()
}

class SomePresenterImpl: SomePresenter {

    weak var delegate: SomePresenterDelegate?

    func doByPresenter() {
    }
}

ビューコントローラおよびプレゼンターはお互いインターフェース(プロトコル)のみに依存して詳細を知らないようにします。 そしてDIコンテナにて以下のように依存性を注入すると思います。

let viewController = SomeViewController()
let presenter = SomePresenterImpl()
viewController.presenter = presenter
presenter.delegate = viewController

ここまではまだ違和感を抱かないで理解できるのではないでしょうか。 ちなみに、同じファイルにプロトコルとその実装を書くことで、 Xcodeでジャンプしても迷子にならずにすみます。 参照元が要求しているのはプロトコルなので、プロトコル定義にジャンプしてしまい、 実装まで直接ジャンプできなくなってしまうんですね。

ゲートウェイとレポジトリ

では、次にゲートウェイリポジトリを見ていきたいと思います。

// SomeGateway.swift
protocol SomeGateway {

    func doByGateway()
}

protocol SomeGatewayDelegate: AnyObject {

    func doByUseCase()
}

class SomeGatewayImpl: SomeGateway {

    private let repository: SomeRepository
    weak var delegate: SomeGatewayDelegate?

    init(repository: SomeRepository) {
        self.repository = repository
    }

    func doByGateway() {
    }
}
// SomeRepository.swift
protocol SomeRepository {

    func doByRepository()
}

protocol SomeRepositoryDelegate: AnyObject {

    func doByGateway()
}

class SomeRepositoryImpl: SomeRepository {

    weak var delegate: SomeRepositoryDelegate?

    func doByRepository() {
    }
}

この辺で「ん?ゲートウェイがレポジトリを持つ形になって良いのか・・・?」となりました。 先程の構成図に依存性の方向を入れた図を見てみたいと思います。

f:id:open8tech:20190311100910p:plain

レポジトリは最も円の外側であるDBやAPIなどの詳細が含まれている領域です。 それは正しいのですが、なぜゲートウェイがレポジトリを持つような形になってしまうのかが違和感でした。 ですが、それもそのはず。iOSでは基本的にビューコントローラが参照元となり、 プレゼンターやユースケースゲートウェイ、レポジトリの順に参照されているからです。 参照元と参照先の関係は以下の図のようになると思います。

f:id:open8tech:20190311100919p:plain

これは恐らく、ビューコントローラが破棄された際、 その画面を構成するインスタンスも同様に破棄されて欲しいためだと思います。 ですが、クリーンアーキテクチャの依存性の方向と参照の方向が異なるため、 このような違和感を抱くことになったんですね。

(もっと上手にやれば参照の方向なども自然な設計になったりするんでしょうか?)

ユースケースとはどのようなもので何を実装するか?

ユースケースとはどのようなものでしょうか? 本家のブログや書籍には「アプリケーション固有のビジネスルール」とありますが、 APIから取得したデータをビューに表示するだけのシンプルなアプリの場合、 恥ずかしながら何がユースケースに相当するのかがイマイチ想像できませんでした。

こんなとき頼りになるのがグーグル検索です。 そこで「ユースケース」と検索しますと、様々なユースケース図が出てきて気づきました。 iOSアプリケーションにおいては純粋にユーザーのアクションで良いのではないか?と。 例えば、皆さんが知ってるTwitterアプリなどの場合、以下のようになるかと思います。

f:id:open8tech:20190311121355p:plain

Twitterアプリケーションでなくとも、多くのアプリケーションにおいて 「お気に入り」や「再読み込み」、「追加読み込み」などの機能があると思います。 これらユーザーのアクションをユースケースとするのがiOSアプリケーションにとって 自然なのではないでしょうか。

(クリーンアーキテクチャの「ユースケース」にとらわれて広義での「ユースケース」がすっぽり抜け落ちてたのは内緒です)

エンティティとRxSwift

皆さんRxSwift使っていますでしょうか? タイトルに入れたくせにこれまで全く触れられてこなかったRxSwiftについてですが、個人的にはとても好きなライブラリです。 さて、クリーンアーキテクチャを用いた実装でRxSwiftをどのように使うかですが、意外とエンティティと相性が良いのではないでしょうか。 (ビュー層はこれまでと同様の使い方をすると思います。また必ずしもエンティティにしなければならないわけではないと思います)

例えば、テーブルビューやコレクションビューにて1つ1つのセルを構成するデータをSomeDataとして、 そのデータの配列を SomeDataList とした場合、以下のような実装になります。

// SomeData.swift
struct SomeData {

    let title: String
    let description: String
}

(以下の SomeDataList ではBehaviorRelayを用いていますのでRxCocoaのインポートが必要です。)

// SomeDataList.swift

import RxSwift
import RxCocoa

class SomeDataList {

    let list: BehaviorRelay<[SomeData]>

    var stream: Observable<[SomeData]> {
        return list.asObservable()
    }

    init(value: [SomeData] = []) {
        list = BehaviorRelay(value: value)
    }

    func set(value: [SomeData]) {
        list.accept(value)
    }

    func add(value: [SomeData]) {
        list.accept(list.value + value)
    }
}

このように Observable で観測可能な状態にしてユースケースからプレゼンターへ、 そしてプレゼンターで Driver にしてからビューコントローラへ渡していくことで ビュー層では観測するだけですむのではないかと思います。 詳細な部分は違うかもしれませんが、目的やイメージとしてはfluxに近いかもしれません。

またエンティティ(SomeDataList)が扱う[SomeData]ですが、これは最初の構成図におけるdataに相当します。 クリーンアーキテクチャでは「境界線を超えるデータは単純なデータ構造で構成されている」とあるので、 structで定義した単純なデータ構造の配列である[SomeData]は境界線を超えても良いのではないかと思いました。

最後に、最初の構成図でエンティティがユースケースをまたがっている部分についてですが、 同一のエンティティを異なるユースケースで使うパターンがあるかもしれない、と思ったからです。 ログイン・ログアウトのような場合はユースケースを再利用したら良いかもしれませんが、 上記のようなデータの再読み込みと追加読み込みなどは、ユーザーのアクションは異なりますが、 扱うエンティティは同じ方が都合が良いと思います。

ただ、データの再読み込みと追加読み込みに関しては、 ゲートウェイやレポジトリも同じ方が都合が良いため、 今のところ「ロード」という1つのユースケースに集約しています。 (もしかしたらそのようなエンティティは存在しない・・・!?)

試してみた感想

まだ直面していないので自信を持って言えないですが、 利点としてはやはり「仕様変更に強そう」ではないでしょうか。 ですが、サービスそのものが開発途上のiOSアプリケーションにおいては、 中心のドメインの仕様変更も少なくないのが少々怖いところです。

逆に欠点ですが、やはり「ファイル数が多い」と「理解が難しい」です。 「理解が難しい」は勉強しろと言われればそれまでかもしれませんが、 チーム開発を行う上では全員に理解してもらわないといけないので 勉強会を行うなどしないといけないと思います。

まとめ

いかがでしたでしょうか? 正直、まだまだ実装している最中なので何か不都合が出てこないか、 そもそも自分のクリーンアーキテクチャの理解が間違っていないか毎日ドキドキしています。 また、今回お見せした例は「こうあるべきだ」とか「こうしないといけない」というものでもないです。 ですが、クリーンアーキテクチャを勉強を通して「こうしたらもっと仕様の変更に強くなりそうだ」というのが 以前より多くなったと思いますので、(プロダクトに導入するかはともかく)一度本家のブログだけでも 読んでみてはいかがでしょうか。

reduxのstate設計についてスタートアップテックで話しました

こんにちは、オープンエイトでフロントエンドエンジニアをしている澤木です。 最近お腹の調子が良くないので朝にヨーグルトを食べるようにしたのですがかなりの改善を感じています。皆さんもヨーグルト食べましょう。

ところで弊社オープンエイトですが、昨年末からスタートアップテックと題してスタートアップ企業合同で様々話題をテーマに LT 大会を開催しております。 今回はその第2回目、スタートアップフロントエンドということで私も LT に参加させていただきました! ということでその時の発表内容についてブログでも紹介させていただければなと思います。

f:id:open8tech:20190214154427j:plain

発表内容

今回は「redux の state 設計の話」と題して、redux の state 設計の話をしてきました。まんまですね。 弊社では多くのプロジェクトで React が使われているのですが、中でも私の担当する VIDEO BRAIN では react+redux の SPA で開発を行っています。 その時に state 設計にかなり苦戦しましたので、どういう経緯で作っていったか、現在の設計はどうなっているか等についてお話しさせていただきます。

redux の state 設計

まず redux の state 設計についてですが、redux では state は原則として一つのツリーとして一箇所で管理されます。(Single source of truth) もちろん一枚フラットな state にするのは辛すぎるので、そこからどうやってツリーを切っていくかが state 設計の肝となります。

画面ベースでの設計

VIDEO BRAIN では最初 state を切る際に画面ごとに切るという方法を取っていました。 例えば編集画面、作成画面などがあった場合に編集画面用の state、作成画面用の state といった用に画面と1:1で state を切っていくようなやり方です。 ざっくり図を作るとこんな感じ。

f:id:open8tech:20190208183137p:plain

このような形で切っていくと画面数が少ないうちは良かったのですが、画面数が多くなってきた時にその数分 state を切らなければならない、画面に変更があった場合に state を作り直さなければならない、といった問題が出てきました。(特に VIDEO BRAIN では画面の変更が多かったためかなり辛かったです…) そこで、画面ベースでの切り方はやめて、ドメインベースで state を切っていくやり方に移行することにしました。

ドメインベースでの設計

こちらのやり方では state を画面から切り離して、user だったり projects だったりドメインで state を切っていく形になります。 ざっくり図を作るとこんな感じ。

f:id:open8tech:20190208183131p:plain

このような設計にすると、画面と state を分離することができるため、画面側に変更があった際にも state を作り直す必要がなく、ロジックの共通化も行いやすくなります。 実際には下のような形で state を切っていきました。

state
  ├─ entities // APIからフェッチしてきたデータを正規化して保持
  ├── 各ドメインのstate
  │   ├── lists // 各ドメインのリストデータを保持
  │   └── edits // 各ドメインの編集データを保持
  └── ui // グローバルなUIの表示状態を保持

entities

こちらの state では API から取得したデータを一括で保持するようにしています。 API から取得したデータの構造は呼び出し場所ごとに異なっており、また各ドメインの情報がネストして含まれていたりしています。 そういった場合にそれらを違う state で保持しているとデータをフェッチしてきた際に、各 state ごとに更新作業を行わなければならず操作が複雑になってしまいます。またデータがネストしている場合オブジェクトをたどっての変更が難しいという問題も出てきます。 データを正規化することでデータの構造がフラットになり、各ドメインごとのデータを同じ形式でまとめることができるようになります。

例えば projects とそれにひもづく scnens をもつオブジェクトをフェッチしてきたとします。この場合にデータの正規化を行うと下のようになり、projects と scenes をフラットな状態にすることができます。

正規化前のオブジェクト

{
  id: 1,
  title: "project1",
  scenes: [
    {
      id: 1,
      name: "scene1",
    },
    {
      id: 2,
      name: "scene2"
    }
  ]
}

正規化後のオブジェクト

entities: {
  projects: {
    1: {
      id: 1,
      title: "project1",
      scenes: [1, 2]
    }
  },
  scenes: {
    1: {
      id: 1,
      name: "scene1"
  },
    2: {
      id: 2,
      name: "scene2"
    }
  }
}

ドメインの state

こちらの state では各ドメインのデータを保持しています。この中でまた state をネストさせて一覧や編集状態の管理用の state を作成しています。 各 state では API からのフェッチしてきたデータは直接持たず、entities のデータを参照するようにしています。こうすることで、entities を変更すれば全ての場所で自動的に表示が更新されるようになり更新作業が楽になりました。 lists と edits の構造は下のような形にしました。

lists

lists: {
  [key]: {
    ids: [1, 2, 3],
    loading: false
  }
}

edits

edits: {
  [id]: {
    name: hugahuga,
    ...
  }
}

ui

こちらの state ではモーダルなどグローバルな UI データを保持しています。各ビューごとの UI の状態はできるだけコンポーネント側で管理するようにして、redux 側での UI の状態保持は最小限にとどめています。

まとめ

画面ベースでの state 設計からドメインベースでの state 設計に切り替えたことで、ビューに変更があった際も state を書き変えずに最小限の変更で対応できるようになり、ある程度苦労を減らせたと思います笑 ただビュー側に固有の処理をどうするかなど、画面ごとの設計では気にすることのなかった問題も出てきたので、そこらへんに関しても綺麗な書き方を模索していければなと思います。(redux 難しい…)

styled-componentsのスタイル拡張について

2018年度に新卒で入社した東度です。配属当初はRailsでサーバーサイドを書いていたのですが、最近はReactでフロントを書いています。

自社プロダクトの一つであるVIDEO BRAINでは、CSS in JSのライブラリの一つであるstyled-componentsを使ってスタイリングをしているのですが、中でも度々登場するスタイル拡張について自身の勉強も兼ねて記事をまとめてみました。

styled-componentsとは

現在、CSS in JSの中で最も人気のあるライブラリで、要素にスタイルを付加したコンポーネントが作成できるというのが特徴です。

styled.div``のように記述すると、div要素にタグ付きテンプテートリテラル内のスタイルを付加したコンポーネントが返される仕組みとなっています。

以下の例では、button要素にスタイルを当てたButtonコンポーネントを定義しています。 定義したButtonコンポーネントを呼び出すと以下のボタンが出力されます。

// Button.js
import styled from 'styled-components';

export const Button = styled.button`
  margin: 1em;
  padding: 0.25em 1em;
  border: none;
  outline: none;
  border-radius: 3px;
  color: #fff;
  background-color: #404143;
`;

Image from Gyazo

スタイル拡張について

styledされたコンポーネントに対してstyled()コンストラクタでラップすると、スタイルを拡張した新しいコンポーネントを作成することができます。

例えばButtonコンポーネントの場合、色やサイズなどを調整して新しいコンポーネントを作成したい場合などがあるかと思います。以下の例ではButtonコンポーネントを継承し、スタイルを拡張した新しいボタン作成しています。

// Button.js
import styled from 'styled-components';

export const Button = styled.button`
  margin: 1em;
  padding: 0.25em 1em;
  border: none;
  outline: none;
  border-radius: 3px;
  color: #fff;
  background-color: #404143;
`;

export const RedButton = styled(Button)`
  background-color: #ff0000;
`;

export const GreenButton = styled(Button)`
  background-color: #00ff00;
`

export const BlueButton = styled(Button)`
  background-color: #0000ff;
`

Image from Gyazo

次に、styledされていないコンポーネントに対してスタイルを拡張する方法を紹介します。

styled-componentsでは、classNameに指定したスタイルを渡すことでスタイルを適用しています。 styledされていないコンポーネントに対しては、以下のように、propsで渡されたclassNameをコンポーネントのDOM要素に適用することで、スタイル拡張が行えるようになります。

// Hello.js
import React from 'react';
import styled from 'styled-components';

export function Hello({className, children}) {
  return(
    <a className={className}>
      {children}
    </a>
  );
}
export const StyledHello = styled(Hello)`
  color: #7F9DB5;
  font-size: 30px;
  font-weight: bold;
`; 
// App.js
import React, { Component } from 'react';
import { Hello, StyledHello } from './Hello.js'

class App extends Component {
  render() {
    return (
      <div>
        <Hello>Hello</Hello>
        <br />
        <StyledHello>Hello</StyledHello>
      </div>
    );
  }
}

export default App;

Image from Gyazo

まとめ

今回はstyled-componentsを使ったスタイル拡張について記事をまとめました。今後React等に触れていく中で、得られた知見などを共有できたらと思います。

最後に、告知になるのですが1月29日(火)に「スタートアップテック vol.2:スタートアップとフロントエンド」が開催されます。 弊社からも澤木(@ayatas0623)が「reduxのstate設計の話」について発表します。彼の勇姿を是非ご観覧ください!

イベントの詳細については下記のリンクからご確認ください。

connpass.com

「スタートアップテック vol.1」を開催しました!

https://connpass-tokyo.s3.amazonaws.com/thumbs/87/36/87360719e01f4b0d089645f47e2f7d45.png

こんにちは、インフラ・データ基盤部の川島です。最近寒くなってきましたね。今年も終わりますね。心はすでに年末休みです。

先日、エンジニア交流イベント「スタートアップテック vol.1」を開催しました。

今回のテーマは、みんなが大好きな「Ruby」です。弊社のプロダクトもほとんど全てと言ってもいいくらいRubyを使っています。 主催枠として、私もLTを行ったので、発表内容を紹介できればと思います。

発表内容

LTのテーマは、「Rubyffmpegのfilter_complex」について発表しました。オープンエイトのプロダクト全てが動画をベースに展開しているため、Rubyと同じく、全てのプロダクトでffmpegを使っています。最近のプロジェクトの中でのffmpegを活用した実装事例について紹介しました。

ffmpeg は動画や音声に対して、非常に多くのことができる優秀なツールです。基本的にコマンドラインで操作を行うため、多くのオプションを設定しなければいけません。

下記のコマンドが実際に使用したものになります。

ffmpeg -y -r 15 \
-i ./image/%d.jpg -i 01.mp3 -i 02.mp3 \ 
-filter_complex "[0:v]fps=fps=15[img];[1:a]atrim=duration=20.0,afade=type=out:start_time=19.0:duration=1.0,asetpts=PTS-STARTPTS[OA1];
[OA1]amerge=inputs=1[a]" \
-map [img] -map [a] -s 640x360 -crf 30 -movflags faststart -vcodec libx264 -pix_fmt yuv420p -q:a 0 -strict -2 \
output.mp4

プロジェクトの中では、このコマンドを Ruby で生成しています。 LTの中では、複数あるオプションの中でも、 filter_complex 部分に焦点を絞って紹介しました。

filter_complexは大きく3つの構成に分類することができます。

  • filter
  • filter_chain
  • filter_graph
fps=fps=15 # filter
[0:v]fps=fps=15[img] # filter_chain
"[0:v]fps=fps=15[img];...." # filter_grpah

filter_graph[filter_chian[filter]] という形でそれぞれが内包されているイメージです。

コードで実装する場合にも、この構成を元にクラス定義していきます。

filter class
filter_chain class ( N filters )
filter_graph class ( N filter_chains ( N filters ))

対象のディレクトリの構成としては下記になります。

- filter_complex  
│
└──-filter
│   │   xx_filter.rb 
│   
└───filter_chain
│   │   xx_chain.rb
│   
└───filter_graph
    │   xx_graph.rb

名前空間、filter毎のクラスで分けることによって、それぞれのfilterの責務を明確にすることができます。また、追加したいfilterがあったとしても、filter, filter_chain, filter_graph をセットで追加することで、容易に作成ができます。

まとめ

ffmpegは、本当にたくさんのことができるツールです。この記事でffmpeg、特にfilter_complex に興味を持っていただけるとうれしいです。

次回のイベント告知

1/29(火)にも、弊社主催のLT大会を行なっていきます。次回のテーマは「フロント」です。 また、「一緒に勉強会を行いたい!」などのご要望がありましたら、ぜひご連絡(@hisatake)をお待ちしております!

おまけ

コードなどの内容は下記のスライドに掲載してあります。

www.slideshare.net

技術書典にサークル参加してきました

こんにちは。初めまして。 OPEN8の大津( @14__oz )です。

技術ブログを始めることになりました!! 編集長に抜擢され、初回の内容を任されています。 頑張っていきますのでよろしくお願いします!

OPEN8には2017年新卒エンジニアとして入社し、ルトロンのアンドロイドアプリを初期開発からやってきました。 ReactNativeを使っています。

詳しくは、Wantedlyインタビュー記事があるので読んでみてください。 www.wantedly.com

早速、初回のテーマですが、「技術書典5」に出展したときの話をします! 新機能の開発が忙しいなか、時間を作って書き上げた技術書を頒布してきました。 内容は、ReactNativeのアニメーションについて書いています。 今更ですが、振り返っていきます(笑)。

技術書典

技術書典とは、技術書オンリーイベントです。 技術者のためのコミケをイメージしてもらえると良さそうです。 出展者が普段から使っている・興味のある技術のノウハウをギュッと技術書に詰め込んでいて、とても読み応えがあります。 かなり幅の広いジャンルが揃っていて、内容も初学者に向けたものから、ニッチなものまで様々です。 どの技術書も販売されているものに劣らない内容となっています。

もともと興味があったなか、CTOの石橋( @hisatake )からの後押しでチャレンジしてみることになり、 10/8(月)に池袋サンシャインシティにて開催された技術書典5に出展してきました。

当日は、およそ10,000人も来場されたそうです! 前回の来場者数が、およそ6,000人で、技術書典の規模がどんどん拡大していますね。 今後も楽しみです!

初めてのサークル参加

技術書典5に無事当選はしたものの、当時は、内容さえ決まって書き始めれば何とかなるだろうという見切り発進をしていました。

  • 即売会にサークル参加する
  • 技術書を書く
  • 書籍を作る

執筆や書籍を作ろうとした事もないのに、余裕をこいていたのはどうしてなんでしょう・・・。

後々に大変痛い目をみる羽目に・・・。

技術書の内容

頒布した技術書の内容は、

  • 業務ではAnimatedを使う機会がほぼなかった事
  • 新卒当時は難しくて断念していたアニメーションにリベンジしたかった
  • 実際に動かして、理解したかった

と言った理由から、ReactNativeのAnimatedクラス・コンポーネントをテーマとして選んでみました。

技術書を書くにあたり、ReactNativeでパズルアプリを作りました。 アプリ内でAnimatedを用いた部分のコードを載せて解説しています。 Animatedとスクロールの連携やinterpolateを用いた例を書いています。

Easingの使い方や、PanResponderを用いたフリックの取得も書いています。 知らないことが多かったので、ReactNative本体のソースコードを読んで理解しことや、 AnimationLayoutなど、一通りアニメーションに必要なものを含んだ内容になっています。

書籍の最後には、およそ1年ReactNativeを使ってきて、印象的な出来事を中心にトピックとして残しておくことにしました。

当日の様子

開場1時間前には、列ができていました。 この時点で早くも自分のテンションが上がり始めます。

緑色の服を来た運営の方たちに出迎えてもらい、自分のブースへと向かいます。 ブースに作った技術書が直接届いていたので荷物整理をしていました。

一息ついてからの、開封の儀。

そして、ブースの設営をしました。 必要そうなものの大半は前日・前々日に100均に駆け込んで買い揃えました。 書籍の内容がReactNativeだったのでFacebookの服を着て待機。

始まるまでに時間が少しばかり余ったので、顔見知り方のブースに挨拶に行ったり、 となりのブースの方と話していました。 なんだかんだ、お隣の方とは1日中話していました。

始まってすぐに3名の方がブースに来てくれたのは、かなり嬉しかったです。 そのあとは、入場規制の関係で人の波が一定間隔で押し寄せるといった感じでした。 ブースに来て見本誌を読んでくれる方がたくさんいて、読まれているときの緊張感は計り知れないです。 じっと観察されているような気分でした。 見本誌を見て買っていただけた時は嬉しくて顔に出ていたかもしれないですね。 同僚や知り合いなど、たくさんの方にブースへ来てもらえたのでありがたかったです。

最終的には、50部ほど頒布できました。 ただ、今だから思うと、調子に乗って100部刷ったのは完全にミスですね。 余ってしまったので、今でも家に眠っています。 また、機会があれば頒布しようと思います。

失敗したこと

失敗したことはたくさんあって、

  • 部数を刷りすぎた
  • 表紙・裏表紙の入稿データの形式が違っていた
  • PDFの用紙サイズが間違っていた
  • 書く時間をほとんど取れなかった

などなど、出し始めるとキリがなさそうです(笑)。

見切り発進した結果、ギリギリまで入稿方法について調べずにいました。 いざ、入稿するぞってときにノンブルがない、PDFの用紙サイズが違うなど、かなり焦りました。 表紙は塗り足しがなくて作り直しと、PDF同様にダメな点がありました。 事前確認を怠り、行き当たりばったりで良くなかったですが、ノウハウを得たので次は活かせられそうです。

一番キツかったのは、書く時間を取れなかったことです。 時間があまりにもなくて最後までずっと終わらないのではないかと内心思い、 まるで、締め切りに迫られた作家のようでした。 また、時間を置いてから内容を読み直して修正する時間もほとんど取れず、 完成度が下がってしまったのは悔やまれます。

技術書典を終えて

総合的にはかなり満足しています。 執筆に当たっては失敗しことも多いですが、やって良かったと思えたからですね。

実際に技術書を出そうとすると、 かなりのインプットがいることが身に染みました。 今回の執筆では体感で2倍くらいのインプットが必要でした。 業務でReactNative本体のソースコードを読むことはほとんどないので、いい機会だったと思います。 次回もまた出展したいとは思います!内容が決まればですが・・・。

技術書典では、参加者としてもたくさんの技術書を買いました。 手当たりしだい買っていたので、むしろ買いすぎた気がしています。 今でも出社前に読みふけっています。

おわりに

ここまで読んでいただきありがとうございました。

今後は、弊社の個性豊かなメンバーが更新していきます。 もちろん、僕も何度か登場することになります。 楽しみにしていてください!!

最後に告知があります!!

Ruby LT大会

11/29(木)に「スタートアップテック vol.1: Ruby LT大会」が開催されます。 スタートアップテックとは5社合同で開催するエンジニア交流会です。 初回はRubyに関するLT大会です。

OPEN8からは、インフラエンジニアとして活躍する川島が登壇します。 発表の内容は、OPEN8のコアテクノロジーにも関わってくる動画処理についてです。

connpass.com

参加枠は多めにとってあり、現在も枠は空いています。 Rubyに興味がある、これから始める予定でLTだけでも聞いてみたい方など、 ぜひご参加ください。

今後、様々なテーマで開催していきます。