エンジニア仲間とブログを開設しました。 - ペンギン村 Tech Blog
1年半くらい前になるでしょうか、ペンギン村というSlackを作ってエンジニア仲間と情報交換をしていました。
人数も少しずつ増えてきて、なんか面白いことをやりたいね、ということで新たにブログを開設しました。
blog.penginmura.tech
とりあえず、最初の挨拶的な記事と、前から書きたいと思っていたKotlinの記事を書いてみました。
blog.penginmura.tech
blog.penginmura.tech
やはり一緒に何かに対して取り組むというのは、個人的に非常に楽しく感じると思う今日この頃です。
そのうち何かサービスを作っていきたい的な話もあるので、今からどうなるか楽しみにしています。
まぁ、こういったものは最初だけ気合が入ったものの途中から興味を失うということもあるので、この先どうなるかは分かりませんが。
といった感じで、新年最初のブログ記事でした。(久しぶりに本当にただのブログという感じ)
JJUG CCC 2017 Fall に参加してきた(いまさらまとめ)
さて、JJUG CCC 2017 Fallに参加してきました。
はい、2017/11/18に開催されたもので、すでに参加から1ヶ月以上が経っています。しかし、年内にやり残していたこととして記憶していたので軽くまとめたいと思います。
今回はKotlinの話を聞きたいと思ったのがキッカケで、Springなどの話も面白そうだと思ったので参加を決めました。懇親会も参加する予定だったのですが、体調を崩してしまって参加できなかったのは少し残念です。
ところでCCC
って何の略かと思ったら「Cross Community Conference」の略みたいですね。なんだかカッコいいです。
10年前のレガシーシステムをサーバサイドKotlinでフルリニューアルした話
- 自己紹介
- ベルセルク好き
- API部分をやった
- Kotlin x SpringBoot x (Vue.js)
- エンジニア3人で
- どうやって経営層を通したか?
- 最優先のIssueを見極めた
- 可能な限り数値化
- 複数案(メリット・デメリット)
- 自分でも客観的に見られるようになる
- プロトタイプで不確実性をコントロール
- 自分でも自身がつく
- 説得力につながる
- 技術選定
- なぜKotlin?
- 技術スタック
- Spring
- DOMA2
- swagger-codegen
- SpringFox
- 定義ファイルを生成してくれる
- SpringFox
- どこでもKotlin
- 勉強会的な
- 他社事例
- Retty
- CA
上層部に提案する際の進め方として「複数案を用意する」「実際に動くプロトタイプを作る」というのはやはり重要だと思いました。
JavaとKotlinの共存という面では、変化の少ないDBアクセス層部分はJavaで書くという選択は素晴らしいと思いました。あと、kotlin-springプラグインを利用することで、デフォルトでopen
にしてくれるという話を聞き、Kotlinにはそんな機能もあるのだと思いました。
swagger-codegenは使ったことが無いのですが、いろいろな勉強会でよく聞きますし、個人開発で使ってみたいと思いました。(こういうのって最初に始めるところが壁があるのですよね・・・便利だとは分かっていても)
ちなみにベルセルクは読んだことがないのですが、ちょっと興味がわきました。
Pivotal認定講師が徹底解説! Spring Bootの本当の理解ポイント
www.slideshare.net
- SpringBoot
- まずはSpringを理解せよ
- Spring
- CoCではない
- 設定ファイルはJavaコードで記述する
- 開発を始めるのが面倒
- Spring Bootは設定の塊
- 設定=Bean定義
- DIコンテナ
- Spring MVC
- CoCではない
- Spring Boot
- Beanの種類
- FWが利用するもの
- アプリケーションロジック(自分たちで書くもの)
- Spring Bootがやっていること
- FWが利用するBeanを事前に定義しておくだけ
- JavaConfigのかたまり
- AutoConfigurationクラスが大量にある
- アプリケーションロジックのBeanには何もない
- Springの知識が必須
- Springをかんたんに使えるようにしたのがSpringBoot
- application.properties
- FWのBeanの各設定値
- @ConfigurationProperties
- application.propertiesの設定値をBeanに反映するもの
- 起動するプロセス
- @SpringBootApplication
- いくつかのアノテーションの集まり
- @SpringBootApplication
- 定義するBeanの選別
- spring-boot-autoconfigure.jar
- すべてのBeanが定義されている
- 無駄なBeanをコンテナに登録しないようにする仕組みがある
- @ConditionalOnXxx
- 条件に合致した場合にそのBeanが定義される
- @ConditionalOnXxx
- spring-boot-autoconfigure.jar
- Beanの種類
- カスタマイズ方法(トラブル回避)
- @ConditionalOnXxx による芋づる式のトラブル
- @EnableXxxをあまり使わないほうが良い
- Spring Cloudとかでは使う必要もある
- 安全な方法
- application.properties
- BeanをDIで取得して設定変更(コンストラクタInjection)
- 補助的なBeanを定義する
- ThymeleafなどのBeanに拡張の仕組みが用意されている
- Dialectという形で用意
- Springの本
- Beanの丸写しはしないように(SpringBootの場合)
私は以前Seasar2を用いた開発を行ったことがあり、SpringもDIコンテナなんだなくらいにしか知らなかったのですが、この発表を聞いてSpringBootとSpringの関係がようやく理解できたような気がします。
SpringがCoCでなく設定を大量に記述する必要があること、そしてその負担を軽減するための設定ファイルの塊を生成してくれるのがSpringBootであるという理解で落ち着きました。
普段はSpringを使う機会がないのですが、今度Kotlinで触ってみようかと思っているので、その際にこの資料を見ながらSpringの基礎を固めたいなと思いました。
Spring Security にできること・できないこと
- どこが守られるのか、どこが守られないのか
- 使った実装 vs 使ってない実装
- Servletのフィルターを利用した実装
- SQLインジェクションとかは全く意味がない(管轄外)
- セッション管理の不備(セッションID)
- 推測
- 連番とか
- 推測できないランダム値を生成する
- Servletの話になるので管轄外
- 盗用
- セッションIDの固定化
- ログイン前後でセッションIDが変更されていない場合に起こる
- セッションIDを対象者にセットしておくことで、そのセッションIDでログインできる
- 対策:ログインしたらセッションIDを変える
- Spring SecurityはFormログインしていれば、自動的にやってくれる
- 推測
- XSS
- JavaScriptを入力・実行できちゃう問題
- 対策:エスケープする
- Spring Securityはサポートなし
- レンダリング部分の話なので
- CSRF
- HTTP ヘッダーインジェクション
- Clickジャッキング
- 見えないiframeを表示する
- 対策:
- X-Frame-Options
- 主要なブラウザはサポートしている
- Spring Security もサポート
- 権限
- ルーティングごとの適切なアクセス制御を設定する
Webセキュリティの復習になったような気がします。
そしてSpring Securityというものも初めて聞いて、Springは随分と巨大なFW群になったのだと感じました。ServletのFilter機能を利用している、なのでHTTPリクエスト前後で出来ることしか行えない、ということが重要であると思いました。
発表はデモを多く使用されていたので、普段イメージしにくい攻撃が理解しやすくてとても良かったです。
オレオレJVM言語を作ってみる(四則演算するだけだけど)
www.slideshare.net
ハッキリ言ってとても難しかったです・・・。
なんとなくぼんやりと全体のイメージが出来たような気がしますが、それも怪しいです。
新しいプログラミング言語の学び方 ~ HTTPサーバーを作って学ぶJava, Scala, Clojure ~
- 新しい言語を学ぶときはHTTPサーバを作ると良いよ、という話
- なぜ?
- よくあるやり方
- HelloWorld、書籍、TODOアプリ
- WebでTODOアプリ
- DBが必要になり
- MySQLWorkBench
- 画面表示は?
- HTTPサーバなら必要ない
- よくあるやり方
- HTTPサーバのやってること
- リクエストの待受
- パース
- 結果を返す
- Scala
- Clojure
- LISP
- 文法が少ない
- データとしてのコード
- 参考:http://boxofpapers.hatenablog.com/entry/simple_made_easy
- 並列性を考慮
- コンセプト
- 状態の扱い:Identity, State, Value
- シンプルさ
lein run
(らいにんげん?)
- LISP
- 作り始めるコツ
- 難しく考えなくても良いかも
- n年後にもう一度作り直すと成長を実感できる
- HTTP
- Socket=(IP+ポート)
- 流れ
- ServerSocketの初期化
- while
- accept
- input/output stream を取得
- inputからread、outputにwrite
- 正規表現
- リソースの開放
- 並行処理
- Java
- WorkerThread
- Socker, Input/OutputStream
- WorkerThread
- Scala
- Future
- 非同期に実行される
- ExecutionContext次第で実行方法は変わる
implicit
- スコープ内に宣言されていれば勝手に取ってくる
- Scalaでよく使われるテクニック
- 参考:http://gakuzzzz.github.io/slides/implicit_reintroduction/#1
- what/howの分離
- howが大きくなると意図が埋もれてしまうため
- Future
- Clojure
- go / thread / send / ...
- Java
- 文字列連結
- まとめ
- すでに知っているものとdiffを取ってみる
話の流れがスムーズで分かりやすく、聞いていて面白いセッションでした。
私も新しい言語を学ぶ時に、最近だとConsListは書くようにしているのですが、どうも物足りなく感じていたのでHTTPサーバを作ってみようかなとこのセッションを聞いて思いました。
Clojureは以前Lisp系の言語を学ぼうと思って2日間くらい勉強したのですが、それきりだったので今度また勉強してみようと思いました。
作り始める際に最初からがんばりすぎない(その言語の機能をフルに活用しようとしない)というのは、モチベーションというかやり方として大切だなと思いました。
感想
JJUGは初参加だったのですが、かなりの人数が参加されていてとても驚きました。
それゆえ、満員で参加できないセッションもあったのが残念ですが、まぁそれは仕方がないでしょう。
有益な発表がいろいろ聞けて、発表者および運営者の方には大変感謝です。
Quick/Nimbleで独自Matcherを自作して、テストコードの可読性を上げる
さて今年も終わりに近づいてきました。
この記事はモバイル 自動化 / 自動テスト Advent Calendar 2017の17日目の記事です。
実はアドベントカレンダーの参加は今回が初めてだったりするのですが、まぁそれはどうでも良いですよね。
Tl;Dr
Quick/Nimbleで、独自Macherを作成するとテストコードの可読性が上がるかも?
// 標準のMatcherを使用 it("use built-in matcher") { expect(person1.isTeen()).to(beTrue()) expect(person2.isTeen()).to(beFalse()) expect(person1.gender).to(equal(person2.gender)) expect(person1.gender).toNot(equal(person3.gender)) } // 独自のMatcherを使用 it("use custom matcher") { expect(person2).to(teen()) expect(person1).toNot(teen()) expect(person1).to(sameGender(person2)) expect(person1).toNot(sameGender(person3)) }
iOS Test Night
さて、iOS Test Night #6 - 1周年 - では、Quick/Nimbleのイケてないところを改善したい、といった内容で発表をさせていただきました。 speakerdeck.com
その中で「Matcher APIはコード補完が効きづらいのがイケてない」的な話をしました。
たしかにMatcher APIはコード補完が効きづらく、初心者にとっては学習コストが高いものです。しかし、Matcher APIが悪いかというとそうではなく、あえて柔軟に作られるように設計されています。
そこで今回は、独自のMatcherを作成する方法と、それによってテストコードがどのように変わるのか見ていきたいと思います。
Quick?
QuickはSwift製のBDDフレームワーク(+Matcher APIベースのAssertionライブラリ)です。
私の記憶では、Swiftがリリースされてから2日後くらいには公開されていた、かなり早くからあるテスティングフレームワークです。Ruby製のBDDフレームワークであるRSpecなどにインスパイアされていると、公式のREADMEで書かれています。
BDDフレームワークとは「振る舞い(Behavior)」に着目してテストコードを書こうという思想のテスティングフレームワークです。
歴史的には、先にTDDによる「テスト駆動」という「テストを先に書く」という思想を開発にもたらされました。
しかし、「テストを書くこと」が目的になるという悪い側面もあり、それを解決するために(テスト対象の)「振る舞い」に着目することで質の良いテストを書こう、ということでBDDが生まれたとかどうとか。(そんな話を聞いた覚えがあるような、くらいなので間違っているかも)
以下のようにテストコードが(DSLによって)構造化されるのが最大の特徴になっています。
class SampleTest: QuickSpec { override func spec() { describe("足し算") { context("1 + 1") { it("2") { expect(1 + 1).to(equal(2)) } } context("1 + 2") { it("3") { expect(1 + 2).to(equal(3)) } } } } }
よくありがちな単純な例ですが、テストが構造化されるのが見て取れるかと思います。
コード中に出てくる単語は、以下のような意味を持っています。
describe
:テストの概要説明context
:テストの条件it
:期待される振る舞い
このような形で、テストコード全体が構造化されるのがBDDフレームワークの特徴になっており、さまざまな言語でBDDフレームワークが作成されていますが、この見た目に関してはだいたい似たような感じになっています。
Nimble?
Quick/Nimble
とセットで呼ばれる事が多く、実際セットで使われることが多いため、あまり意識されることは多くない(ように思える)のですが、Nimbleは「Assertionライブラリー」という位置付けになっています。
QuickがBDDフレームワークとしてDSLを提供するのに対し、NimbleはXCTestでいうところのXCTAssertEqual
のような期待値と結果を比較して、テストの成否を判定する機能を提供しています。
さきほどのコード中にexpect(1 + 1).to(equal(2))
といったコードがありましたが、この部分はQuickではなくNimbleに用意されたAPIを利用しています。テストコードが自然な英文になるようなAPIが提供されており、「Matcher API」と呼ばれることが多いです。
Matcher APIのメリットは、テストコードが自然な英文になることで意図が分かりやすくなることと、失敗時のエラーメッセージが分かりやすいという点が挙げられます。
expect(1 + 1).to(equal(3)) // => expected to equal <3>, got <2>
この失敗時のエラーメッセージが分かりやすいというのは意外と重要で、プロダクトコードに何らかの変更を加えた時に既存のテストが失敗した場合は、その原因をできるだけ早く知りたいと思うはずです。失敗時のエラーメッセージが不親切だと、なぜテストが失敗したかの原因を調べるのに多大な時間を消費してしまいます。
これはミクロな視点で見た時は大した問題にならないように見えますが、マクロな視点で見ると結構重要だったりします。
CI(継続的インテグレーション)により自動テストが失敗した場合に、その原因がすぐに分からない場合は(他の作業との兼ね合いで)修正が後回しにされることが多いように感じます。それが繰り返されると、テストコードのメンテナンスがされなくなり、最後には捨てられるということも少なくありません。(実際に、私も以前関わったPJで目の当たりにしています)
Matcher APIの欠点
Matcher APIは以下を提供することで、前述したような問題への対処を試みています。
- テストコードの意図を明確にする
- テストが失敗したときの原因を明確にする
一方で、IDEによるコード補完との相性は悪く、初心者にとっては学習コストが高めです。
その対処として、
といった改善策を考えた、というのが冒頭のiOS Test Nightでの発表内容になります。(詳しくはスライドをご参照ください)
独自Matcherを自作する
ようやくタイトル回収までたどり着きました。
Matcher APIの他のメリットとして、独自のMatcherを作成することが出来るという点が挙げられます。つまり、Built-inのAPIで十分な可読性が得られなければ、自分で拡張することもできるという意味です。
今回は以下のPerson構造体に対して、「ティーンエイジャー(13〜19歳の間)であること」と「性別が同じであること」というMatcherを作成してみたいと思います。
struct Person { enum Gender { case male case female } let age: Int let gender: Gender func isTeen() -> Bool { return 13...19 ~= age } }
期待値を受け取らないMatcher - teen()
まずは「ティーンエイジャー(13〜19歳の間)であること」を確認するテストコードについてです。
標準のMatcherを利用したテストコードを見てみます。
let person1 = Person(age: 17, gender: .male) let person2 = Person(age: 20, gender: .male) describe("Person") { describe("is teen?") { it("use built-in matcher") { expect(person1.isTeen()).to(beTrue()) expect(person2.isTeen()).to(beFalse()) } } }
悪くありませんが、isTeen()
の呼び出し結果がtrue/false
であること、といった感じで少しだけ回りくどいテストコードのようにも見えます。
次に自作したteen()
というMacherを利用したコードを見てみます。
let person1 = Person(age: 17, gender: .male) let person2 = Person(age: 20, gender: .male) describe("Person") { describe("is teen?") { it("use custom matcher") { expect(person1).to(teen()) expect(person2).toNot(teen()) } } }
さきほどの標準APIに比べて、意図が分かりやすくなったのではないでしょうか?
以下がMatcherの実装です。
func teen() -> Predicate<Person> { return Predicate { (actualExpression: Expression<Person>) throws -> PredicateResult in let message = ExpectationMessage.expectedTo("teenager") if let actualValue = try actualExpression.evaluate() { return PredicateResult( bool: actualValue.isTeen(), message: message ) } else { return PredicateResult( status: .fail, message: message ) } } }
ゴチャゴチャしているように見えますが、だいたい決まりきったコードパターンになっているので、公式のREADMEに書かれたサンプルコードを真似すればわりと簡単に作成できます。(実際、内部的な実装までは把握していません)
beTrue()
のように期待値を受け取らないパターンは、このような感じのコードで実装することが出来ます。
期待値を受け取るMatcher - ()
次に「性別が同じであること」を確認するテストコードについてです。
同じように標準APIのコードを見てみます。
let person1 = Person(age: 17, gender: .male) let person2 = Person(age: 20, gender: .male) let person3 = Person(age: 15, gender: .female) describe("same gender") { it("use built-in matcher") { expect(person1.gender).to(equal(person2.gender)) expect(person1.gender).toNot(equal(person3.gender)) } }
やはり悪くはありませんが、視覚ノイズが多く、パット見で意図を読み取るのが難しくなっている印象を受けます。
次に自作したsameGender()
によるテストコードです。
let person1 = Person(age: 17, gender: .male) let person2 = Person(age: 20, gender: .male) let person3 = Person(age: 15, gender: .female) describe("same gender") { it("use custom matcher") { expect(person1).to(sameGender(person2)) expect(person1).toNot(sameGender(person3)) } }
先程の標準APIに比べ、はるかにテストの意図が分かりやすくなったのではないでしょうか?
sameGender()
の実装は以下のとおりです。
func sameGender(_ expectedValue: Person) -> Predicate<Person> { return Predicate { (actualExpression: Expression<Person>) throws -> PredicateResult in let message = ExpectationMessage.expectedActualValueTo("same gender <\(expectedValue)>") if let actualValue = try actualExpression.evaluate() { return PredicateResult( bool: actualValue.gender == expectedValue.gender, message: message ) } else { return PredicateResult( status: PredicateStatus.fail, message: message ) } } }
引数として期待結果expectedValue
を受け取るようにしているという違いはありますが、基本的には先程と同じようなコードになっています。
いつMatcherを作成すべきか?
これについて明確な答えはありません、おそらくプロジェクトによってマチマチかと思います。
独自Matcherを作成したほうが読みやすくなるからと言って、片っ端から独自Matcherを作成していたのでは、そちらのコードの記述量が多くなってしまって逆にコストが掛かるでしょう。
それにテストが失敗した時に、独自Matcherの不具合ではないかと疑いをかけたくなるケースもあるでしょう。そういう意味では独自Matcherもきちんとテストされるべきかもしれません。
しかしアプリケーションの中心となるドメインモデルがあり、独自Matcherを作成することでテストコードの可読性があげられるのであれば、独自Matcherを作成することを検討する価値はあるでしょう。
テストコードを負債にしないために
最近わたし自身が感じているのは、テストコードが失敗したときの原因が「ほぼ一瞬」で分からない場合、「面倒だからあとで調べよう」となるという気持ちのコンテキストスイッチの切り替えが心の中で起きるということです。
それは「実際に調べてみたら大した事がなかった」としても、「対応までの時間と(心理的な面も含めて)コストが掛かる」ということです。テストコードが負債になっていくのは、失敗したテストコードに対するチームメンバーの心理的ストレスではないかと思うわけです。
そういう意味で独自Matcherの作成は、適材適所で利用すれば価値があるのでは、と思ったりします。
終わり
最初は独自Matcherの作成という技術的な記事にするつもりだったのですが、なんだか途中からポエミーな感じになってしまいました。まぁ、年の瀬ですし、たまにはこういうのも良いでしょうか。
個人的に次の課題として、NimbleのMatcher APIまわりの実装の仕組みをきちんと理解したいと思うので、今度コードリーディングしてみたいなと思ったりします。
そんなわけでモバイル 自動化 / 自動テスト Advent Calendar 2017の17日目の記事でした。
皆様良いお年を。(ちょっと早い?)
勉強会:Bonfire iOS #3 に参加してきた。
さて、気づけばどうやら久しぶりのブログ更新のようです。
今回は、Bonfire iOS #3 というヤフーが開催しているIOS系の勉強会に参加してきました。 yj-meetup.connpass.com
第3回の今回のテーマは「品質」ということで、様々な会社・プロダクトに携わっている方たちが品質について発表してくださいました。
iOSの勉強会というと、開発Tipsやテストといった技術的なテーマが多い中、面白いテーマだなぁと思いました。
いつものように箇条書きメモ+感想みたいな感じで順番に書いていきたいと思います。 スライドがアップされたら更新していきたいと思います。
Yahoo!天気アプリを少人数でも支えられた理由
- 自己紹介
- iOS歴3年
- Swift
- 大阪から
- Y天気アプリ
- 利用者あわせて600万
- 天候があれると1000万
- 統合ランキングでも1位をなんども
- 体制
- 企画
- メンバーと新機能を決める
- PMもエンジニア経験ある
- 企画が実装も踏まえて話を進めてくれる
- Sckethでエンジニアがプロと
- 職種の垣根をこえて進められる
- 開発フェーズ
- 最初から実機で進めている
- シミュレータでは感じられない操作感などがわかる
- デザイナーに見てもらうときも、いろいろな実機をもっていく
- ヘルプデスクから端末を借りられる
- テストフェーズ
- 天気アプリならでは
- 天気情報を見せるのがメイン
- 入力などはないのでそのあたりのセキュリティなどの考慮はあまりない
- プラットフォームが整っている
- 生活の一部
- 毎日起動されるアプリなので、見た目の品質が重要
- ユーザは細かいことでも気になる
- コンテンツの品質
- 災害発生時の動き
- 8面モニタで情報収集をしている
- 災害発生時にすぐに分かるように
- 8面モニタで情報収集をしている
- サービスマネージャが天気予報士の資格を持ってる
- 予想しながら動くことも
- アプリチームは?
- ユーザが必要そうな情報は発信
- 手動で通知をうって、ユーザに知らせる
- チャット上で通知の文言を相談する
- 事実を提供する
- 災害時
- 一部はWebViewなのでデザイナが更新できる
- 災害が落ち着いてから情報が十分だったか振り返り
- ピンチのときにユーザを助けてこそ会社の信頼につながる
- 災害発生時の動き
- まとめ
- 少人数PJを支える強力な社内システム
- 見た目に徹底
- 他
- MixLeap
- 大阪2拠点になります
- 毎週イベントを開催している
- フォロー歓迎(Twitterアカウント)
- MixLeap
私も普段から利用している「Y!天気」アプリの発表でした。
まず、iOS/Androidエンジニアが1名ずつという点に驚きました。そういった少人数でも品質を保つ大勢や仕組みが非常に参考になりました。
参考になることばかりだったのですが、あえてピックアップするとすれば以下が特に参考になりました。
- 前バージョンからのコード差分を見る
- 毎日起動されるアプリなので、細かいUIについても拘る
- サービスマネージャが天気予報士の資格を持っている
当たり前な品質を支える様々な仕組みと、天気というサービスに特化した品質の考え方が取り入れられていて、とても戦略的にサービスを開発・運用しているのだと強く感じました。
iOS アプリエラー監視のための設計と効果
- 自己紹介
- 開発速度を2倍にした
- 趣味はTODO
- エラー監視とは?
- アプリで発生したエラーをサーバに送る
- クラッシュレポート
- Crashlyticsなど
- クラッシュ以外のエラーも監視できる
- 内部状態の不整合とかも
- エラー監視の特性
- 広範なバグを検知
- 発見が遅い
- バグが埋め込まれてからの時間が短いほうが嬉しい
- 特殊ケースのバグは発見が遅くなる
- 下から2つ目
- 最後の砦
- ユーザからの問い合わせはあるいみNG
- 理想のバグ検知
- ダメ検知
- 発見までの時間が長くなる
- エラー監視は特殊なバグを検知する手段
- それ以外はそれより前のフェーズで見つけるべき
- エラーレポーターをカスタマイズ
- NSErrorではなくSwiftのErrorで送信できるように
- 発生元のオブジェクトを渡す
- DEBUGと本番を分ける
- DEBUGでも送信したほうがベター
- 区別できれば良いのではないか?
- NSErrorへの変換
- domain/codeで設定される
- 発生元をreporterとしてdomainに含める
- エラーメッセージを含めてはいけない
- 同じ不具合が別のバグとして分類されてしまう
- 実際に組み込む
- ハードコード
- 単一責務原則に違反する
- 単体テストでエラーレポートが送信されてしまう
isTest
フラグ
- Observerパターン
- エラーReporterを監視者として、エラーが発生したら送信
- テストの時にはエラーレポーターを使わない
- Observerパターンを使える場所は限られる
- Modelはだいたい監視できる作りになっているはず
- RxのObservableを使っている
- エラー監視にはObserverパターンが適している
- ハードコード
- 困ったケース
- 結果
- ユーザの手元で発生しているバグの種類や規模を把握できるようになった
- 重要度のジャッジが出来るようになった
- ユーザの手元では予想外のエラーが起こっていることに気づく
- 特定のキャリア回線で発生する不具合など
- Sandboxのレシートじゃないと再現しないとか
- 副作用
- テスターの動作確認中にエラーレポートが飛んでくる
- ユーザの手元で発生しているバグの種類や規模を把握できるようになった
- まとめ
- エラー監視で、テスターが発見できない不具合が発見できる
- 宣伝
- ランチ募集
モバイルアプリの開発において、避けては通れないエラー監視をどのように扱うか、またどのように設計したら良いかという発表でした。
Twitterのタイムラインでも話題になっていましたが、エラーの種類とそれがどこで発見されるべきかという図がとても分かりやすかったです。こういったことは開発が忙しくなると特に忘れがちなので、こういった図にまとめられているととても良いと思いました。(チームメンバーが見える位置に貼っておくというのもありかと思いました)
そしてエラー監視の設計についてはObserverパターンを利用すると良い、という話が後半でした。Observerパターンを採用することで、単一責務の原則を守ることが出来て、かつ不要なときは観測者(Observer)を外せば良い、という考え方はよくできているなぁと思いました。
あと、エラーレポートに詳細なメッセージを含めない、DEBUG環境でも区別できるようにした上で送信してしまう、というのも参考になりました。(私が以前関わっていたiOSプロジェクトでは、DEBUG時は送信しない設定にしていました)
スタートアップでのQA
- 自己紹介
- QA?
- 会社や組織によってまちまち
- 入社時の肩書として、QAエンジニアを選んだ
- プロダクトの品質を広範囲でサポートしたい
- テストは品質保証の一手段
- 2年間でやったこと
- 価値の高いテストに集中する
- テストに限られるリソースは限られている
- 関係者を巻き込む
- セールス・サポート:おさわり会
- E2Eテストは同じリポジトリで管理
- QAエンジニア以外でもテストコードをかけるように
- 自動化
- 時間ができたら自動化に取り組む
- テスト・デプロイの自動化
- 開発・運用の持続可能性を高める
- TORETAはプロダクトのライフサイクルが長い
- 5年・10年、それ以上も?
- ドキュメント
- 書くのもメンテするのもかなりのコスト
- 書きすぎないを意識(問い合わせがあったら書く、くらいの感覚)
- 手動テストケースを追加した理由を残す
- 長く時間が経つと、なぜ追加したのかわからなくなることも
- Markdownで書いて履歴として管理する
- 長くプロダクトを育てていくために
- サポート運用の課題を技術で解決する
- サポートの意見を製品に活かす
- サポートチーム、アカウント管理チームと週1ミーティング
- お知らせ機能
- 問い合わせ番号
- 設定画面の文言改善
- まとめ
- スタートアップは総力戦(みんなで協力する)
- 顧客のことをよく知る
- 価値が高いことに集中する
- プロダクトの問題をプロダクトだけで改善しない
- プロダクト品質 x サポート品質
- お隣さんとはアイディアが眠っている
飲食店向けのiPadで予約管理できるサービスにおいて、QAエンジニアとしてどう関わったかという発表でした。QAエンジニア歴10年ということで、参考になる話ばかりでした。
個人的には、顧客やプロダクト、サービスの性質(ライフサイクルが長い、B2B)を考えた上での取り組みが行われていることが、とても素晴らしいと感じました。とくに「顧客のことをよく知る」というのは品質を考えていく上でとても大切なことだとあらためて思いました。
ちなみにテストケースをMarkdownでバージョン管理するというやり方は、以前取り組んだものの失敗した経験があるので、機会があればもう一度挑戦してみたいなと思いました。
QA組織とiOSのテスト
- 自己紹介
- LINE株式会社
- サービスQAチーム
- LINEファミリーアプリを担当
- QAエンジニア歴9年
- 社内インタビュー
- QAエンジニアのロール
- QA?
- テスト管理全般をする
- 上流からどういうテストが必要可考えて、プロダクトの品質を評価
- SET
- テスト自動化
- Tester
- 手動テスト
- QAエンジニアに必要なスキル
- 幅広いスキルセットが必要
- チームにQAとしてアサイン
- 静的テスト
- インスペクション(仕様レビュー)
- 欠陥の防止
- 動的テスト
- ブラックボックステストとか
- 欠陥の摘出
- QA?
- 品質評価の考え方
- 取り組み
- テストケースの見える化
- テスト実行結果
- テストケースは誰でも見えるように
- テスト結果とBugを紐付ける
- どのテストによってBugが生まれたか開発者がわかりやすい
- グレーボックステストのアプローチ
- iOS固有のプラットフォーム
- テストしている側がプラットフォームを理解していない
- テスターもヒューマンインターフェースガイドラインを読む
QA組織としてどのようにプロダクトの品質を判定、リリースしているかについての発表でした。
BTSなどのメトリクスをきちんと測った上で、QCDとのバランスを考えた上でリリース判定しているというのが非常に良いと思いました。
私は以前とあるプロジェクトで開発していた時にQA組織がメトリクスを測っていたのですが、とてもレアケースな不具合が(一般的に想定される利用ケースではまず発生しないようなもの)多くあったことを理由に品質が不十分であると判定された経験がありメトリクスについては懐疑的でした。(QA組織はきちんと仕事をしてくださった、とも言えますが)
今回の発表ではメトリクスを測った上で、それだけを正解(あるいは正義)にしていないのが個人的にはとても好印象でした。
あと品質の見える化を行うというのは、とても良い試みであると感じました。
SmartNewsアプリの品質
SmartNewsアプリの品質への考え方や取り組みについて、2名からの発表でした。
前半はSmartNewsアプリの品質についての取り組みについての発表でした。
SmartNewsはアプリ実装について結構なこだわりを持っているとのことで、なめらかなページめくりや良質な見た目など、UI/UXにとてもこだわっているとのことでした。このあたりは求められる(あるいは目指す)品質が、プロダクトやサービスなどによって全く異なるということをあらためて思い出させてくれました。
後半はビルドサーバやUIテストの実装についての発表でした。
ビルドサーバは2台構成にしていて、新しいものを導入する時には1台のマシンに導入した上で、問題がなければ新しいマシンにも導入する、といったビルド環境を壊さないようにする取り組みは参考になりました。
XCUITestについては、enumを名前空間(ネームスペース)として利用する方法は良いなと思いました。静的型付けでIDE上でコード補完が効くSwiftという言語を有効活用した、良い方法だと思いました。
ところでSmartNewsは「世界中の良質な情報を必要な人に送り届ける」というミッション(あるいはビジョン?)を持っているそうです。
”船を作りたければ、海へのあこがれを説け”という有名な言葉がありますが、プロダクトやサービスがこうした向かうべき方向についての軸を持っているのは重要だとあらためて思いました。
短期大規模開発の品質とスピードの両立について in ライブコマース
- 自己紹介
- 開発工数3ヶ月で無事故でライブコマースを乗り切った
- ライブコマース?
- アプリをタップするとライブ動画が配信される
- いいね、コメントなどを複数のアプリで共有する
- ライブ配信
- RTMP(RealTimeMessagingProtocol)
- NGINX
- CDN
- 視聴アプリ
- HLS
- Appleが企画したライブストリーミングの企画
- キャッシュとかもできる
- やることいっぱい
- デモアプリのメリット
- 完成のイメージを固められた
- 実現への自信が持てた
- 社内での説得力がます
- 有識者とのコミュニケーションもできた
- コードを流用できる
- 実際に本番コードに組み込んで流用
- 簡易動作確認環境
- 問題の切り分けに繋がった
- 品質・スピードを上げることができた
- テスト
- 振り返り
- Good
- ミニマム開発から広げることができた
- 社内から知見のある人を見つけることができた
- 精度の高いテストができた
- Bad
- 省いたところはある
- Good
ライブコマースという、アプリからライブ動画を見れて、そこでの「いいね」やコメントなどを複数アプリ感で共有する機能の開発を短期間で行った際の取り組みについての発表でした。
よく言われることですが、実際に動く簡易版の実装を行うことはとても大切、かつ効果的だとあらためて思いました。特に自信への繋がりや、有識者とのコミュニケーションに繋がったのは、とても良いと思いました。
あとは社内で利用者を集めて、本番同等の環境でテストを行うという取り組みはとても良いと思いました。やはり開発時には気づかない不具合も出てくるので、品質を上げるためにはそうした取組は必要だと思いました。
全体を通して、とにかく戦略的に開発を行ったのだという空気を強く感じました。
懇親会
お寿司を頂きました、美味しかったです!
感想
あまり他のiOS勉強会では話題に上がらない「品質」というテーマで、バラエティに富んだ発表を数多く聞くことが出来てとても有意義な勉強会でした。
私があらためて思ったのは、プロダクトやサービスによって品質の考え方は異なるということでした。画一した「品質」というものは存在せず、品質の考え方については結局自分たちで考え抜かなければならない、ということです。
それを実現する上で、様々なプロダクトやサービスにおける実際の取組みが聞ける、というのはとても良いことだと思いました。(おそらく発表者の方々も、他の発表で得るものがあったのではないかと思います)
勉強会の企画・運営をしてくださった方々にお礼申し上げます。
蛇足
久しぶりのブログのせいか、なんだか文章が稚拙な気もしますがご容赦を。
Androidで利用されるGradleバージョンの確認方法
AndroidでGradleのバージョンと言った場合、以下の2種類がある。
Gradle本体
Gradle本体のバージョンは、File > Project Structure > Project
から確認できる。
利用可能なバージョンは以下のURLから確認可能。 https://services.gradle.org/distributions/
gradle/wrapper/gradle-wrapper.properties
のdistributionUrl
を変更することで、新しいバージョンの利用が可能。(gradlew
がラッパーになっており、自動的に記載されたバージョンがダウンロードされる仕組みになっている)
#Mon Apr 17 18:32:32 JST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip
例えば上記のように指定して、./gradlew build
すると自動的にダウンロードされてbuild
タスクが実行される。
$ ./gradlew build Downloading https://services.gradle.org/distributions/gradle-3.5.1-all.zip ...
$ ./gradlew --version ------------------------------------------------------------ Gradle 3.5.1 ------------------------------------------------------------ Build time: 2017-06-16 14:36:27 UTC Revision: d4c3bb4eac74bd0a3c70a0d213709e484193e251 Groovy: 2.4.10 Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM: 1.8.0_121 (Oracle Corporation 25.121-b13) OS: Mac OS X 10.12.6 x86_64
Android Plugin for Gradle
GradleのPluginとして実装されているもの。
トップレベルのbuild.gradle
に利用するバージョンが書かれている。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
利用可能なバージョンは以下から確認できる。(Gradle本体の必須バージョンも書かれている) https://developer.android.com/studio/releases/gradle-plugin.html
Gradle本体のケースと同様にファイルを書き換えて、Android Studio上からSyncすればOK。
参考URL
platform-tools について復習
なんか微妙に理解が怪しくなったので復習。
なに?
adb
とかfastboot
といったコマンドが含まれるツール群。
インストール
Android Studio の SDK Manager からインストール・アップデートできる。
最近は SDK Manager を利用せずとも単独でダウンロードできるらしい。 https://developer.android.com/studio/releases/platform-tools.html
含まれている主なコマンド
adb
android debug bridge
の略。
apkをインストールしたりデバッグしたりまぁいろんなことに使う。
fastboot
- Fastbootモードという、PCでいうところのBIOS画面のようなものがある
- 端末がそのFastbootモードで起動していれば、
fastboot
コマンドで操作することが出来る adb reboot bootloader
コマンドで、再起動後にfastbootモードで立ち上がる- フラッシュメモリへの書き込みや、フラッシュメモリ上のパーティションの管理などが行える
- カスタムリカバリの書き込みを行うことも出来る
参考URL
https://jagadgetaholic.blogspot.jp/2015/12/fastboot-command.html http://news.mynavi.jp/column/androidnow/043/
iOSDC JAPAN 2017 に CfP を出してみた
iOSDC JAPAN 2017 に CfP を 3本出しました。 iosdc.jp
”当たらなければどうということもない”なんて名セリフもありますが、たしかに当たらなければ発表できません。 (悲しいけどこれ抽選なのよね)
なのでせっかくなのでシェアしたいと思います。 もし「これ聞きたいかも」と思うものがあれば、リンク先のページでブックマークやらTweetしていただけるとです。
実践テスト駆動開発 in iOS 15分 or 30分
TDD(テスト駆動開発)をご存知の方も多いかと思いますが、iOSではあまりテスト駆動開発の適用例を聞かない気がしています。 おそらくその理由の一つとして「UIが頻繁に変わるから向いてない」ということなのでしょうが、果たして本当でしょうか?
iOSにおけるUIテスティングは確実に進化しています。
本セッションではライブコーディングを取り入れながら、 実際にどのようにテスト駆動開発を適用していけるかをステップ by ステップで紹介したいと思っています。
UIテストの実行時間の短縮に挑戦する(LT)
UIテストを作成することで、リグレッションテスト(回帰テスト)の自動化といった恩恵を受けられるようになります。
しかし、往々にしてUIテストは実行時間がネックになります。 個人的な意見ですが、”実行に時間がかかる”というのは見た目以上のコストがかかっており、実際に掛かった時間以上のものを奪うと思っています。 (モチベーション、集中力低下によるパフォーマンスの低下、etc)
本セッションでは、UIテストの実行時間をどこまで短縮できるか挑戦した結果を発表したいと思います。 それによって、実際の開発にUIテストを導入する障壁を少しでも低くすることができればと思っています。
Swiftzで学ぶ関数型プログラミング
ここ数年で関数型プログラミングはかなり注目され始めています。
Swiftを作る際には関数型言語Haskellが参考にした言語の一つとして紹介されていますし、 実際、Swiftは関数型プログラミングをパラダイムとしてサポートしています。
しかしながら、関数型プログラミングはなかなかとっつきづらく難しいテーマであるのも事実です。
本セッションではSwiftでの関数型プログラミングをサポートするライブラリである「Swiftz」を用いつつ、 関数型プログラミングとはどういうものかという入門的なお話をできればと思っています。
最後に
まぁそんな感じです。よろしくお願いします。