ごんれのラボ

iOS、Android、Adobe系ソフトの自動化スクリプトのことを書き連ねています。

InDesignでMacにインストールされたフォントのフォント見本をほぼ自動で作りたいというSOSを、ExtendScriptで解決のお手伝いをした

概要

お世話になっている方がTwitterでSOSを出されていたので、ExtendScriptで解決のお手伝いをした。

仕様

  • InDesign上のすべてのテキストフレーム内のテキストにMacにインストールされたフォントを適用して、PDFとJPEGを書き出す
    • PDFとJPEGはフォント名で書き出される
  • 実行時に表示されるダイアログに入力された文字列をキーに、フォント名で絞り込みする
    • 正規表現で検索できる
    • なにも入力しない場合はフォント名での絞り込みは行われない
  • PDFに埋め込めないフォントは除外する
  • 以下の形式のフォントは除外する
    • OCF
    • Type1
    • TrueType
  • 欧文フォントと和文フォントの種別判断を行っていないので、日本語に欧文フォントを適用するとアラートが表示される
    • InDesignの設定で無視することを想定しているが、実行後に設定をもとに戻すことを強く推奨する

使い方

  1. InDesignドキュメントにテキストフレームを作成して、テキストを入力する
  2. スクリプトを実行する
  3. 表示されたダイアログで検索したいフォント名の一部分を入力(なにも入力しなくもていい)してOKをクリック
  4. 保存場所を聞かれるので、選択する。デスクトップを選択するとファイルで埋め尽くされるので、フォルダを作成することを強く推奨
  5. 処理が完了すると4のフォルダ内にPDFとJPEGが作成されている

動かしてみるとこんな感じ。

output

ソースコード

まとめ

喜んでいただいてよかった!

Adobe XDのアートボードをPNGに書き出すPluginを作った

概要

2018年10月よりAdobe XDのPlugin開発が誰でもできるようになった。
そこで、公式のサンプルを読み解きつつ、ドキュメント内のアートボードをPNGに書き出すPluginを作ってみた。

仕様

  • 用途に応じて、メニューから「選択しているアートボードを書き出す」「すべてのアートボードを書き出す」を選べる
  • 書き出しサイズは以下のサイズから選べる
    • 0.5x(50%)
    • 1x(100%)
    • 1.5x(150%)
    • 2x(200%)
    • 3x(300%)
    • 4x(400%)
    • 5x(500%)
  • 書き出したPNGはダイアログで選択したフォルダ内に 20181126101110 というような名前のフォルダを作成し、その中に格納される
    • 実行後に表示するアラートに保存先が表示される
  • PNGはアートボード名で書き出される

使い方

output

インストール方法

  1. こちらからxdxファイルをダウンロード
  2. ダウンロードしたxdxファイルをダブルクリック
  3. Pluginをインストールするか確認する旨のダイアログが表示されるので、インストールを選択
  4. インストール完了した旨が表示される
  5. メニュー>プラグイン に「export-artboards-to-png」が表示され、利用可能になる

アンインストール方法

  1. メニュー>プラグイン から「プラグインを管理...」を選択
  2. サイドバーから「インストールされたプラグイン」を選択
  3. 「export-artboards-to-png」にマウスカーソルを合わせると、名前の右側に「…」が表示されるので、クリック
  4. アンインストールを選択
  5. Pluginがアンインストールされる

困ったこと

ドキュメント上のすべてのNodeを取得する方法がわからない

コマンドに渡される第二引数の documentRoot がドキュメント上のすべてのNodeだった。

ドキュメントより抜粋。

Typically, you access scenegraph nodes via the selection argument that is passed to your plugin command, or by traversing the entire document tree using the documentRoot argument that is passed to your plugin command.

option タグで selected をサポートしていない

ダイアログ表示時にデフォルトで書き出しサイズを設定しておきたかったんだけど、ドキュメントにサポートしていない旨書いてあって諦めた。
他に方法があるかもしれないけど…。 ドキュメントはこちら

ソースコード

GitHubで公開しているので、詳しくはそちらを参照してほしい。
export-artboards-to-png

main.js だけ載せておく。

const application = require('application');
const fs = require('uxp').storage.localFileSystem;
const { Artboard } = require('scenegraph');
const {alert, confirm, prompt, error, warning} = require("./lib/dialogs.js");

let selectedRatio;

async function exportSelectedArtboards(selection, root) {
    let nodes = selection.items.filter(node => node instanceof Artboard);
    if (nodes.length == 0) {
        error('エラー', 'アートボードを1つ以上選択して実行ください');
        return;
    } else {
        exportArtboards(nodes);
    }
}

async function exportAllArtboards(selection, root) {
    let nodes = root.children.filter(node => node instanceof Artboard);
    if (nodes.length == 0) {
        error('エラー', 'アートボードが存在しません');
        return;
    } else {
        exportArtboards(nodes);
    }
}

async function exportArtboards(nodes) {
    const outputFilePaths = await exportNodes(nodes);
    if (undefined == outputFilePaths) {
        return;
    }
    const joinedFilePath = outputFilePaths.join('\n');
    alert('処理が完了しました', `書き出したPNGファイルは下記に格納されています\n\n${joinedFilePath}`);
}

async function exportNodes(nodes) {
    const dialog = await makeSelectScaleDialog();
    await dialog.showModal();
    dialog.remove();

    if (selectedRatio.selectedIndex < 0) {
        return;
    }

    const excutedTimeStr = getNowYMDHMS();
    const selectedFolder = await fs.getFolder();
    if (null == selectedFolder) {
        return undefined;
    }
    const folder = await selectedFolder.createFolder(excutedTimeStr);

    let renditions = await makeRenditionOptions(nodes, folder);
    application.createRenditions(renditions)
        .then(results => {
    })
    .catch(error => {
        console.log(error);
    })

    // 書き出したファイルのパスを配列に格納
    const outputFilePaths = renditions.map(rendition => {
        return rendition.outputFile.nativePath;
    });

    return outputFilePaths;
}

async function makeRenditionOptions(nodes, folder) {
    let renditions = [];
    await Promise.all(nodes.map(async (node, i) => {
        const file = await folder.createFile(node.name + '.png', {overwrite: true});
        renditions.push({
            node: node,
            outputFile: file,
            type: 'png',
            scale: selectedRatio.options[Math.max(0, selectedRatio.selectedIndex)].value
        });
    }));
    return renditions;
}

function getNowYMDHMS() {
    const dt = new Date();
    const y = dt.getFullYear();
    const m = ('00' + (dt.getMonth()+1)).slice(-2);
    const d = ('00' + dt.getDate()).slice(-2);
    const h = ('00' + dt.getHours()).slice(-2);
    const mm = ('00' + dt.getMinutes()).slice(-2);
    const s = ('00' + dt.getSeconds()).slice(-2);
    const result = y + m + d + h + mm + s;
    return result;
}

function makeSelectScaleDialog() {
    const labelWidth = 75;

    const dialog =
        h("dialog",
          h("form", { method:"dialog", style: { width: 380 }},
            h("h1", "Select the export scale"),
            h("label", { class: "row" },
              h("span", { style: { width: labelWidth } }, "Scale"),
              selectedRatio = h("select", {  },
                                h("option", { selected: true, value: 0.5 }, "0.5x"),
                                h("option", { value: 1 }, "1x"),
                                h("option", { value: 1.5 }, "1.5x"),
                                h("option", { value: 2 }, "2x"),
                                h("option", { value: 3 }, "3x"),
                                h("option", { value: 4 }, "4x"),
                                h("option", { value: 5 }, "5x")
              )
            ),
            h("footer",
              h("button", { uxpVariant: "primary", onclick(e) { selectedRatio.selectedIndex = -1; dialog.close(); } }, "Cancel"),
              h("button", { uxpVariant: "cta", type: "submit", onclick(e){ dialog.close(); e.preventDefault; } }, "OK")
            )
          )
        )
    document.body.appendChild(dialog);
    return dialog;
}

/**
* Shorthand for creating Elements.
* @param {*} tag The tag name of the element.
* @param {*} [props] Optional props.
* @param {*} children Child elements or strings
*/
function h(tag, props, ...children) {
    let element = document.createElement(tag);
    if (props) {
        if (props.nodeType || typeof props !== "object") {
            children.unshift(props);
        }
        else {
            for (let name in props) {
                let value = props[name];
                if (name == "style") {
                    Object.assign(element.style, value);
                }
                else {
                    element.setAttribute(name, value);
                    element[name] = value;
                }
            }
        }
    }
    for (let child of children) {
        element.appendChild(typeof child === "object" ? child : document.createTextNode(child));
    }
    return element;
}

module.exports = {
    commands: {
        exportSelectedArtboards,
        exportAllArtboards
    }
};

次はなに作るの?

なにかしら通信が発生するものを作りたい。

感想

ES6で書けるの、最高。
InDesignのCEPもES6に対応してくれ!
頼む!!!!!!!!!

参考

公式ドキュメント
はじめてのAdobe XDプラグイン開発!定番のHello Worldを表示させてみよう

FILCO Majestouch MINILA Air US67 Bluetoothキーボードを買いました

良さげなキーボードがほしいと思い続けて幾星霜。
ついに買いました。

購入候補

候補は絞れていて、下記の3機種のどれにしようかと悩んでいました。

購入したもの

REALFORCEもHHKBもとても良いという話を聞いていたんですが、良さげなキーボードを買うのが初めてという状態なので、お手頃価格の FILCO Majestouch MINILA Air US67キー 茶軸 にしました。

ヨドバシ・ドット・コムで購入したら、10時間後に届いてびっくりした。

開封の儀を執り行った

飼い猫レノくんに避けられながら開封の儀を執り行った。

外箱はがっしりしてた。
重量感があってかなりずっしり。

f:id:macneko-ayu:20180924205248j:plain
外箱

思っていたよりコンパクトだけど、高さはそこそこある。
持ち上げてみて「重っ!」っていうぐらいずっしり。持ち運びには向かなそうだ。 キータッチは軽く押しただけで入力ができて、ほどよいカチカチ音で満足。
奥さんからは「やかましいな」とちょっと不評だったけど、負けないぞ。
でも自宅用には赤軸でもいいかも(早速ヒヨる)

f:id:macneko-ayu:20180924205243j:plain
本体

Macbook Proの上に載せてみた。
写真だとキーボードのほうが幅があるように見えるけど、実際はぴったりか少し小さいくらい。

f:id:macneko-ayu:20180924205238j:plain
幅はMacbook Proとほぼ同じくらい

カスタマイズ

DIPスイッチでカスタマイズが可能なんだけど、使ってみた感じでは私は初期状態のままで良さそう。
ただ、WIN キー(Macだと Command)と Alt キー(Macだと Option)の位置が標準キーボードと逆になっているので、そこだけ設定を変えた。
システム環境設定からキーボード設定に遷移して、修飾キー... ボタンをクリックすると、修飾キーの設定を変更するダイアログが表示される。
そのダイアログで CommandOption を入れ替えれば設定完了。

f:id:macneko-ayu:20180924214115p:plain
変更前

f:id:macneko-ayu:20180924214119p:plain
変更後

あと上記の設定変更にあわせて、キートップも入れ替えました。
専用の器具が付属してるので、自他ともに認める不器用の私でも一人でできた!

f:id:macneko-ayu:20180924205233j:plain
購入時のキー配置

f:id:macneko-ayu:20180924205228j:plain
入れ替え後のキー配置

気に入ったところ

少ししか触っていないけど、気に入ったところ。

  • キートップ交換用の器具がついてくる
  • Fnキーがスペースキーの左右にあるので、使いやすい
    • Macbook ProのFnキーはUSキーボードだと左下で押しづらいんだよ…
  • Fnキーとのコンビネーションが便利
    • 矢印キーの代わりになるので、キーボードキー押さなくてよい
    • PageUp、PageDown、Deleteが使えるので便利
  • キータッチがペタペタしてないので良い
    • 入力音が気になると指摘されたけど、Macbook Proのキーボードでも結構うるさいよね

まとめ

良い買い物をした気がする!

iOSでチラシっぽい価格レイアウトを再現してみた

概要

TwitterでフォロワーさんがUIStackViewで挑戦してたのを見かけた。

スレッドを遡ってみると、NSAttributedStringで実装できるんじゃないかという話があり、興味が湧いたので挑戦してみた。

作ったもの

文字のサイズ感は目見当。

chirashi.png

gist.github.com

説明

ソースコードを部分的に切り出して処理内容を説明する。

let fontSize: CGFloat = 80
let font = UIFont.systemFont(ofSize: fontSize)
let attributeText = NSMutableAttributedString(string: "各種¥(税込)280",
                                              attributes: [.font: font, .foregroundColor: UIColor.red])

はじめに attributeText に基本的な装飾と文字列を格納しておいて、装飾を変更したい部分をNSRangeで指定して、加工していく方法をとることにした。

// 各種
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.4),
                             .baselineOffset: 2],
                            range: NSRange(location: 0, length: 2))

各種 の部分。
文字サイズは基本サイズの40%の大きさを指定。
や数字よりベースラインが少し下にずれて見えるので、.baselineOffset: 2 を指定して少し上にずらした。
ベースラインについては ラテン文字と欧文組版 をP14の図を参照。
雑に説明すると、.baselineOffset に正の数を与えると上に移動し、負の数を与えると下に移動する。

// ¥
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.6),
                             .kern: -50],
                            range: NSRange(location: 2, length: 1))

の部分。
文字サイズは基本サイズの60%の大きさを指定。
.kern: -50 を指定して、次の文字の ( との字間を詰めた。
雑に説明すると、.kern (カーニング)は当該文字と次の文字の文字間のアキを詰める設定。
なお、パーレンにはカーニングが適用されないっぽかったので、を前にもってきてカーニング設定をしている。

// (税込)
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.2),
                             .baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 4],
                            range: NSRange(location: 3, length: 4))

(税込) の部分。
文字サイズは基本サイズの20%の大きさを指定。
ベースラインは相対値で計算したものの、それだけではうまく揃わなかったので、微調整している。

// ()のベースライン調整
attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                            range: NSRange(location: 3, length: 1))
attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                            range: NSRange(location: 6, length: 1))

() の部分。
ベースラインが揃わなかったので、この部分だけさらに微調整した。

文字列ごとにNSAttributedStringKeyを指定していき、最後に結合する方法でも良かったんだけど、DTP的な手法のほうが手慣れているため、この方法にしてしまったがゆえに、すごくIllustratorやInDesignを触っている気分になった。

まとめ

参考

Mastering TextKit

iOSDC 2018 2日目に参加してきた

概要

iOSDC2日目に参加したので、そのまとめ。
参加したセッションまとめと、感想を記しておく。

セッションまとめと感想

登壇者が話したことと感想とが混じっているので、雰囲気で察してくれることを祈る

詳解Fastfile by ぎぎにゃん

  • 資料
  • fastfileの詳細について話すよ
  • fastlineの活用事例
    • コードレビュー
      • Danger用に自社で作ったスペルチェックツール、いいな
    • サブミット
      • CIでリリースビルドしてサブミット
      • SlackBOTからサブミット
      • 定期的にmasterをビルドしてサブミット
        • 強いな
    • 社内向けビルド
      • エンタープライズライセンスでビルドして配信サービスで社内配布
      • PRごとに配布
      • 社内向け配信サービスは16時から話すよ
    • メトリクス収集
  • ありがちなこと
    • なんでもfastfileに書きがち
  • メンテしやすい最高のfastfileの書き方
    • Fastfile
      • 基本的にはRuby
  • import
    • 複数のfastfileを読み込んで実行できる
  • GitHubでシンタックスハイライト
    • 一行目に #vim: syntax=ruby って書くといいよ
  • 公式のAdvanced Featureを読む
  • いろいろ書きやすいがゆえに肥大化する
  • 最高のFastfileとは
    • 書かない
    • コードを書くところではないので、書くものを減らす
  • コツ
    • 値を書きすぎない
      • 環境変数を利用する
    • 設定とロジックを分離する
      • ~fileを利用する
        • Gymfileなど
    • Actionを分離する
      • テンプレートを作るコマンド bundle exrc fastlane new_action があるので、それを利用して作成するとよい
      • パラメータのバリデーションがしやすい
        • 型チェック
      • テストが書きやすい(RSpec)
  • コードサイン
    • AutomaticはCIでこけやすい。理由はわからない
      • よく聞く話だー
    • matchはGitで管理しているプロファイルをいい感じに取得する…らしい
    • 正しい世界観はXcodeのコンフィグレーションを使うのがよいのではないか
      • Xcode9からAutomaticとManualが同居できるようになった
  • 最高の設定
  • fastlaneあるある
    • 手元での確認がだるい
  • デバッガを使う
    • Rubyのデバッガ
      • pry
    • .envrc
    • envchain
    • direnv

Depth in Depth

  • 資料
  • Depth
    • 深度
  • 深度の用途:背景を飛ばす
    • フリマ系アプリで出品時に背景を飛ばすなどの用途がある
  • 深度の用途:3Dスキャン
  • 深度の用途:その他
    • ZOZOスーツの「30センチ後ろにさがってください」などの検知に使っていそう
  • 深度は発想次第で写真以外にも用途がいろいろある!
  • Disparity(視差)
    • 人間の左右の目で見えるものが違う
    • iPhone7以降の背面カメラで利用
  • DepthはDisparityから計算できる
    • Depthの逆数=正規化されたDisparity
  • Time of Flight
    • iPhoneXの前面カメラ
  • iOSで取得する方法
    • AVDepthData
      • 深度を表すクラス
      • どの方法で取得しても最終的にこれが得られる
      • iOS11以上
      • var depthDataMap: CVPixcelData
    • 用途別にわけると3種類
      • 撮影済の写真
      • カメラからリアルタイムに取得
        • AVCaptureDevice
      • ARKitから取得
        • ARFrameにプロパティがある
  • 方法に優劣はなく、用途に応じたものを使う
  • 背景合成の手法
    • マスク画像を基準に、オリジナル画像と背景画像をブレンドする
    • CIBlendWithMask
  • 顔の深度をしきい値に、深度マップを2値化する
  • PotraitMatte
  • どういうケースで、なにができてなにができないのか把握しづらい

5000行のUITableViewを差分更新する

  • 資料
  • UITableViewで差分更新、パフォーマンスの話
  • UITableViewで差分更新する
    • 特徴
      • 行数がたくさんあっても早い
    • 更新方法
      • 全部更新
        • アニメーションなしだが、簡単に使える
      • 差分更新
  • 差分更新をどう実現するか
    • 差分のIndexPathを正確に指定するだけ
    • diffを使おう
  • diffとpatch applyをしている
  • 差分更新はここがいい
    • きれいでわかりやすいアニメーション
  • 既存アプリ+差分更新
    • 来週からでもいれてみたらいい
      • あかんやつw
    • 実際にやってみた
  • 差分更新いれてみた
    • reloadData()を置き換えていく
    • 遅すぎた。Filterが遅すぎる
    • reloadData()のほうがマシでは?
  • パフォーマンス解析するのにInstruments
    • Timer Profiler
  • Timer Profilerでわかること
    • アプリ実行中のCPU負荷の時系列のグラフ
  • differを使って調査
  • 調査した結果、diffに時間がかなりかかっていた
    • firebaseの指標値内に収めたい
  • diffのあとはpatchのパフォーマンス改善
    • 削除に時間がかかる
      • reloadData()に戻すという方法もある
  • diffの行数だけ計算させて、行数が少なければそのままライブラリ、多ければreloadData()を使うという方法をとった
    • 差分更新と多数行削除の共存
  • banjun/GigDiffer というコンセプト実装ライブラリを作った

Synchronized iPhones!

  • 資料
    • まだない
  • Syncしてやりたいこと
    • iOS端末のリフレッシュレートにあわせる
      • 最も早いリフレッシュレートは60fps
    • CADisplayLinkを使えば、リフレッシュレートにあわせて描画できる
  • iOSデバイスの時刻をあわせる
    • NTP、GPS、NITZ

LT

メモ取る時間がない感じなので、諦めた。
全般的にルーキーという感じがまったくしなくて、とても良かった。

下記のLT資料は、あとで読みたい。
Appleのアニメーションはなぜ美しいか考える

まとめ

デザインやアニメーションについての言及があるセッションがあって、音系のセッションもあって、実り多いカンファレンスだ。

iOSDC 2018 1日目に参加してきた

概要

iOSDC1日目に午前中だけ参加したので、そのまとめ。
参加したセッションまとめと、感想を記しておく。

セッションまとめと感想

登壇者が話したことと感想とが混じっているので、雰囲気で察してくれることを祈る

複数のライブ映像を同期再生するのが大変だったので知見をお伝えします ~~

  • 資料
  • ライブストリーミング系の話は気になる
    • 同期はやったことないけど
  • AVPlayerはしんどいので、できるだけWKWebViewやAVPlayerViewControllerを使おう
    • AudioToolboxで実装するよりはAVPlayerのほうが数段楽なのでは
  • お、やっぱりHLSだ
  • WWDC2017のAdvance in HTTP Live Steamingをみるとだいたい実装できる
  • KVO
    • 音声系のHLSでObjCで実装したなー
  • iOS9のサポートを切る
    • なるほど…
    • iOS10以上じゃないとAPIがないとのこと
  • 設計上のコツ
    • Viewにデータが密結合しやすい
    • 複数の動画が密結合する
    • Managerを作って同期に必要なデータを外に出す
    • わかる、わかるぞ…
  • AVPlayerItem の preferredForwardBufferDuration でバッファ時間の調節ができる

MicroViewControllerで無限にスケールするiOS開発

  • 資料
  • 一番聞きたかったやつ
  • コンポーネントがすべてVCらしい?
  • 層に分割することが目的ではない
  • Micro化することでパフォーマンスがあがる
    • レイアウトに一番時間がかかる
  • StoryboardではなくXIBを使っている
    • IBを使う理由はAutolayoutのエラーを実行前に確認できる手段だから
  • ボタンの種類ごとにVCが存在する
    • まじか…
  • IFを統一した
    • ですよねー
    • じゃないと、現実的に無理だよね
  • かなり強い型プログラミングができる
  • テンプレートでVCの生成を行っている
    • よいぞ
  • サンプルコード

まとめ

フォントと組版の話が聞きたかったけど、用事があるので残念。 明日も楽しみ。

前夜祭の記事

www.macneko.com

iOSDC 2018 前夜祭に参加してきた

概要

iOSDC前夜祭に参加したので、そのまとめ。
参加したセッションまとめと、感想を記しておく。

セッションまとめと感想

登壇者が話したことと感想とが混じっているので、雰囲気で察してくれることを祈る

標準アプリから学ぶ、HIGが教えてくれないiOSデザインのこと

  • 資料
    • まだない
  • ARKitの話も気になったんだけど、こっちにした
  • HIGのお話
  • 自動ドアとか建物とか、同じルールで使えてユーザーが困らないようにしようね
  • 新しい標準が登場したときはその背景・使い方を知ろう
    • OS Xのカラムレイアウトも最初は慣れなかったなー
  • Home Indicatorが新しいUIなのはわかるけど、使いやすいUIなのかなぁ
    • iPhone XのUIは旧来のiPhoneと違っている部分が多くて、好きじゃないんだよな
    • 日常的に使っていたら印象も違うんだろうけど
  • 画面が大型化することによってパラレルでユーザと会話することが可能になった
  • セミモーダルも…うーん…
    • 新しい機能の背景や使い方を知るというのは同意

キラリと光るテクニック、アプリをデモするときの心構え

  • 資料
  • デモすることも多くなりそうなので聞きに来た
  • デモはオフラインでも動くもので行うのが良い
    • 会場に丸投げだとWifiが制限かかって使えないなどよくあるらしい
  • Wifi、Bluetoothは大規模会場ではほぼ使えない
    • WWDCでも使えなかった
  • 電力が心配
    • 会場の電力量を確認しておくといいかも
  • 東日本、西日本で光源にちらつきがでることがある
    • 蛍光灯・LED光源のちらつきがうつることがある
    • 光源をもちこむとよい
      • あ、はい
  • バッテリー問題
    • 管理をちゃんとしよう
    • 監視もあり
  • デバイスの損傷・盗難の心配
    • デバイスの落下は起きることを前提にする
    • 動産保険に入る
  • プロファイルなどの有効期限
    • ちゃんと確認する
  • iPadのClassroomを使う
    • 60台ぐらいまでSafariでこのページを開くなどコントロールできる

iOSエンジニアの為のgrpc-swift入門

再利用可能なUI Componentsを利用したアプリ開発

  • 資料
    • まだない
  • 課題
    • テキストのサイズが異なる
    • IBと色指定が異なる
    • 複数の画面で同じような実装
  • デザイナーのアプローチ
    • デザインシステム
      • 色とかサイズとか決める
      • Sketchのシンボルの話っぽい
  • SketchのシンボルのようにUIコンポーネントが作れたらいいのではないか
    • Atomic Designの話かなーと思ったらやっぱりそうだった
    • 社内のエンジニア共有会でAtomic Designの話を聞いて、これを取り入れたら良さそうと思ってたので、聞けて良かった
    • DXELでもAtomic Designに関連する発表があったな
  • Atomic Designで現状整理、いいね
  • InVisionやZeplinだとスタイル情報、シンボル情報が欠落するので廃止したとのこと
    • なるほどー
  • デザイナーとどうするか決めるのもいいアプローチだな
  • デフォルト実装でスタイルを適用するのか
  • Storyboardでスタイル指定をやめた
    • 石川さんの記事にもあったけど、自分としてもStoryboardで指定するのは限界がきていると思っているので、同意しかない
  • Q.デザイナーとSketchファイルのやり取りはどうしているか
    • Abstractを経由するのが手間だということで、Gitでやりとりしてる
      • え、それはどうよ…

ツールとして利用するUIテスト

  • 資料
  • かっくんさんのQiitaを見て前職の案件でUIテストを導入したのであった
  • たくさんの画面サイズ、回転時のUI確認、大変よね
  • UIテストをしているとしたくなること
  • Xcode9からScreenShotが撮影できるようになった
    • 前職の案件で使ったなー
  • ShellScript化するとよい
    • Gistにあがっている
  • UIテスト遅い問題
    • 並列テストができるようになるらしい
      • 良いのでは
    • 並列化するとシミュレーターの数で実行速度が変わるっぽい
  • TestSummariesを作ったというお話
    • デモを見せてもらったが、これは本当に良いぞ
    • あの案件で導入したかった…
      • UIテスト自体のハードルが高いのでなかなか手が出ないんだよな
  • スクショ撮るツールとしてのUIテスト導入は実際に前職でやったことがあって良さしかなかった
    • 人に教えるときに「これだけ画面あるので」とか話しやすいし、一度画像化しておくと変更も理解しやすいので、良さしかなかった

設計時空のリファクタリング〜複数アーキテクチャを抱えたアプリのリファクタリング事例〜

  • 資料
    • まだ
  • BOOTHアプリのリファクタリングの話?
  • 負債の話は日々直面するよね
  • 複数のアーキテクチャパターンの混在はつらいだろうなぁ
    • 途中から入る立場からすると「え、どれにあわせればいいの?」ってなるし、不安が重くのしかかる
  • リリースが落ち着いているときに負債の返済
    • わかる
  • リファクタリングの方針を考える
    • 手を付けるところから小さく直す
    • 大きなリファクタリングに舵取りしなかった理由
      • 自信がなかった
        • わかる
      • 仕様を理解していない状態では難しい
        • わかる
  • コード理解のためのリファクタリング
    • リファクタリングしながら設計などを理解する
    • わからないことはメンバーにきいて、ドキュメントに残す
    • 責務やフローを再検討する
  • リファクタリングをしたあとにテストをする
    • 都度手動テストはしんどいし、現実的に無理(というのは自分の経験上完全同意である
  • 自動テストを書く
    • UIテストを豊富に書く
      • 経験がないとむずかしめ
    • 単体テストができる形に設計を見直していく
      • リファクタリングのためのテストが必要な問題でデッドロック
        • こちらを選択した
  • 「いきなり新人が仕事を増やしやがったと思われないように説明した」
    • わかる
  • イケていないコードに対する感情
    • 当時は正しかったコードが時間経過で負債になる
  • 反省点
    • 不安を感じすぎてしまった
      • 中途入社だとそうなるのはわかるし、実際自分もそういう心境だった
    • お金が絡んでくる部分のリファクタ…

まとめ

前夜祭から盛りだくさん。
資料はそのうち追記する。
明日も楽しみ。