Yabu.log

ITなどの雑記

テストのためだけのコード変更は許されるのか?

レガシーコード改善ガイドに以下のような一節がありました。

私はテストが簡単に書けるなら、変数をpublicにすることでカプセル化が壊れても通常は気にしません。

私はEffective Javaに強く影響を受けているのでメンバを書くときは極力公開性を最小にコーディングする。 しかし困るのはユニットテストのときで、privateなメンバのテストはリフレクションを使ってテストコードからアクセスしていた。

可変性*1・公開性*2を最小にする、というこだわりを持っているので上記の引用の記述には少し驚いた。

そもそもテストコード内でのアクセス出来ないメンバはどう対処するのが最適なのか、少し調べてみた。

https://qa.atmarkit.co.jp/q/2784

短くまとめると、プライベートなメソッドのテストを書く必要は 無い と考えています。ほとんどのプライベートメソッドはパブリックメソッド経由でテストできるからです。プライベートメソッドは実装の詳細であり、自動テストのターゲットとなる「外部から見た振る舞い」ではありません。

こちらの方*3の意見は非常に説得力がある。 確かにブラックボックステストとしてユニットテストを作成するなら、privateメソッドのテストは書く必要がない。

一方でこの方はレガシーにも触れている。

レガシーコード(テストコードの無いコード)に対する「仕様化テスト(Characterization Test)」を書いているような状況では、リフレクションは唯一の、かつ強力な手段になります。プライベートメソッドにテストを書くことのデメリットを理解しつつ、黒魔術の強力さを堪能しましょう。

機能追加の際に、理想的なテストを書いてしまうと、既存バグが発見され、そちらの対応に追われるかもしれない。 バグ修正よりも現在の変更作業を優先するために、一旦既存バグを含めた現在の挙動を保護するテストを作成する。*4

ほぼ全てのレガシーシステムでは、「システムがどのようにうごくべきか」よりも、「実際にどのように動いているか」のほうが重要です。*5

仕様化テストはレガシーコードに対処し始めた初期段階のプロセスといえるかもしれない。

調べた知見を自分なりにまとめると

まともにやっている新規開発*6ではprivateメソッドのテストなんて書く必要はないけど、 設計が破綻しているレガシーコードに絡んだsingleton*7などはテストの観点から見ると有害なので、公開性をどれくらい壊すか、というところのトレードオフを考えながらコード変更やリフレクションという黒魔術を使おう、ということになる。

調べながら・考えながら読んでいるので読むペースは遅いが、どんどん内容が面白くなってきた

参考:レガシーコード改善ガイド 第9章

*1:Effective Java項目15:可変性を最小限にする

*2:Effective Java項目13:クラスとメンバーへのアクセス可能性を最小限にする

*3:ユーザー名を見たらt_wadaさんだった…

*4:もちろんこれはゴールではない。既存バグの修正よりも、機能追加を優先したというだけであり、既存バグは別に対処しなければならない。

*5:レガシーコード改善ガイド13.1仕様化テスト

*6:新規開発のすべてがまとも、というわけではない

*7:文中ではsingletonのコンストラクタの公開性をprivate→protectedに変更している例が挙げられている

はてなブログを1ヶ月使ってみての感想

はてなブログを書き始めてから多分1ヶ月位たったので適当に使い心地でも書いてみる

いいところ

Markdownで書ける

これが一番重要。もうね、手打ちでタグ書いたり、セルの幅揃えたりするのに消耗したくないんだよ。

意外と簡単

なんかはてなのサービスってごちゃごちゃしてて難しそうな印象があったけど はてなブログはUIも洗練されてて使いやすい。

Qiitaと違ってブログは内容にあまり気を使わなくて良いのが楽。

注釈がめちゃくちゃ書きやすい!!!!

ブログ本文((注釈内容))

こんな感じでかなり手軽に注釈がかけちゃうんです。 この記法考えた人凄い。Markdownにも標準化団体みたいなのできたら 絶対これは入れて欲しい。*1

 わるいところ

はてなキーワードとかいうやつが邪魔

一応課金すれば消せるらしいけど、そもそもこれいるの?

*1:多分今って互換性のない方言がボコボコ生まれてるフェーズなんかな?

わけわからんコードにはとりあえず影響スケッチ。

影響スケッチとは?

レガシーコード改善ガイドに掲載されている、影響を把握するための方法です。

影響はどのように伝搬するか

影響は

  1. 呼び出し側によって使われる戻り値
  2. パラメータとして渡されるオブジェクトの変更
  3. グローバルスコープのデータの変更

によって伝搬します。

影響スケッチの書き方

ただ影響の伝搬を線で結ぶだけです。変数だけでなく、メソッドも結びます。

例:直したメソッドがグローバル変数を書き換えていた→そのグローバル変数を参照している箇所には全て修正の影響が伝搬してしまっている(涙)*1*2

レガシーコード改善ガイドの例では変数もメソッドも同じように丸で囲っていてわかりにくかったので、メソッドは()をつけるなどの工夫が必要でしょう。*3

影響スケッチは何に役立つのか。

1.テスト箇所の把握

まだテストコードが十分に整備されていない時は、変更を入れたコード以外にどこまでテストコードを準備する必要があるのか、という把握のために使える。

2.リファクタリング

本書の中の例では、変数の取得方法をgetterメソッドに統一することで影響の重複を排除していた。*4

感想

なぜ影響スケッチが必要になるかというと、そもそも変数に必要以上に広いスコープや可変性を持たせているからであって、 きちんと構造を持っているコードなら影響スケッチはシンプルになるし、そもそも影響スケッチを書くまでもないかもしれない。

レガシーコード改善ガイドは自動テストが導入されていることを前提に話を進めているので、そういう現場で働いていないと役立たないかもしれない。 でも調査や分析のためのテクニック、精神論などはテストを自動化していなくても役に立つと思う

今回紹介した影響スケッチもそんな役立つ技術の一つだと思う。

参考:レガシーコード改善ガイド第11章 変更する必要がありますが、どのメソッドをテストすればよいのでしょうか?

*1:図は書くのがめんどくさいのでなんとなくイメージしてください。。。

*2:スコープの広い変数に影響与えたあとにはきちんと調査してください

*3:別にこの本にケチを付けているわけじゃないよ。アメリカ人は変数は名詞、メソッドは動詞みたいなことをちゃんと徹底できるから別に俺が書いてる工夫なんてしなくて良いんだよ。ブツブツ…

*4:参考:11.6影響スケッチの単純化

Effective Java 3rd予約開始!

日本語版翻訳者の柴田さんのブログで知りました。

yshibata.blog.so-net.ne.jp

アマゾンの紹介を見る限り7~9も扱うらしい。*1 2ndはjava 6までの内容だったので少し古い感じがあった。

https://www.amazon.co.jp/Effective-Java-3rd-Joshua-Bloch/dp/0134685997

今から英語鍛えようかな

*1:なんでリリースしてない9が書けるんだろう?

仕様化テストについて

仕様化テストとは何か

コードから起こした仕様を検証するテストのこと。 大事なのは理想的な仕様を追い求めるのではなく、「現在のコードはこのように動いている」点を明らかにすること。

何のために行うか

機能追加の際に、理想的なテストを書いてしまうと、既存バグが発見され、そちらの対応に追われるかもしれない。 バグ修正よりも現在の変更作業を優先するために、一旦既存バグを含めた現在の挙動を保護するテストを作成する。*1

トレードオフ

機能追加 vs 品質

既存バグを直さずにシステムに機能追加が出来るというメリットがあるが、システム自体の品質は良くなっていないし、 作成した仕様化テストも最終的には理想的な仕様をブラックボックステストで網羅できるようなテストコードで置き換えられる必要がある。

ほぼ全てのレガシーシステムでは、「システムがどのようにうごくべきか」よりも、「実際にどのように動いているか」のほうが重要です。*2

仕様化テストはレガシーコードに対処し始めた初期段階のプロセスといえるかもしれない。

*1:もちろんこれはゴールではない。既存バグの修正よりも、機能追加を優先したというだけであり、既存バグは別に対処しなければならない。

*2:レガシーコード改善ガイド13.1仕様化テスト

SSIDのANY接続拒否(ステルスモード)はセキュリティ強度を下げる?

長らく、自宅のWifiをステルスモードにして使っていたが、2〜3年前からiPhoneが自動接続しなくなった。手動で接続すればつながるのだが、毎度ルーターSSIDとパスワードを入れるのは面倒だ。だがなぜか、パスワード無しで接続→失敗→数秒後接続される、という方法で繋げていたので、パスワード無し接続でしのいでいた。

流石に毎度手動設定は面倒で、たまにwifiにつなぎ忘れて通信料の多いアクセス等をしてしまうので、なんとかならないのか?と調べてみたら、どうやらAppleはアクセスポイントのステルスモードを推奨していないようだ。

https://discussionsjapan.apple.com/thread/10177615?start=0&tstart=0

また詳しそうなサイトの解説を見る限り

https://the01.jp/p000137/

以下のような理由から推奨していないと勝手に推測してみる

自動接続設定時の電力消費

any接続許可(非ステルスモード)の場合、ビーコン信号はアクセスポイント側が発信する。 any接続非許可(ステルスモード)の場合はクライアント側が定期的にアクセスポイントを探すパケットを周囲にブロードキャストする。非接続状態の場合、クライアント側が無駄にアクセスポイントを探し続けてしまい、無駄な電力消費となってしまう。

自動接続設定時のセキュリティ

ステルスモードのアクセスポイントに対して自動接続を設定している場合、非接続状態のクライントは周囲にアクセスポイントを探すパケットを投げ続ける。偽のアクセスポイントを立てて、クライアント側の接続要求のパケットを受信すれば、WEPでなくても容易にパスワードが解析できる

他情報

手元にある2016年情報セキュリティスペシャリストの対策本に関連する記載がある。

端末側にSSIDを設定していなくても(ANYと設定していると)接続が出来てしまいます。こちらもセキュリティ確保の観点から考えればANY接続を拒否する設定(ANYプローブ応答の禁止設定)にすべきでしょう。なお、こうした隠蔽を実施したとしてもSSIDは平文でやり取りされます。したがって、その通信を傍受されると、すぐに判明してしまうので、セキュリティ対策にはなりません。

推奨しているのかしていないのか、イマイチわからない。

接続が出来てしまいます。

この一文の意味がわからない

strategic choice閉鎖か?

http://d.hatena.ne.jp/asakichy/

昔からよく見ていたサイトですが、非公開設定になってしまっている。書籍化した影響なのかどうかは分からないが、readable codeもeffective javaもこのサイトがきっかけで読んだので閉鎖だと寂しい。