My Favorite Things - Coding or die.

とある技術者の経験記録、的な。

CAMPFIRE iOS #2 に参加してきた。

CAMPFIRE iOS #2に参加してきました。

ブログ枠です。 多忙でまとめるのが遅くなってしまいました。

WWDC2017 レポート & Quick Look Preview Extension について

  • WWDCに行った感想
    • 英語の勉強にもなるし良い経験になる
  • メリット
    • 1週間、WWDCに集中できる(業務から離れられる)
    • 参加者の日本人同士で交流できる
    • 新機能について不明点があったらLabsに聞ける
  • デメリット
    • 業務溜まったり
    • 飛行機が
  • Bash
    • 有名なアーティストの演奏を聞きながらお食事
    • すごく楽しかったのでぜひ
  • WWDC Labs
    • 既存アプリについてアドバイス
    • 新機能の説明
    • 実装の相談
    • マーケティング関連の質問
      • 英語力がなくて伝わらない場合はタイピングしてもらった
      • やはり英会話は必要
  • UIKitラボ
    • 記事詳細の実装方法について
    • HTMLをUITableViewにマッピングしている
      • UIWebViewの描画だと遅かったから
      • WKWebViewだと速くなった
    • どちらが良いの?
      • サービスの方向性次第だよ
      • UITableView/WebViewどっちでもたくさん使われてるから大丈夫だよ!
    • TRILLのUIについての相談
      • タブ化したほうがよい
      • ユーザに見せたい画面がどれだか分からない
      • 参考に出来るものとしてAppStoreを見ればいいんじゃない?というアドバイスを貰った
    • CoreMLとか
    • Labsは素晴らしい
  • Quick Look Preview Extension
    • 現地でも人気がなかった・・・
    • TRILLではCore Spotlightを導入しているのでチェックした
    • 動画ででも紹介
      • フォースタッチでクイックルック
      • (会場の反応が薄い・・・)
      • 今後は対応端末も増えてくるし、バカにできないんじゃないと思う
  • CoreML
    • デモ
      • 動物をランダムで表示して、それを解析する
      • 機械学習の部分は完全にオフライン
        • ユーザのプライバシーを考慮
        • サーバサイドの実装が必要ない
      • 40行くらいのデモ
  • Day1対応
    • 去年行ったこと
      • Swift3対応
      • UNNotification対応
      • Widget
    • うまく行けばフィーチャー枠に乗っけてくれる
    • 3回くらい特集に組み込まれた
      • Day1の対応をしたおかげ?
    • Swift化は企画も納得してくれたのでやりやすかった
  • まとめ
    • 英語力が必要
    • Quick Look すぐにサービスに使えるのでおすすめ
    • Day1対応

WWDCについてのリアルな感想が聞けて良かったです。

ちなみに Quick Look Preview Extension は正直あんまり興味をそそられませんでした。私がフォースタッチの端末を持っていないのと、フォースタッチ自体あまり良い機能とは感じないためですが。(SteveJobsだったら絶対につけない機能だと思ってます)

マスティフ: (for Xcode Beta) バージョンアップ対応を軽減するためのサービス

  • イントロ
    • マスティフ
    • 今日は Xcode β について
  • 宣伝
    • iOS Test Night #5
    • 今の人数は把握済みです
    • WEB-DBに寄稿しました
      • Espresso / XCTest / Appium
      • UIテスト自動化
  • WWDCについて思うこと
    • Xcode9になってようやくまともなIDE
    • アプリの動作確認とか既存の動作については?
  • WWDC2017の影響
    • 既にリリース
      • 自動アップデート
      • サブタイトル
      • プロモーション用テキスト
    • そのうち
      • Xcode9
      • iOS11
  • マスティフとは?
    • バージョンアップ対応軽減サービス
    • ライブラリのバージョンアップを自動的に行なってくれる
    • 既存ライブラリが動くことを定期的に動作確認
      • 使えなくなったことを早めに知りたい
    • 大きな流れ
        1. バージョンチェック
        1. バージョンで動作確認(Jenkins)
        1. 通知
    • 1日1回、現行バージョンの動作確認
    • 新しいリリースの検知
      • Xcodeとか自動的にインストールされる
      • Fastlane/gem
    • 朝来て通知を見たら落ちるのが分かってた
      • Firebase
    • セマンティックバージョンに従っているものは少ない
  • WWDC2017初日の出来事
    • deliverが失敗してた
    • 出社するまでには全ての対応が終わっていた
  • Xcode βとの生活
    • 1.ベータ版はn回リリースされる
      • info.plistのバージョン番号は変わらない
      • buildNumberを見る
    • 2.ベータ版のGM
    • 3.正式版
    • マスティフ
      • Xcode β は通常フロートは別で用意
      • 古いのは残さない
      • 散布アプリを元に動作確認
        • 既存
        • 新規対応
  • SWETとして
    • テスト周りと中心に見ていく
  • 最後に
    • WWDC2017お疲れ様でした
      • GM版が出るまでが勝負
      • バージョンアップ対応における不安とコストは極力下げていこう
    • フィーチャー
      • iOSバージョンアップも自動化出来ないかを検討中
        • AWS Device Farm での利用を検討したがベータ版が無い
        • 新しいテストの仕組みで自動化できるかも?
          • うまく行ったらシェアします

Mastiff、OSS化が楽しみです。

Essential for What’s new in Distribution

  • イントロ
  • Distribution で何が変わったか?
  • Report
    • 新しいAppStore
      • 俺達が作った最強のAppStoreという話
    • iTunes Connect
    • StoreKit
    • Device Configuration Deployment And Management
      • ATS対応が2018年に必須化される(さらっと)
    • Advanced StoreKit
      • レシートのバリデーションやSandboxの話
  • AppStore
    • タブが増えた
    • IAPが可能に
    • サブタイトル
    • 動画プレビューが勝手に再生される
    • プロモーションテキスト
  • iTunesConnect
    • 段階的リリース
    • TestFlight
    • 90日間有効
    • 外部テスターが10000人
    • AppStoreで閲覧可能
  • Phased Release
    • 設定しているユーザのみ
    • StoreにアクセスすればDL可能
    • 最大7日で100%リリース
    • Pause可能
      • 何か問題があったら止められる?
      • 制限があるのでAndroidほどではない
  • StoreKit
    • レーティングの話
      • すべてのバージョンのレビューのみ表示
      • バージョンアップ時にリセット可能
        • 日本のユーザのせい?
      • Rating/Reviewを求められるように
      • AppStoreRviewへのDeepLink
      • 1行だけのAPI
        • 適切なタイミングでしか出せない
        • 年3回
        • ボタンを使うならDeepLink、アラートを使うなら、SKStoreReviewControllerを使うこと
          • アラートはNG?
  • レビューのガイドラインが変わった
    • App Review Guideline
      • diffが見れるサイト
  • 本編(WWDC2017)
    • Dub-Dubという略し方だった
    • サンノゼ
    • WWDC Extended、ここでやった
  • AltConf 2017
    • 隣の建物でやってた
    • 今年は結構ガラガラだった
  • Swift Panel
    • Swiftを作った人のパネルディスカッション
    • 待ってる人がやたら多い
    • 2ショット写真が取りたかった
  • Beer Bash
  • 写真
    • いろんな開発者と会いました
    • アメリカ人はNBA大好き
  • 犬?
    • Zaku-K9
      • 麻薬とかを見つける警察犬

いやはやWWDCは楽しそうです。

段階的リリースはAndroidほど自由度は高くないようですが、ブランドを大切にしているAppleとしてはよく導入したものだなぁと思います。これもSteveJobsなら絶対にやらないことでしょうが・・・まぁ開発者にとっては楽になるので良しとするのもありでしょうか。

クックパッドiOS更新との付き合い方

  • イントロ
  • 過去のiOS/Xcode更新の対応事例の紹介
    • Handoff対応
      • iOS/Macの体験を引き継ぐ(iOS8)
      • レシピ画面を共有
      • 自動アップデートに連動して辛いことも
    • AppleWatch
      • レシピで指定された時間のタイマーを
    • Swift
      • かなり慎重に導入した
      • レガシーコードのリファクタリングやnullabilityも利用した
      • 現在は35%がSwift
    • 新しい機能を導入・利用する理由
      • 利便性
        • 4.7/5.5インチ
        • Spotlight
        • Shared Web Credential
          • 楽にログインできるように
    • プロモーションのため
      • Handoff対応
      • AppleWatch対応
        • Appleのサイトに載せてもらえる
      • 新機能を利用したアプリはAppStoreで目立つ
    • 開発効率向上の為
      • Swiftの利用
      • AutoLayout、UIStackView、WebView
      • 非推奨になったAPIは利用しないように(負債になる)
    • 変更点の情報収集
      • 公式ドキュメント、API diff
      • iOS/Xcodeのベータ版をすぐに試す
      • Beta版でドキッとしたこと
        • Safariからのリンクが全てアプリに遷移みたいな
          • 途中で動きが変わった
        • アプリ削除でKeychainの情報も消える
      • バグかと思ったらバグレポートを送ったり、フォーラムを見ると良い
    • 事業への影響
      • コンテンツブロッカー
        • スマホWebの広告はどうなる?
        • アプリのことだけ気にすればいいわけではない
      • ATS
        • どこまで対応すればいいのか・・・
        • 広告SDKの通信など自社だけで解決しないものもある
    • 開発環境の変化に追従する
      • Xcode/Swiftバージョンアップ
      • 常に情報収集して追従していく
      • 開発を続けられない状況にならないように気をつける
    • サポートバージョンの見直し
      • 新機能が使えるのは新しいバージョンだけなので
      • 基本は直近2バージョン
      • OS更新の案内をきちんとする(慣れていないユーザもいるので)
    • 新機能導入の判断基準
      • ユーザが便利になったり、影響サービスとマッチするものは積極的に
      • 機能リリース後に取り下げることもある
        • サービス拡大像をうまく描けなかった
        • 中途半端に残してもユーザ・サービス提供側、双方に不利益
      • 開発効率やパフォーマンス、セキュリティ向上なら
      • 明らかにやらないと行き詰まるものはやるしかない
        • 最新のSDKを使う
  • まとめ
    • ユーザが便利になる機能は積極的に採用していく
    • バージョン・アップによる変更点の情報はしっかりと
    • 安定したリリースサイクルを回すために、開発環境に関わるところは早めに

かなりボリューミーな発表内容だった気がします。

iOSでの新機能に関してうまくいかなかった点も含めての発表内容だったのでとても参考になりました。

iOS11対応に向けて - Yahoo! JAPANアプリiOS10対応事例紹介

  • イントロ
  • iOS 10 の話
    • どのように新OSと向きあっていくか?
    • 失敗や試行錯誤
  • 65
    • WWDC終了〜iOS10リリースまでの営業日
  • 全体スケジュール
    • 6月:キックオフ
    • 7月:アイディア出し
    • 8月:開発
    • 9月:リリース
  • 6名体制
    • YJの中でも珍しい(力を入れてる)
  • キックオフ
    • 過去、リリースに間に合わないことがあった
      • 完成度にこだわってしまった
    • トレードオフスライダーを作って方向性を
      • スケジュール ※一番
      • API対応
      • 特集掲載
      • 途中から入ってくるメンバーにも必ず共有するようにした
  • アイディア出し
    • 良いアイディアが欲しい
    • 1.有志の協力者募集
      • デザイナーが4名入ってくれた
    • 2.デザインスタジオ
      • ブレストでペーパープロトタイピング
      • あとでみんなで発表
    • 良いアイディアはたくさん出た
      • トレードオフスライダーによりスケジュールが大切だという判断が容易にできた
  • 品質チェック
    • 社内SDKの取り込み
    • 課題
      • 取り組む温度感がまちまち
      • 多対多のコミュニケーションでコストがかかった
    • テスト計画
      • 課題
        • コスト大(7,000件) ※手動のテストです
          • かけ過ぎだと怒られた
      • 改善策
        • 社内SDKの対応に期限を設ける
          • タイミングを揃える
        • マスターテストケースに優先度付
    • まとめ
      • 成功するためのルールを作って自立したチームへ
      • テスト計画は効率とコストバランスを見て早期に立てる
        • これでiOS11も万全

YahooでのiOS新機能対応についての戦略的な内容が聞けて、大変貴重だと感じました。

みんなでアイディア出しをしたり、トレードオフスライダーを作ったり、すごく面白そうなことをやっているなぁと感じました。

まとめ

WWDCに関する情報や感想、iOS新機能対応、Mastiff、など、様々な発表が聞けて非常に有意義な勉強会でした。

会場(LODGE)も広くてキレイ、かつ懇親会でのお寿司も美味しかったりと、なかなかにリッチな勉強会でもありました。

メタプログラミングRuby - 2章 月曜日:オブジェクトモデル(その1)

前回に引き続きRubyメタプログラミングについて学んでいきます。

オープンクラス

既存のクラスにメソッドを追加する

Rubyのクラスは標準ライブラリも含めて「オープン」であり、 あとからメソッドを追加したり、既存のメソッドを置き換えたりすることが可能である。

class String
  def emphasize
    self + '!!'
  end
end

p "Hello, world".emphasize # => "Hello, world!!"

ここでは標準ライブラリのStringに対してemphasizeを追加している。

既存のメソッドも置き換えられる

注意すべきなのは既存のメソッドを置き換えても何の警告も出ないことである。

p "Apple".length # => 5

class String
  def length
    1
  end
end

p "Apple".length # => 1

ここでは既存のメソッドString#lengthを再定義して、1を固定で返す実装にしている。

こうした場合でもRubyは何の警告も表示しない。

つまりこれは強力で機能であると同時にかなりのリスクも伴うことが分かる。 間違って既存のメソッドを置き換えようものなら、簡単にシステムを壊してしまう。

クラス定義は他のコードと違いはない

他の多くの言語では「クラス宣言」は専用の構文であることが多いが、 Rubyでは通常のコードと変わらない。

3.times do
  class Foo
    puts "Hello"
  end
end

ここでは 1.ループ構文の中でクラスを定義しているし、2.クラス定義の中で特定の処理を呼び出している。

class構文は、もしそのクラスがまだ定義されていなければそのクラスを新たに作成し、そうでなければ既存のクラスをオープンする、という挙動となっている。

オブジェクトモデル

インスタンス変数

他の多くの言語では、クラス定義に含まれるインスタンス変数は固定であるが、Rubyにおいては動的である。

class Foo
  def bar
    @x = 1
  end
  attr_reader :x
end

f = Foo.new
p f.x                  # => nil
p f.instance_variables # => []

f.bar # これを呼び出すことによりインスタンス変数`@x`が追加

p f.x                  # => 1
p f.instance_variables # => [:@x]

ここでは@xに値を代入するコードがFoo#barに定義されているが、 これを呼び出すまでは@xは存在しない。

コード中にあるようにinstance_variablesを呼び出すことで、定義されているインスタンス変数の一覧を得ることが出来る。

メソッド

インスタンスの中身はオブジェクトによって異なるためオブジェクトごとに用意されるが、 メソッドは全オブジェクトに共通なのでクラスに定義される。

class Bar 
  def foo
    puts "foo"
  end
end

b = Bar.new
p b.class                          # => Bar
p Bar.instance_methods.grep(/foo/) # => [:foo]

Bar.newしたbオブジェクトは、クラスオブジェクトBarへの参照を持ち、 fooBarクラスオブジェクトのインスタンスメソッドとして宣言されているのが分かる。

実際に呼び出されるメソッドの特定には「メソッド探索」という仕組みが使われるが、 それについては後ほど。

クラスはオブジェクト

既に簡単に触れてしまったが、Rubyにおいてはクラスも単なるオブジェクトである。

p "hello".class # => String
p String.class  # => Class
p Class.class   # => Class

"hello"Stringクラスのオブジェクトであり、StringClassクラスのオブジェクトである。 (Classの先はずっとClassのオブジェクトである)

Rubyでは#newを呼び出してオブジェクトを初期化するが、これはClassクラスに定義されたインスタンスメソッドである。

# `false`は継承されたメソッドを表示しないという意味
p Class.instance_methods(false) # => [:new, :allocate, :superclass]

つまり、String.newとした場合、Stringオブジェクトに実装されたnew、より具体的にはClass#newメソッドを呼び出していることになる。

ちなみにallocateというメソッドは、インスタンス生成時にinitializeを呼び出さないところがnewと異なる。

superclassメソッドは親クラスを取得するのに利用できる。

p Array.superclass        # => Object
p Object.superclass       # => BasicObject
p BasicObject.superclass  # => nil

継承ツリーとしては以下のようになる。

Array --> Object --> BasicObject

BasicObject.superclassnilであることから分かるように、 BasicObjectRubyにおけるルートクラスである。

モジュール

Classクラスの親クラスはModuleである。

p Class.superclass  # => Module

つまり、Class is a Module、すべてのClassModuleであると言える。

Classにはnewallocatesuperclass というインスタンスメソッドが定義されていることが確認できたが、 Moduleとの違いはこれだけである。

定数

Rubyにおいて大文字から始まる変数はすべて定数である。 すなわちStringといったクラスについても、ただの定数であると言える。

もっともRubyにおける定数には強制力がなく、 書き換えようとした時に警告が表示されるくらいであるが。

ツリー構造

定数はツリー構造を持つ。

X = "::X"
module M
  X = "M::X"
  class C
    X = "M::C::X"  
  end
end

p ::X     # => "::X"
p M::X    # => "M::X"
p M::C::X # => "M::C::X"

ここでは以下のような階層を持っている。

  • Root
    • X
    • M
      • X
      • C
        • X

つまり同じ定数名Xでも所属しているスコープが異なるのである。

::

先のコード中で示したように定数のパスは::で記述する。

Y = "::Y"
module M2
  Y = "M2::Y"
  p Y   # => "M2::Y"
  p ::Y # => "::Y"
end

定数ツリーの中間にいた場合、相対パスでアクセスするため ルートからアクセスしていることを明示する場合には先頭に::を記述する。

ネームスペースとしての定数

あるクラスを新たに定義しようとした時、 既に同名のクラスがあると既存クラスをオープンする形になってしまう。

いわゆる名前の競合である。

それを避けるために定数ツリーが利用できる。

module Editor
  class String
  end
end

p String == String          # => true
p String == Editor::String  # => false

ここでは標準ライブラリと同じ名前のStringを宣言しているが、 Editorモジュールの内部であり定数ツリー上の位置が異なるため別のものとして扱われている。

このように定数をネームスペースとして利用することで、 名前衝突を割けたり、分かりやすい階層にクラスを配置することが出来る。

今回のまとめ

  • Rubyオープンクラスである
  • Rubyにおいてクラス定義に紐付いたインスタンス変数というものは無い(動的)
  • RubyのクラスはClassクラスのオブジェクトである
  • Classクラスの親クラスはModuleである
  • ClassクラスはModuleに加えてnewallocatesuperclassを定義したクラスである
  • RubyのルートクラスはBasicObjectである
  • Rubyのクラスは単なる定数である
  • 定数はツリー構造を持つ

Kotlin で HelloWorld(コマンドライン編)

さて前回に続いて、今度はコマンドラインで Kotlin のHelloWorldをやってみたいと思います。

公式ドキュメントのチュートリアルを見ながら進めていきます.

インストー

まずは念のため既にインストールされていないか確認します。

$ kotlinc
zsh: command not found: kotlinc

IntelliJ IDEA で自動でインストールされてはいないようですね。

SDKMAN! のインストー

brewでインストールするのが手っ取り早いかと思ったのですが、 SDKMAN!という複数バージョンを共存させられるrbenvと似たようなツールがあるようです。

しかもKotlin以外の言語にも対応しているとのことで今後も使えそうなので、これを使ってインストールしてみます。

$ curl -s https://get.sdkman.io | bash
...
All done!


Please open a new terminal, or run the following in the existing one:

    source "/Users/yusuke/.sdkman/bin/sdkman-init.sh"

Then issue the following command:

    sdk help

Enjoy!!!

以下のコマンドを実行して有効にします。

$ source "/Users/yusuke/.sdkman/bin/sdkman-init.sh"

sdk helpと試しに打ってみると。

$ sdk help

Usage: sdk <command> [candidate] [version]
       sdk offline <enable|disable>

   commands:
       install   or i    <candidate> [version]
       uninstall or rm   <candidate> <version>
       list      or ls   [candidate]
       use       or u    <candidate> [version]
       default   or d    <candidate> [version]
       current   or c    [candidate]
       upgrade   or ug   [candidate]
       version   or v
       broadcast or b
       help      or h
       offline           [enable|disable]
       selfupdate        [force]
       flush             <candidates|broadcast|archives|temp>

   candidate  :  the SDK to install: groovy, scala, grails, gradle, kotlin, etc.
                 use list command for comprehensive list of candidates
                 eg: $ sdk list

   version    :  where optional, defaults to latest stable if not provided
                 eg: $ sdk install groovy

sdk listというコマンドを使うとインストール可能なツールや言語の一覧が表示できるっぽいです。

================================================================================
Available Candidates
================================================================================
q-quit                                  /-search down
j-down                                  ?-search up
k-up                                    h-help

--------------------------------------------------------------------------------
Activator (1.3.10)                   http://www.lightbend.com/activator/download

Typesafe is a GUI/CLI tool to help with building reactive applicaions. It uses
sbt (simple build tool) behind the scenes to build, run, and test your project.
It provides a code editing interface, and provides templaes and seeds for you to
clone and use.

                                                         $ sdk install activator
--------------------------------------------------------------------------------
Ant (1.10.1)                                             https://ant.apache.org/

...

Kotlin のインストー

SDKMAN!を使ってインストールをします。

sdk list kotlinコマンドで、一応インストール可能なバージョン一覧を見てみます。

$ sdk list kotlin

================================================================================
Available Kotlin Versions
================================================================================
     1.1.2-2              1.0.3                                                    
     1.1.2                1.0.2                                                    
     1.1.1                1.0.1-2                                                  
     1.1-beta2            1.0.1-1                                                  
     1.1-beta             1.0.1                                                    
     1.1-RC               1.0.0                                                    
     1.1-M04                                                                       
     1.1-M02                                                                       
     1.1-M01                                                                       
     1.1                                                                           
     1.0.7                                                                         
     1.0.6                                                                         
     1.0.5-2                                                                       
     1.0.5                                                                         
     1.0.4                                                                         

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

なるほど今日時点の最新は1.1.2-2なのですね。

sdk install kotlinで最新版をインストールします。

$ sdk install kotlin

Downloading: kotlin 1.1.2-2

In progress...

######################################################################## 100.0%

Installing: kotlin 1.1.2-2
Done installing!


Setting kotlin 1.1.2-2 as default.

もう一度sdk list kotlinしてみる、最新版がインストールされて有効になっているのが分かります。

$ sdk list kotlin

================================================================================
Available Kotlin Versions
================================================================================
 > * 1.1.2-2              1.0.3                                                    
     1.1.2                1.0.2                                                    
     1.1.1                1.0.1-2                                                  
     1.1-beta2            1.0.1-1                                                  
     1.1-beta             1.0.1                                                    
     1.1-RC               1.0.0                                                    
     1.1-M04                                                                       
     1.1-M02                                                                       
     1.1-M01                                                                       
     1.1                                                                           
     1.0.7                                                                         
     1.0.6                                                                         
     1.0.5-2                                                                       
     1.0.5                                                                         
     1.0.4                                                                         

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

下の方に書いてありますが、

  • * がインストール済み
  • > が現在有効になっているバージョン

ということみたいですね。

+はまだ表示されていないので断言できませんが、特定のディレクトリに適用されたバージョンが表示されるのでしょう。

Hello, world!

ソース作成

さてまずはhello.ktを作成します。

$ touch hello.kt
$ vim hello.kt
fun main(args: Array<String>) {
    println("Hello, World!")
}

コンパイル

つぎはコンパイルですね。

kotlincというコマンドを使ってコンパイルするようです。 (ちょっと長いのでktcとかエイリアスを貼ってもいいかもですね)

$ kotlinc hello.kt -include-runtime -d hello.jar

-dが出力を指定するもの、-include-runtime.jarの中にKotlinのランタイムを同梱するオプションのようです。

ちなみに最初に拡張子を.ktではなく.tkとしてしまっていたのですが、そうした場合は以下のようなエラーが出てコンパイルできませんでした。

$ kotlinc hello.tk -include-runtime -d hello.jar
error: source entry is not a Kotlin file: hello.tk

なるほど拡張子は.ktでないとKotlinのソースとしては認識されないのですね。

実行

さてディレクトリの中身を見ると、hello.jarがちゃんと出来ていますね。

$ ls
hello.jar  hello.kt

javaコマンドを使ってjava -jar hello.jarで実行できるようです。

$ java -jar hello.jar 
Hello, World!

ちゃんと実行できましたね。

kotlinc

kotlinc -helpでヘルプが見られるようなので確認しておきます。

$ kotlinc -help
Usage: kotlinc-jvm <options> <source files>
where possible options include:
  -d <directory|jar>         Destination for generated class files
  -classpath (-cp) <path>    Paths where to find user class files
  -include-runtime           Include Kotlin runtime in to resulting .jar
  -jdk-home <path>           Path to JDK home directory to include into classpath, if differs from default JAVA_HOME
  -no-jdk                    Don't include Java runtime into classpath
  -no-stdlib                 Don't include Kotlin runtime into classpath
  -no-reflect                Don't include Kotlin reflection implementation into classpath
  -module <path>             Path to the module file to compile
  -script                    Evaluate the script file
  -script-templates <fully qualified class name[,]>
                             Script definition template classes
  -kotlin-home <path>        Path to Kotlin compiler home directory, used for runtime libraries discovery
  -module-name               Module name
  -jvm-target <version>      Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6
  -java-parameters           Generate metadata for Java 1.8 reflection on method parameters
  -language-version <version> Provide source compatibility with specified language version
  -api-version <version>     Allow to use declarations only from the specified version of bundled libraries
  -nowarn                    Generate no warnings
  -verbose                   Enable verbose logging output
  -version                   Display compiler version
  -help (-h)                 Print a synopsis of standard options
  -X                         Print a synopsis of advanced options
  -P plugin:<pluginId>:<optionName>=<value>
                             Pass an option to a plugin

もっと大量のオプションを予想していたのですが、思ったよりは少ないですね。(swiftc --helpの量が多すぎるのかも分かりませんが)

今後必要な時に見ていくことにします。

最後に

さて無事にコマンドラインでKotlinのHelloWorldを試すことが出来ました。 最近の言語は試すのが導入から試すまでが簡単で良いですね。

ちなみにチュートリアルのページには、ライブラリの作成方法やREPL、スクリプトとしての実行などが含まれているのですが、続きは別の記事にしたいと思います。

Kotlin で HelloWorld(IntelliJ IDEA編)

世の中はKotlin一色ですね。(言い過ぎ?)

そんなわけで私もKotlin始めてみようと思います。
まずは IntelliJ IDEA(Community Edition)をつかってサクッと。

IntelliJ IDEAのダウンロード

公式サイトからCE版をダウンロード。 www.jetbrains.com

無償のCE版でもKotlinが使えるってのはありがたいですね。
(JetBrainsからしたらそりゃ使ってほしいでしょうが)

プロジェクト作成

Create Project から作成します。 f:id:yu_dotnet2004:20170527195615p:plain

Kotlinの中に「Kotlin (JVM)」ってのがあるのでそれを選択します。
(というかJavaScript版?があるのに驚きました) f:id:yu_dotnet2004:20170527195641p:plain

Project name は「HelloKotlin」にしてみます。 f:id:yu_dotnet2004:20170527195847p:plain

ウィンドウが表示されたものの殆ど表示されないので戸惑いましたが処理中のようです。 画面下の方にインジケータが表示されています。 f:id:yu_dotnet2004:20170527195951p:plain

Kotlinファイル作成

まだ良くわかっていませんが、srcディレクトリを右クリックして「New > Kotlin File/Class」を選んでみます。 f:id:yu_dotnet2004:20170527200103p:plain

ダイアログが表示されるので Name に「HelloWorld」と入れてみます。 f:id:yu_dotnet2004:20170527200149p:plain

コードを書く

エディタが表示されるので早速コードを書いてみます。

fun main(args: Array<String>) {
    println("Hello, world!")
}

main関数の行に Kotlin のアイコンが表示されました。 f:id:yu_dotnet2004:20170527200314p:plain

実行

Kotlinアイコンをクリックしてみると、どうやらここから実行できるようです。(便利) f:id:yu_dotnet2004:20170527200405p:plain

画面下の方に実行結果が出力されました。なにやらエラーっぽいものも表示されていますが、とりあえず実行はできているようです。 f:id:yu_dotnet2004:20170527200459p:plain

ディレクトリ構成

ちなみにサイドバーを見るとコンパイル後の結果は out ディレクトリ配下に格納されるようです。 f:id:yu_dotnet2004:20170527200543p:plain

最後に

とりあえず覚え書きとしてスクリーンショット多めで記事を書いてみました。

次回はコマンドラインでHelloWorldしてみたいと思います。

potatotips #40 に参加してきました。

はじめに

(2017/05/27追記) 新たに公開された発表資料を追加しました。

以下のイベントに参加してきました。 potatotips.connpass.com

実は当日まで参加予定ではなかったのですが、 偶然にもAndroidのブログまとめ枠が一人空いたとのことで急遽参加させていただきました。 (ちなみに「ブログまとめ枠」での参加は初めてです)

ちなみにここ数年はiOSエンジニアとしての活動が多いので、ポテチには一度は参加したいと思っていました。 本当は発表者として登壇したいという欲望もあったのですがそれは別の話。

Androidのブログまとめ枠での参加でしましたが、iOSも含めて記事にしちゃいたいと思います。 (大丈夫ですよね?)

箇条書きはリアルタイムで頑張って書いたものなので、間違いとかあるかもです・・・ご容赦を。 またスライドとかは後日公開とかもあると思うので、アップされしだいリンク追加していきます。

乾杯

まずは乾杯、というかもう飲んでる人多数。 Swift愛好会といい最近の勉強会は最初に乾杯ってパターンが多いんですかね?

事前説明

Rettyの中川さんより会場説明。

CMタイム、スポンサーだから当然許されます。 engineer.retty.me

iOSDCやPyConなどのスポンサーもやっているらしいです。 イベントスペースなどもレンタルもやっているとのこと。

Retty Android もくもく回?なるものもやっている、 勉強会などのコミュニティ活動もサポートしてくれる、とのこと。ふむふむ。

では、各発表のまとめです。

どうしたらログがちゃんと管理できるのか?(kosako)

speakerdeck.com

  • アプリの分析
    • GA
    • DB
    • 自前(TD?, BigQuery)
      • 今回はこれのお話
  • よくあるパターン
    • ここの数字をみたい
    • ボタンのタップ数ってどっちが多いの?
  • よくあるパターン
    • 都度埋め込まれるログ
    • 取りたいデータが取れない
    • 後始末がされにくい
    • etc
  • アプローチ
    • ログを送るメソッドを1つに
    • コールする場所ではどこに送るか指定しない
    • 送信設定ファイルを用意して集約
  • イメージ
    • ボタンタップ
    • 送信メソッド(ここで設定ファイルを見る)
    • 送信
  • 設定ファイル(log.json
    • ログの設定を集約する
  • ポイント
    • JSONファイルを用意すれば
    • ログの意味が分かりやすい
    • ログ同士の対応表がそこにある
    • 設定ファイルを変更すればOK
  • 今後の野望

「ログをどう管理するか?」という課題に対して、1つの設定ファイル(JSON)に集約するというアプローチ。 個人的にはコード上に値が分散するよりも断然良いと感じたので、良いアプローチだと感じました。

Modern Java Libraries with Kotlin(Keisuke Kobayashi)

  • 無料送金アプリ(Kyash)
  • 今日
    • JavaライブラリをKotlinでも
    • 特別に対応が必要なケース
  • Dagger2 + Orma
    • kaptで自動生成されるクラスはDaggerでprovideできない
    • OrmaDatabase
  • OrmaDatabaseをラップすればOK
  • Dagger Module
    • ラップしたクラスを返す
  • Data binding
    • dependenciesにkaptを追加する
    • Androidバージョンに依存するのでバージョン番号も書く
  • Parceler
    • Parcelableのボイラープレートを自動生成
    • Kotlinのデータクラスで使いたい
  • data class
    • toString, hashCodeの実装が不要
  • @Parcelをつけるだけでは動かない
    • Kotlinのプロパティはフィールドではない
  • @Parcel(Parcel.Serialization.BEAN)ってやつ
  • おまけ
    • サンプル作ったよ(2ヶ月くらい)

JavaライブラリをKotlinで使う際に特別な対応が必要になるケースの紹介でした。 私はAnrdoid初学者でDaggerくらいしかライブラリを知らなかったのですが、なんとなくイメージは伝わってきました。

個人的に、Kotlinのプロパティはフィールドではない、というのは勉強になりました。

ゲームアプリの「ドット絵」をディープラーニングで自動生成(shu223)

qiita.com

  • 結論:失敗したorz
  • DCGAN
    • アイドルの顔画像を大量にあつめて自動生成
    • スライドに写されたのは元データではなく実際に生成された画像!!
  • DCGAN-tensorflow
    • サンプルデータだとセレブっぽい顔の画像をせいせい
  • 自前のデータを食わせてみたい
  • スーパークエス
    • ドット絵モンスターを自動生成できないか?
  • やってみた
    • 基本的にフォルダに置いて動かすだけ
  • epoch
    • 学習の進み具合
    • 途中経過が面白い
  • 学習は順調に見えた
  • 過学習
    • 学習データを元にしちゃってる?
  • 何が違っていたのか?
    • セレブは20万枚
    • 目も鼻もある、だいたい似てる
    • アイドルデータも似てる
    • 学習データの量も変化も違う
  • まとめ
    • ダメだった
    • 問題設定が悪かった&データ量が少なかった
  • QA
    • もう一度チャレンジしますか?
      • しません。(ドット絵の題材はもうやらない)
    • 解析にかかった時間
      • MacBookProでまる1日くらい

ドット絵ディープラーニングで自動生成しようとしたけれどダメだったというお話。 結果はさておき、失敗要因の分析がとても良いと思いました。

ちなみに epoch の過程を見るのは確かに楽しそうだと思いました。

Kotlin Reflection(hikaru_satoh)

  • 自己紹介
  • リフレクションのKotlinバージョン
    • KClass、KPropertyを利用する
  • プロジェクト設定
    • app/build.gradleに追加する
    • 書かなくてもビルドエラーにはならなかったが、エラーログとか
  • 4.8kb多くなった
  • Class References
    • KClass型
    • User::classで取得
  • member.properties
  • private
    • privateなプロパティがあると例外スロー
    • isAccesible = trueってやれば見られるようになる
  • Property References
    • kProperty型
    • User::firstName.get(user)みたいな感じで使える
    • privateメソッドは見られないのでコンパイルエラーになる
  • KProperty1
    • p:KProperty1<User, *>
  • KPropertyの種類
    • 0: static変数を取得
    • 1: メンバーのプロパティ取得
    • 2: (聴き逃した)
  • まとめ
    • Javaと同じような感じでアクセスできそう
    • 他にもリフレクション機能はいろいろ使えそう
  • QA
    • リフレクションの具体的な利用事例は?
      • デバッグ出力を簡単にしたり、ホットパッチ?

Kotlinでのリフレクションの使い方についての説明。 Java8におけるメソッド参照みたいなことが出来る分、Kotlinのリフレクションは安全なのだなと感じました。

シークバーサムネイル作成Tips共有(satoshi0212)

  • AbemaTVの人
  • 何を作ったのか?
    • シークバーのサムネイル表示機能
  • アトラス画像表示
    • サムネイル画像をまとめたもの
    • APIを用意してもらって、番組ID、サイズ、時間
    • 1枚で600秒分
    • シークバーを初めて触った時に取得
    • 再生時間を元に特定
  • デザインの作り込み
    • デザイナさんが思い入れ
  • DEMO
  • まとめ
    • アトラス画像方式はわりと軽めで実装できた
    • 画像取得タイミングを遅らせてみた
  • 蛇足
    • 作り込みたいけれど締切はあるね
    • そういう部分を作る担当になる
  • QA
    • 画像の切り出しタイミングって?
      • 実際に表示しようというタイミングで切り出してUIImageを生成している
      • けれど質問されて、UIImageで切り出す必要はないかもと思った

動画再生においてシークバーをスライドするとサムネイルが表示される例のアレ。 アトラス画像といった考え方や、データ取得を遅延させるといったテクニックなどが聞けて面白かったです。

ちなみに、そういう部分を作れる担当になれるかが重要、というのはまさにだと思いました。

Android Instant App(Sam)

www.slideshare.net

  • 自己紹介
  • Android Instant Appとは
    • インストール不要のAndroidネイティブアプリ
    • URLの起動に応答してインストール不要でアプリ起動
    • PlayStoreとは全然別
  • 仕組み
    • 機能ごとにダウンロードしてくる
    • URLからの要求に対して必要な機能だけをダウンロード
  • 2つのAPK
    • Base Feature APK
      • 2回目以降のダウンロードは不要
    • 機能のAPK
  • 機能ごとにモジュール化させる
    • 1つのモジュールは4MBまで
  • 制限されている機能
    • フアグラウンドは実行できる
    • 外部ストレージアクセス
    • 明示的インテント
    • ブロードキャスト
  • 使えない機能
    • コンテンツプロバイダ使えない・・・
  • コンテンツプロバイダ
    • DAO使えない
    • Realmは3MB
    • Firebase Realtime Database
      • Googleが使っていいよ、と。
      • データベースの時代はクラウドになったんだぜ、と。
  • 現状
    • 50個以上のアプリが対応済み
  • ぶっちゃけ?
    • 情報が少なすぎる。。。
    • 導入する場合はユースケースを決める必要がある
      • どんな体験を?どこの機能を?

Android Instant App についての紹介。 今まで噂に聞いたことがあるレベルだったので、具体的な内容が知れて良かったです。

ユーザにとっての利点は納得できるものの、これだけ制限が多い中、開発者的にはそんなに美味しいかしら、とも思いました。 日本のブロードバンド事情を考えると、Instant App を開発して公開するメリットを感じるアプリは少ない印象を受けました。

ちなみに私も暴君ハバネロは大好きで、箱買いしたこともあるレベルなので懇親会で話そうと思いつつ、 まとめに疲れてすっかり忘れてしまいました・・・またの機会に。

Universal Links 対応した話(Ridwy)

www.slideshare.net

  • 自己紹介
    • 音声処理技術が好き
  • モチベーション
    • iOS9以降の機能
    • iOS10が普及したので
    • 実際に対応して得られた知見
  • Universal Linksとは
    • ユーザから見て
      • Webのリンクをタップした時に、ドメインに対応するアプリが起動する
    • ステータスバー
      • 左:遷移元へ
      • 右:Safariで開く、ってやれば今後もSafariで開かれる
      • 正直ユーザにはわかりづらい印象
  • アプリが起動する条件
    • Safariで開くことを選択していない
    • iOS9以降
    • アプリがインストールされている
      • インストールされていないとそのまま遷移(ストアは立ち上がらない)
    • 同一ドメイン内の遷移ではない
  • おさらい
    • Entitlementにドメイン追加
    • アプリが開かれた時に呼ばれるメソッドを実装
    • 扱えないURLはopenで開きなおす
      • でも見た目はいまいち
  • サーバ側の対応
    • AASAファイルを配置
      • ルートまたは.well-knownサブディレクトリ配下に
      • HTTPSで直接アクセスできるようにする
      • HTTPはNG、リダイレクトもNG
      • アプリのインストール時に取得される
  • AppIDのプリフィックス
  • SKIP
  • iOSが何をしているか?
  • QA
    • AASAファイルの更新が必須

iOS9から導入された「Universal Links」についての詳細な発表。 UI/UXに関わる意見や、内部的な実装がどうなっているかの予測など、なかなか深いところまで突っ込んだ内容でした。

発表者の方も言っていましたが、UIはもうちょっとどうにかならないかと感じました。

フル Kotlin で Mastodon クライアントを作ってみて(tomoya0x00)

qiita.com

  • 自己紹介
    • 組込系がメイン
    • 最近アプリとかも
  • Mastodonクライアント
    • MVVM x フルKotlin
  • なぜ?
    • SwiftやってたらJava辛くなった
  • どういったところが嬉しい?
    • Realmとの親和性良いよ
      • プロパティ名が取得できる
      • lazyで遅延取得が出来る
    • 拡張関数でUtilityクラス乱立防止
    • coroutineで簡単非同期処理
  • ハマリポイント
    • 無名くらいのインスタンス
    • DataBinding方法
      • @get:Bindableみたいな
    • 例外処理
      • 普通に囲めばOK
    • UIスレッド実行
      • coroutineビルダー
      • launchUI()を使う
    • coroutineのライフサイクル
      • onDestroyでキャンセルするには
      • async時に取得できる?
  • QA

フルKotlinでMastodonクライアントを作ってみて得られた知見のシェア。 ハマリポイントとかの紹介があって、これからKotlinを使う人には役立つと感じました。

質問の回答でもありましたが、TwitterよりMastodonクライアントの方が作るのが楽、というのはなかなか意外でした。

ちなみに関係ないですが、最近良く聞く「coroutine」を未だに理解していません。 Go言語とかでもよく聞きますし、今度ちゃんと調べねばと思います。(たぶん、Promiseとは違うんですよね?)

いまから使えるSpreadsheetView(pancake)

speakerdeck.com

  • 自己紹介
    • パンケーキの人
    • スプレッドシートは岸川さんが作ったやつ
    • iOSエンジニア
    • 東京にいるわけではないので今日はホテルに帰る
  • OSS
    • 公開後1,500スター
  • 作ったアプリ
  • 機能
    • ヘッダ固定
    • 無限スクロール
    • グリッド線とか枠線とか
    • UICollectionView like
  • サンプル付き
  • UICollectionView likeなAPIなので使いやすいかも?
  • セルのマージ機能
    • 5分刻みのセルを作ってみた
  • ほかのライブラリは?
    • ある
    • セルのマージ機能があるのはスプレッドシートだけ?
    • 標準だとリニアな探索のところ、2分探索が実装されている
  • QA
    • 結合されたセルのタップイベントはどうやって拾う?(インデックスとかどんな感じで?)
      • 現状だと左半分しか反応しない?(実装ミスかも)

岸川さんが開発されたSpreadsheetViewを使ってみたというお話。 github.com

私もiOSエンジニアなので噂は聞いていましたが、具体的にどういうことが出来るのか知らなかったので良かったです。 そしてセルの結合機能があるOSSは(おそらく)唯一なのですね。

しかしスター数1,490とは・・・凄まじいですね。

「Lottie」でお手軽アニメーション実装(shanonim)

speakerdeck.com

  • Lottie
    • 意外と知ってる人が多い
    • アニメーションのライブラリ
    • Adobe After Effectsで作ったJSONをアプリで読み込める
    • そのままアプリに組み込めちゃって楽ちん
    • iOS/Android/ReactNativeすべてに対応
  • AfterEffects
    • 映像分野ではメジャーなソフト
    • CM作成とかでも利用されているらしい
  • アプリに組み込む(Android
    • build.gradle
    • Activityはノータッチ
    • レイアウトXMLJSONを指定する
    • 複雑なアニメーションでもJSONを読み込むだけ
  • 利用ケース
    • ローディングとかアイコンとか
    • 画面全体とかは微妙かも
  • 導入までのハードル
  • LottieFiles.com
    • CCライセンスで公開されている
    • 見てるだけで楽しそう
  • まとめ
    • Lottie楽しい
    • アニメーションでUXをあげよう
  • QA
    • 画面全体には向かない?
      • アニメーションの作成コストが掛かるだけ
    • バイスサイズの対応は?
      • dpで指定すればそれに収まるようになる
      • SVGっぽい感じで、拡大してもぼやけないとのこと

Adobe After Effectsというツールで作成したアニメーションをJSONでエクスポートして、そのままアニメーション出来るLottieについての紹介。 airbnb.design

不勉強なものでAfter Effects自体知らなかったのですが、デザイナさんがそれを利用してアニメーションを作成し、 それを殆どゼロコストで導入できる(デザイナの意図が100%反映される)というのは便利だと思いました。

CCライセンスで公開されているLottiefiles.comは、たしかに見ているだけで楽しいですし、何かアイディアに繋がりそうな気がしました。 www.lottiefiles.com

Lightweight Dependency Injection Tips(Motoki Narita)

speakerdeck.com

  • 放送事故(放送終了)
    • (発表開始直後にディスプレイが消えてしまった)
  • 自己紹介
    • メルカリカウル
    • 本、CDとかに特化した姉妹アプリ
    • クラッシュレート1%を下回る
  • 今回DIを取り入れた
    • AppleでもDIのベストプラクティスをまとめている
    • Qiita記事にもまとめている
  • イケてない気がするところ
    • Segueで依存オブジェクトを渡す必要がある
  • “良い設計は誤った用法をコンパイルエラーにする"(ishikawa)
  • ルール
  • 経緯
    • アッテの開発のなかでそういう話になっった
  • 作り方
  • 作っていく中でリファクタリングを繰り返していった
  • まとめ
    • 良かったこと
      • インスタンス化の方法が統一される
      • 統一されることでDRY
      • 再利用が楽に
    • 良くなかったところ
      • Storyboardを使っているけれど画面遷移が見えない
  • 告知
    • iOSDC(今年は2.5日)

LightweightなDIを使うと良いかもよ、という話。 個人的には今日のLTの中で一番面白く感じた内容でした。

Lightweightというのは誇張ではなく、本当に最低限の仕組みであるにも関わらず、 そこに本質がきれいに表現されていると感じました。

時間の関係上リファクタリングの過程が見られなかったので、発表資料の公開が待ち遠しい限りです。

Protocol Buffers(TakuSemba)

  • 自己紹介
    • 最近ProtocolBufferを使うことがあった
    • CyberAgent, Inc.
  • Protocol Bufferとは
    • Google制のデータ通信の使用
    • JSONではなくバイナリで通信する
  • Quick Start
  • Proto fileの定義
  • スクエア制のツール
    • Javaファイルが書き出される
    • プロジェクトに追加する
  • Let’s 通信
    • dependenciesに追加
    • Retrofit
  • まとめ
    • メリット
      • データ量が少ないので早い
      • Proto fileで共通認識が取れる
    • デメリット

最近何かと話題に上がるProtocol Buffer の話。 やはりデバッグしづらかったり、API変更が面倒だというのは、どこでも共通認識のようです。

Proto fileで共通認識が取れる、という視点は今までなかったので勉強になりました。

LicensePlist(mono)

www.slideshare.net

  • 自己紹介
    • mono
  • LicensePlist
    • ライセンス管理を自動的にやってくれる
  • 今まで決定版がなかった
    • 決定版を目指して作った
    • SPMで管理
    • 手動で入れたものまで検出してくれる
  • 仕組み
    • LICENSEファイルをかき集めている
  • Cocoapods
    • plistを解析すればOK(ローカルにある)
    • Cartfile.resolvedから依存ライブラリのGitHubを見に行く
    • ライセンス取得APIGitHubから
  • plistの生成
    • PropertyListSerializationというものがある
    • 最初は自分で書いてしまったら真っ白になることも
    • YAMLファイルで柔軟性を担保
  • install
    • Homebrewに対応してます
  • 設定
    • Buildのpre-actionに設定するのがおすすめ
  • QA
    • 他の設定を生成したい場合は?
      • 出力形式を変更するだけなので要望があれば対応する(ViewControllerとか)

ライセンス管理自動化の決定版的ライブラリを作ったよ、という話。 その宣伝文句に違わず、CocoaPods、Fastlane、手動など、様々なケースに対応していてとても良さそうでした。

懇親会

窯焼きのピッツァ(!)

最後に

ポテチの参加は初めてだったのですが、多彩な発表が聞けてとても楽しかったです。 会場、飲み物、食べ物を提供してくださったRettyさん、主催者、発表者、の方々、本当にありがとうございました。 (もちろん懇親会で話してくださった方も)

ちなみに勉強会では結構メモるタイプなので、ブログまとめなんて楽勝だと思っていたのですが、 LTはテンポが非常に早くて、メモをしながら発表についていくのは思ったよりもハードでした(笑)

ではまたの機会に参加できることを楽しみにしつつ、締めたいと思います。

技術用語メモ

新しく知った技術用語とかをダンプするようの記事。

Capistrano

Rubyによる構成管理ツール。AnsibleのRuby版っぽいイメージ?

用語を知った場所:
Capistranoを使ってS3等からpull型デプロイするgemを書いた、ほか — Mobage Developers Blog

GCP

Google Cloud Platform。 いわゆるGoogleが提供してるクラウドサービス。

Kubernetes

複数のDockerコンテナを管理するツールで、Googleが開発を始めたもの。

Docker単体では実現できない以下のような機能を提供する。
オーケストレーション

  • 関連するコンテナのグルーピング
  • コンテナに振られるIPアドレスの管理
  • コンテナ間のネットワークルーティング

などなど

関連記事:
knowledge.sakura.ad.jp

GKE

Google Container Engine。
複数のDockerコンテナをKubernetesで管理するクラウドサービス。

GCPだとGoogle Cloud Platformと被るので、KubernetesのKを取ってGKEとなったらしい。

関連記事:
ブログをGKEでの運用に移行した | tsub's blog

セキュリティ

ソルト

憶測されるデータからハッシュ値を衝突させて元データを特定する、といった攻撃に対処するもの。

例えば、ハッシュ値が連番であると予想された場合、連番からハッシュ値を生成して一致するか確認することで総当りで元データが特定できてしまう。

それを避けるために元データに何らかの文字列を付与しておくことを「ソルト」という。 例えば、99xxyyzzとか元データ(今回は99)に対して特定の文字列(今回はxxyyzz)を付与する。

ソルトも当然ながら憶測されにくい文字列である必要がある。

関連記事:
speakerdeck.com