home ホーム search 検索 -  login ログイン  | help ヘルプ

find 検索

11 - 20 / 1297    [|<]  [|<]  [<]  1  2  3  4  5  6  7  8  9  10   [>]  [>|][>|]
タイトル/名前 更新者 更新日
技術/HTTP/URLエンコードで 0x20(スペース) を "+" にすべきか "%20" にすべきか msakamoto-sf 2017-11-19 16:15:33
技術/OSSライセンス/MITとBSD 2-clause の違い msakamoto-sf 2017-10-21 21:23:00
日記/2017/10/09/MSYS2,MinGW64,Cygwinの違い msakamoto-sf 2017-10-09 21:52:13
技術/Security/testssl.sh msakamoto-sf 2017-10-07 17:33:53
技術/Chrome/SeleniumIDE, Selenium Builder, その他E2Eテスト用のChrome拡張について(2015-04時点) msakamoto-sf 2017-10-07 13:53:25
技術/Chrome/お気に入りChrome拡張のメモ msakamoto-sf 2017-10-07 13:49:57
技術/Security/Burp/リクエスト,レスポンスの文字化け対策参考メモ msakamoto-sf 2017-10-07 13:37:43
Java/JMXのCUIツール参考メモ msakamoto-sf 2017-10-07 13:19:15
Java/JVMオプションとデフォルト値の一覧取得(-XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -XX:+AggressiveOpts) msakamoto-sf 2017-10-07 12:30:33
日記/2017/10/05/SingletonのGoodパターン、Badパターン msakamoto-sf 2017-10-06 00:37:20
ソート項目 / ソート順     1ページ 件ずつ表示

技術/HTTP/URLエンコードで 0x20(スペース) を "+" にすべきか "%20" にすべきか  

所有者: msakamoto-sf    作成日: 2013-03-23 22:18:13
カテゴリ: HTML HTTP ネットワーク 

※時間がないとか、だらだらとRFCの解説を読んでる暇が無い方は、末尾のまとめ部分だけ目を通していただければ十分かと。

URLのpath中やquery中、POSTリクエストボディ中で、0x20のスペースを、"+"に変換するのが「正しい」のか、"%20"にするのが「正しい」のか、わからなくなってきたのでちょっと調べてみました。
ただしRFCの全文を熟読してるわけではないので、言い回しや表現はもとより理解そのものが間違ってる可能性もあるので、話半分程度に参考にしてください。

"+"を使うべきか、"%20"を使うべきか、よく迷う箇所:

  • URLのパス中
  • URLのクエリ中
  • "application/x-www-form-urlencoded" 形式中
    • URLのクエリ中
    • POSTメソッドのリクエストボディ中

stackoverflowでも、特にPHPで「rawurlencode()とurlencode()あるけど、どう違うんだよ!?」というのでよく質問されるようです。

2017-11-19追記 : URIのエスケープについて、その歴史や微妙な差異など、こちらの調査報告が非常に精密にまとめられているのでオススメです!

  • "9 URIのエスケープ", 情報セキュリティ技術動向調査(2009 年下期):IPA 独立行政法人 情報処理推進機構

2014-03-16追記 : PHPのurlencode()とrawurlencode()の詳しい経緯についてはこのスライドがスゴイ!

(全て表示する)
プレーンテキスト形式でダウンロード
現在のバージョン : 3
更新者: msakamoto-sf
更新日: 2017-11-19 16:15:33
md5:178e5126f91cc58d98534f0154d0eb37
sha1:357c1f06ea8e55ab575b28739f602e92c4f38b04

技術/OSSライセンス/MITとBSD 2-clause の違い  

所有者: msakamoto-sf    作成日: 2017-10-21 21:22:34
カテゴリ: License 

今まで、ゆるゆるライセンスにしたいときは BSD 2-clause のライセンスを選択してきたけど・・・

以下の記事みると、ゆるゆるライセンスにしたい時はMITがオススメらしい。

こちらのサイトで、自由に使ってもらうならMITライセンスおすすめされてる。

MITライセンスを見てみると、BSD 2-clauseとほぼ同じ内容。

ではどう違うの?というところだけど、以下の問答にあるように、MITの方が「これをしてOKだよ」というのを具体的に、明示的に許可してるのが違いみたい。

とくにマージやサブライセンスなどもMITだと明示的に許可してるのが大きな違い。
BSD 2-clauseだと "Redistribution and use in source and binary form" に丸められてるため、あまり細かく利用用途の許可を明示しておらず、解釈の問題になってしまう。

となれば、企業とか個人に気軽にコピペして使ってもらうライブラリを作りたいなら、BSD 2-clause よりは MIT の方が適切かもしれない。

他参考:



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-21 21:23:00
md5:3e7b662843306d2f710586e947657500
sha1:d8f1cec3c23bde195672f8510defc9de34605bdc

日記/2017/10/09/MSYS2,MinGW64,Cygwinの違い  

所有者: msakamoto-sf    作成日: 2017-10-09 21:51:48
カテゴリ: Cygwin MSYS,MSYS2,MinGW,MinGW64 

会社のPCを入れ替えることになり、Windows上のunixツール環境、今度はどうしようかと考えた。
今まではCygwin使いだったが、apt-cygの動向があるのと、QiitaなどでMSYS2の記事が増えてるので、MSYS2に乗り換えてみようか、とも思う。

実は一度新PCにMSYS2とCygwinを入れてみたのだが、MSYS2はそもそもスタートアップメニューのショートカットがMSYS2とMinGW64/32で分かれてるのがそもそも理解不能だったし、Cygwinのsetup-x86_64.exeの使い勝手も相変わらず悪かった。
とはいえ、apt-cygが一向に公式に取り入れられないなどCygwinに頼り切るのはどうもなぁ・・・という感じ。

apt-cygのゴタゴタ参考:

で、MSYS2だがいまいちMinGW64との違いや関係が理解できない。
これ読んでもまだピンとこない。

一応MSYS2のHistoryも読んでみたが・・・。

やっぱり分からん。つーか、やっぱり何でスタートメニューのショートカットでMSYS2/MinGW64/32で分かれるんや。
ぐぐってたら以下のQAを見つけて、これでようやく腑に落ちた。

つまりこういうことかな?

  • MSYS2とMinGW64の最大の違いは、POSIXエミュレーションを介しているか否か。
  • MSYS2は実はCygwinをupstreamとしたforkで、POSIXエミュレーションとして msys-2.0.dll を使い、パスを変換したりしている。
    • つまり、MSYS2のexeはMSYS2用のDLLやPATH環境じゃないと使えないし、Windowsのファイルパスは扱えない。
  • 一方で MinGW64 はPOSIXエミュレーションは使っておらず、GNUのツールをそのままWindowsに移植したもの。そのためWindowsのファイルパスをそのまま扱える。
    • つまり MinGW64のexeは単体でWindowsアプリとして実行可能となっている。コマンドプロンプト(cmd.exe)からも利用可能。
  • 以下に、pacmanなどではMSYS2を使えとか書いてあるのは、要はMSYS2/MinGW64のパッケージ管理をMSYS2側のpacmanで行えるように統合しているため。
  • スタートメニューからのMinGW64/32のシェルメニューでは、/mingw64, /mingw32 の bin ディレクトリをPATHの先頭に置いて、次に(MSYS2の)/usr/bin を置いている。
    • つまり、gccなどを MinGW64/32 のコマンドを優先して使うように調整している。

自分の中で整理(間違ってるかも):

  • MSYS2がPOSIXエミュレーションを使った一般的なunixのCUI環境を整えて、その上でMinGW64が動いて、OSSをWindowsに移植する作業環境として使う、みたいなのを想定している。
  • MSYS2自身にもgccはあるけど、それはWindowsネイティブexeをビルドするものではなく、あくまでもPOSIXエミュレーションを行う = MSYS2でしか動かないツールをビルドするのにしか使えない。
  • よって、MSYS2が提供するスタートメニューのショートカットのシェルは、以下のように使い分ける。
    • MSYS2 : MSYS2のツールしか使わない(=Cygwinのfork)用途であればこれで問題ない。
    • MinGW64/32 : Windowsネイティブexeを開発したい場合にはこちらを使う。あるいは MinGW64 側にしかパッケージがないコマンドを使いたい場合もこちら。

この辺、MSYS2のintroductionにもはっきり書かれてないので、分かりづらかった。(表現に注意すれば、書かれていなくはないのだが、ストレートに読み取り辛い・・・)

結局MSYS2はCygwinのupstreamを追いかけるforkということは確かで、それならパッケージの種類は問題ないよね・・・と思いきや、上記Wikiでも "msys2 subsystem is pretty small" とある通り、パッケージ一覧を見ても本当に必要最低限のunixツールセット、という感じ。

むしろ "mingw-w64-" prefixの方がパッケージが充実してる・・・。

が、結局はCygwinのサブセットなので、Cygwin側のパッケージ数には劣る。

とはいえとはいえ、MSYS2側の調整でファイルパスの "/cygwin" prefixが省略できたり、マウントにnoaclがデフォルトとなるのは多少楽、ではあるが・・・。

うーん、開発に使いたいわけではなく、便利なunixのCUIツールをWindowsで使いたいだけなので、正直MSYS2/MinGW64の住み分けの考え方は余分なんだよなぁ・・・。
パッケージ数としてもCygwin本家の方が圧倒的なので、結局 Cygwin + apt-cyg の方が良いのではなかろうか・・・。

正直、なんでQiitaでみんなしてMSYS2使ってるのか分からん・・・。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-09 21:52:13
md5:84821906b64d35fe1481f1b548c1a072
sha1:a219bdc0edd1cd8bb75fcc26b34f4dd3f0e010ae

技術/Security/testssl.sh  

所有者: msakamoto-sf    作成日: 2017-10-07 17:31:50
カテゴリ: SSL/TLS セキュリティ 

サーバのSSL/TLSをセキュリティ観点でチェックしてくれるツール、testssl.shを使うメモ。


インストール(Version 2.9.5-1版)

2017年の9月に安定版として 2.9.5-1 がリリースされたのでこれをインストールしてみる。
(正確にはこの時点での安定版は 2.8 だが、開発中の 2.9 branch の中でも安定版として言える状態として 2.9.5-1 がリリースされてる。)

環境:CentOS7, 64bit版

インストールのポイントとしては、 https://testssl.sh/ から testssl.sh をDLするのではなく、GitリポジトリをそのままcloneするかリリースパッケージをDL, 展開する方法に変わってる点。
OpenSSLバイナリも特殊なのをビルドして使ってたりするので、今後はこちらの方式が簡単かもしれない。

Gitからclone -> 2.9devになる

https://github.com/drwetter/testssl.sh の Readme.md にあるとおりにする。

$ git clone --depth 1 https://github.com/drwetter/testssl.sh.git
$ cd testssl.sh/
$ ./testssl.sh -v
(...)
###########################################################
    testssl.sh       2.9dev from https://testssl.sh/dev/
(...)

2.9dev branchがデフォルトのbranchとなっている。gitのcloneオプションを調整すれば、他のbranchを利用することも可能だろう。
また、このままでは /bin/openssl を見に行ってしまい、testssl.sh 中の bin/opensslバイナリを使ってくれなかった。
→以下のようにOPENSSL環境変数で調整できる。

$ OPENSSL=./bin/openssl.Linux.x86_64 ./testssl.sh -v
(...)
 Using "OpenSSL 1.0.2-chacha (1.0.2i-dev)" [~183 ciphers]
 on L0000627:./bin/openssl.Linux.x86_64
(...)

GitHubのリリースアーカイブを使う

GitHubのリリースページからアーカイブをDLする。

$ curl -L -O https://github.com/drwetter/testssl.sh/archive/v2.9.5-1.tar.gz
$ tar zxf v2.9.5-1.tar.gz
$ cd testssl.sh-2.9.5-1/
$ ./testssl.sh -v
(...)
###########################################################
    testssl.sh       2.9.5 from https://testssl.sh/
(...)

こちらでもやはりOpenSSLバイナリが /bin/openssl をデフォルトで使ってしまうので、環境変数かコマンドラインで調整する。

$ OPENSSL=./bin/openssl.Linux.x86_64 ./testssl.sh -v

or

$ ./testssl.sh --openssl ./bin/openssl.Linux.x86_64 -v

→
(...)
 Using "OpenSSL 1.0.2-chacha (1.0.2i-dev)" [~183 ciphers]
 on L0000627:./bin/openssl.Linux.x86_64
(...)

主な使い方

※チェックする対象は自分の管理下にあるサーバか、脆弱性検査を許可されたサーバのみにすること。

通常テスト:

$ ./testssl xxx.xx.xxx.xx:443

HTMLに出力(通常テストでコンソールで使われるエスケープシーケンスが、ちゃんとHTMLにも反映されます)

$ ./testssl.sh --html www.glamenv-septzen.net:443

プロトコルバージョンごとにcipher suiteをリストアップ

$ ./testssl -E xxx.xx.xxx.xx:443

特にプロトコルバージョンごと、にはこだわらず、全部混ぜてリストアップ

$ ./testssl -e xxx.xx.xxx.xx:443

参考/その他

参考:

  • SSTtechlog 05 JavaでSSL/TLS接続アプリケーションを作ってみよう(1) : SSL版Echoサーバ/クライアントの作成と脆弱性テスト(testssl.sh,Nmap) | SST 株式会社セキュアスカイ・テクノロジー

その他:

$ ./testssl.sh xxx.xx.xxx.xx:443 | aha > output.html
  • OpenSSLのciphersuite名をRFCにマッピングするの、2.6の時は別途 mapping-rfc.txt をDLして配置する必要があったが、2.9.5-1 ではその必要無く、OpenSSL形式とRFC形式の両方で表示してくれた。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-07 17:33:53
md5:42e1def4c50c3e294c95c887a7553d0f
sha1:940584c0a1f9bf0332530b40586b0776e14aa210

技術/Chrome/SeleniumIDE, Selenium Builder, その他E2Eテスト用のChrome拡張について(2015-04時点)  

所有者: msakamoto-sf    作成日: 2015-04-27 12:21:34
カテゴリ: Chrome Selenium WebDriver 

ChromeでのSeleniumIDE相当や、End-To-Endテスト向けのChrome拡張にどんなのがあるか調べてみたメモ。

Selenium IDEの次世代、Selenium Builder :

@kyo_ago さんが、Chrome用のSelenium IDEを独自に作ってたり、独自のE2Eテストツール用Chrome拡張作ってる。

その他のブラウザ操作の記録&再生&テスト用Chrome拡張:

ブラウザ操作の記録/再生そのものではないが、WebDriver/Seleniumのテストケースの作成を支援するユーティリティ系Chrome拡張:



プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2017-10-07 13:53:25
md5:85bce92f75f6dc38c15cd522cec94200
sha1:dd71ad0b531fe9ff0011a4fd1a5a6620f5dc5f74

技術/Chrome/お気に入りChrome拡張のメモ  

所有者: msakamoto-sf    作成日: 2017-02-12 12:29:33
カテゴリ: Chrome 

よく使ってる拡張について紹介します。


Proxy切り替え

old:

今のウインドウで開いてるTABのタイトルとURLを抽出

色々調べ物してて、参考ページなどを タイトル + URL で一気にWiki/Markdownのリストに落とし込みたい時に便利です。
自分でも同様の拡張を自作( 技術/Chrome/Chrome Extension の勉強メモ(copy_tab_urls) )しましたが、上記拡張の方が複数フォーマット(テンプレ)を登録できるので、複数スタイル(Wiki/Markdown/HTML)を使い分けられて便利です。

Webページの見出しを目次化してくうれる、アウトライン生成してくれる拡張(heading tag navigation)

見出しのネストが複雑なWebページを閲覧していると、目次が欲しくなってきます。
コンテンツによっては、手動または自動で見出しの目次が生成され、クリックすればその見出しにジャンプできるようになっています。
しかしそうした目次が無い場合は、大きなドキュメントになるほど、文書構造を把握することが困難になり理解するのに時間もかかってしまいます。

そうした時に、コンテンツ側ではなくブラウザ側で自動的に見出し一覧を生成してくれる機能があると便利です。
以下のChrome拡張をインストールすると、そうした機能を使えるようになります。

以下が実際に表示された様子で、左側のページ表示領域に埋め込まれているのが"HeadingsMap", 中央にアドレスバーからポップアップしているのが"HTML5 Outliner"の見出し一覧です。(2017-02時点のChrome56 + Win10 でスクリーンショットを撮り直してます)


それぞれどんな違いがあるか、簡単にまとめます。

  • HeadingsMap
    • Chrome拡張とFirefox AddOnの両方がある。
    • 見出しが長いと省略される。
    • 見出し一覧のブロックのサイズが変更できない。
  • HTML5 Outliner
    • 以下のgithubプロジェクトでHTML5のアウトライン化に関連するプロダクトがまとめて開発されており、Chrome拡張はその中の一つ。
    • Chrome拡張の他に、ブックマークレットで半透明なdivブロックを追加して見出しリンクの一覧を表示することもできる。そのためクロスブラウザ対応と言えなくもない。
    • 長い見出しは折り返される。省略されることはない。

なお、見出し一覧を生成したいコンテンツが仕事に関連する非公開コンテンツの場合も考えられます。そうしたコンテンツを上記Chrome拡張は読み取ることになりますが、コンテンツの内容を不正に外部サーバなどに送信していないか気になるところです。
そこで、HTTPプロキシを間に入れてHTTP/HTTPS通信を確認したところ、不正なサーバにコンテンツ内容を勝手に送信しているような通信は両方共確認できませんでした。
そのため、両方共、コンテンツへのアクセスは純粋に見出しを抽出して一覧を生成するためだけにアクセスしており、非公開コンテンツに対して使っても問題ないと思われます。("HTML5 Outliner"はgithub上でソースが公開されていますので、ソースの方も確認し、XMLHttpRequestなどの呼び出しが無いことを確認済み)

その他、ユーティリティ系

ガラケーのsimulator

文字コード/エンコーディング関連

表示中のページの文字コード(エンコード)を変更:

URLEncode/Decode:

フレームを別タブ/別Windowなどで開く

RSS関連



プレーンテキスト形式でダウンロード
現在のバージョン : 5
更新者: msakamoto-sf
更新日: 2017-10-07 13:49:57
md5:ba8a09de4ee178a5f1ec6dd14cb5ca8a
sha1:25b7d184ca63067d75e059fab32ed99eceb78864

技術/Security/Burp/リクエスト,レスポンスの文字化け対策参考メモ  

所有者: msakamoto-sf    作成日: 2017-10-07 13:33:49
カテゴリ: BurpSuite HTTP セキュリティ ネットワーク 

BurpSuite, 1.3~1.7に至るまで、Proxy historyなどでのリクエスト/レスポンスで、マルチバイト文字のコピペで文字化けする。文字化け、というか、コピーしてペーストすると、マルチバイトのところでデータが切れた内容がペーストされてしまうなど。

解決策としては、現状、Burp拡張を使う他無さそう。

2017年10月時点で有効なBurp拡張:

1.5くらいまでは burpCodeExchange というBurp拡張を使っていた。ISO-2022-JPにも対応していてすごい便利だったが、サイトがLOSTしてる・・・。

http://isayan.cocolog-nifty.com/diary/2014/04/burp-suite-16-e.html


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-07 13:37:43
md5:f63ab6880bd8d8cc04eab17a6c920d02
sha1:055f0869ffdb6a9619c1afd20c65a154355c2056

Java/JMXのCUIツール参考メモ  

所有者: msakamoto-sf    作成日: 2017-10-07 13:14:42
カテゴリ: Java 

2017年現在、JMXを見るツールとしてはJDK付属のjmc(MissionControll)やjconsoleなどがあるが、いずれも基本的にはGUIツール。サーバ内で作業するときなどは、CUIツールでJMXにアクセスできるのがあると嬉しいので、軽くググッたときの参考メモです。

→これが軽い感じのツール。実際には、以下の記事でカスタマイズしたものを使ったほうが簡単そう。

Jmxtermというのもある。これも機能的には十分そう。

これはちょっと違うかも。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-07 13:19:15
md5:3d81e982dac2b875f4697f1aa19dcda1
sha1:2c98bab9828474ec8494967403ab2c34208dbd44

Java/JVMオプションとデフォルト値の一覧取得(-XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -XX:+AggressiveOpts)  

所有者: msakamoto-sf    作成日: 2017-10-07 12:13:33
カテゴリ: Java 

基本形 : -XXオプションの一覧を標準出(-version を付けることでjavaコマンドのusage表示を省略させる)

java -XX:+PrintFlagsFinal -version

仮想マシンチューニング用のオプションも出力:

java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version

実験的なオプションも出力:

java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -version

他、"-XX:+AggressiveOpts" や "-XX:+PrintFlagsInitial" というのもある。

2011年~2017年ごろまでの参考:

その他参考:

Qiitaより:



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-07 12:30:33
md5:909a8dd8757c5179d6bfb8ae649a2967
sha1:0b19c7bc0e83618641d39ca62078882979d92930

日記/2017/10/05/SingletonのGoodパターン、Badパターン  

所有者: msakamoto-sf    作成日: 2017-10-05 23:57:09
カテゴリ: システム開発 プログラミング 

仕事としてプログラミングしてて、もう10年来ずっと、いたるところでレガシー化しやすく、テストコードを書けなくしてる最大の原因と思うのがSingletonデザインパターンだと個人的には思う。

ただ、最近DIコンテナなど扱うようになってきて、ようやくSingletonデザインパターンの使い方でGoodなパターンとBadなパターンの二種類が見えてきた。

Badパターン

Javaでかけば以下のようなコード。

public class MyClass {
  private static final MyClass instance = new MyClass();
  private MyClass() {
    // constructor
  }
  public static MyClass getInstance() {
    return MyClass.instance;
  }
}

何が問題なのか:

  • Mock用のMyClassインスタンスを作れない(constructorがprivate)ので、単体テストが非常に書きづらい。
    • Mock用ライブラリによってはClassLoaderをいじることでMock化できるものもあるが、かなりナイーブなコードとなってしまい、他のライブラリと安定して組み合わせるのが難しくなる。
  • Singleton化されたインスタンスのライフサイクルが、ClassLoaderのライフサイクルと等しくなり、非常に長く、しかもアプリケーションの世界からは扱いが難しいライフサイクルとなっている。

Goodパターン

なんちゃってアノテーションつければこんな感じ。

@Singleton(scope=Application)
public class MyClass {
  private final ApplicationContext appContext;
  public MyClass(@Inject final ApplicationContext appContext) {
    $this->appContext = appContext;
    // ...
  }
}

利用側:

// ...
ApplicationContextImpl appContext = new ApplicationContextImpl();
// ...
DIContainer dicon = DIContainer.create(appContext);
MyClass singleton = dicon.get(MyClass.class);

どう問題は解決されたのか:

  • Mock用のMyClassインスタンスを普通に作れる様になった。
  • Singleton化されたインスタンスのライフサイクルが、DIコンテナ管理となった。DIコンテナは大抵、テストコード中でライフサイクル管理できるようになってるはずなので、アプリケーションの世界から扱いやすいライフサイクル管理となる。

デメリット:

  • 「インスタンスを一つに制限する」というのを言語のルールで制限できなくなった。
    • これにより、ルールに疎いプログラマが、コード内で勝手にnewする可能性がある。

「インスタンスを一つに制限する」をどこで行うか?

Badパターンでは「インスタンスを一つに制限する」を言語のルールで実現できていたが、逆にGoodパターンではそれを諦めている。
それでは本末転倒ではないのか?
否、「インスタンスを一つに制限する」のは、「何に対して」であるのか、という点が今まではおろそかになっていたと考える。
その前に、そもそもそうした「ルール」をどこで担保するのかについて考えなければならない。

Badパターンでは「ルール」の担保を言語側で担保していた。これは非常に強固で確実だが、同時にテストコードを書くときの障害になる。

個人的には、テストコードを書きづらい設計はどんなにデザインパターン上「正しく」ても、最低最悪のクソコードである。

テストコードがかければ、リファクタリングできる。実装コードを、洗練できる。

しかし、テストコードが書けなければ、リファクタリングする機会が大幅に失われる。実装コードを洗練することが難しくなる。

プログラミングは創造的な作業であるのは確かで、最初から100%の正しさでクラス構造をデザインできることはまずありえない。必ずリファクタリングをする時が来る、あるいは振る舞いを変えるレベル=リファクタリングを超えるレベルで設計を変更する時が来る方が自然と考えたほうが良い。(これについては賛否両論ありそうだけど。)

よって、OOPだろうが関数型だろうが手続き型だろうが、リファクタリングできないソース、端的にはテストコードが書けない設計はどんなにその他が正しく作れれていも、クソコードだと断言する。

ここでSingletonの話に戻ってくると、BadパターンがなぜBadパターンか、それはテストコードを書きづらくて、大抵は書くのをギブアップするような状況になるのが理由となる。(これがconstructorがpublicで、デフォルト実装をsingleton化してるだけで、作ろうと思えば派生クラスとかで色々いじれる状況なら、テストコード用にMock化できるので許容範囲)

つまり自分の意見としては、「インスタンスを一つに制限する」のがテストコードを書きづらくするのなら、そんなルールはゴミ箱に捨てろ。それよりもテストコードを書きやすくしろ、そして書け、書いたテストコードがサンプルコードになり、後続がそれを見て使い方を学べるようにしろ、ルールの担保はコードレビューで担保しろ。ということになる。

そして、「何に対して」インスタンスを一つに制限するのかだが、これは普通に考えればアプリケーションのライフサイクルに揃えるのがSingletonの意図として順当と思われる。
となれば、アプリケーションの開始から終了までの、様々なインスタンスを収めた「文脈=Context」的なインスタンスと同じ長さになるだろうし、またSingletonは左記の「文脈=Context」に含まれるのが順当だろう。

よって、Goodパターンではテストコードの書きやすさを担保しつつ、アプリケーションのライフサイクル(Goodパターンで挙げた例ではDIコンテナ)に合わせて管理できるようにした。これなら、テストコード中でプログラマブルにライフサイクル管理がしやすくなる。

「ルール」よりは「テストコードによる例示とコードレビューによる担保」へ

自分の意見になるが、「テストコードを書ける設計になっていること」が最重要となる。
よって、Singletonデザインパターンを実装する場合もテストコードを書ける設計にすることがまず大前提となる。
しかし、Mock化などを考えると言語レベルでの「一つに制限」する「ルール」は採用できない。
そうなると慣れてないプログラマが自分でインスタンスを作ってしまったりする可能性があるが、そのリスクはどう見るか?

そのリスクは、「テストコードによる例示とコードレビューによる担保」で回避すればよい、というのが自分の意見になる。

重要なのは、「何に対してインスタンスを一つに制限しなければならないのか」を明示すること。

実際にDIコンテナやアプリケーションのcontextインスタンスを作り、そこからSingletonインスタンスを取り出すのをテストコードで表現すること。それができる設計にすること。
そうしておくことで、後続のプログラマに対して、そのクラスの使い方、Singletonとしての存在意義をテストコードで表現できる。

もし間違って独自にインスタンスを作るようなコードを書いた場合は、コードレビューで指摘して直してもらう。その際に、テストコードを示してSingletonとしての使い方、アクセス方法、テストコードの書き方を例示することで、後続のプログラマの勉強にもつながる。

もう一度書くと、テストコードを書く障害になるような設計は、どんなに他が正しくてもゴミ箱ゆきというのがここ数年における自分の意見なので、それに基づくと上記のようになった。

以上。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2017-10-06 00:37:20
md5:52236fb8050e949c0c90355914245d54
sha1:7b41518cbe4645a10c375a56e4a422e7020699ad