Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

業務アプリにおける VB との付き合い方

1,378 views

Published on

CLR/H in TOKYO #2 の発表資料

Published in: Software
  • Be the first to comment

  • Be the first to like this

業務アプリにおける VB との付き合い方

  1. 1. 業務アプリにおける VBとの付き合い方 2014/5/10 @s_earlgrey
  2. 2. Profile •某独立系SIerでプログラマーとかやってます •好きな言語はC#ですが、お仕事ではVB多め •DBとかSQLまわりも好きですよ! •勉強会で話すのは初めてなので、ちょっとドキ ドキ →最初はLTのつもりでしたが、資料の量が増えてき たので、セッションとしてチャレンジしてみることに •和文フォントは「あんずもじ」を使ってます →http://www8.plala.or.jp/p_dolce/
  3. 3. VBと業務アプリ
  4. 4. VBの持ち味ってなんだろう? •VBといえば、遅延バインディングや暗黙の型 変換による、ゆるふわなプログラミング →規定でOption Strict Offですしね •ただし、それらの挙動をきちんと理解していな いと、たまに落とし穴にはまる →あとで例を出します •ということは、バグが出ても許されるお気楽な アプリを開発する場合か、ハイレベルな開発 者が楽をしたい場合に適しているのでは?
  5. 5. じゃあ業務アプリでは? •別に業務アプリに限った話じゃないけど、世の 中やたらと他人に厳しいので、バグだなんてと んでもない! →業務アプリは大抵お高いのでなおさら →細かいところだと再発防止策とかなんとか •業務アプリといえばSIerですが、そこではハイ レベルの開発者を揃えることよりも、平凡な 開発者を集めて標準化やプロマネの手腕で 成功に導くことが是とされがち
  6. 6. あ、あれ? 実はVBって業務アプリに 向いてなかったりしますか???
  7. 7. そんなことは・・・ •もしかしたらSIer的にはあるかもしれないです •でも原理主義にこだわっても仕方ないし、Dis りに来たわけでもないので、現実的にどう付き 合っていくかという話をこれからします
  8. 8. まずは型から
  9. 9. IDEにチェックしてもらいましょう •Option Strict On →もはや釈迦に説法ですね →正直VBの持ち味を殺すことになるけど、しょうが ない •Option Infer On →これも今さらですが →元からOnなのでそのままにしときましょう →As Newの派生と言っておけば、昔ながらのVBプ ログラマーにも受け入れられやすいかも・・・?
  10. 10. 部分的に動的型を使う場合 •Option Strict Onにしつつ、特定のオブジェクト に対してだけ動的型付を行うことはできない →現状ではVBとC#は構文ぐらいしか違いがないと 言われているものの、C#にしかない気になる機能 差のうちのひとつ(他には逐語的リテラル文字 列とか) •VBの場合、パーシャルクラスを活用することで、 プロパティ/メソッドのスコープ単位で動的型 付を許可することになる →動的型を使いたいものだけ同じファイルにする
  11. 11. パーシャルクラスってイマイチ・・・ •パーシャルクラスを使うと、ソリューションエクス プローラでの見通しが悪くなる →ので、接尾辞を付けましょう(_StrictOffとか) •後述のVSCommandsをインストールすれば ソースファイルのグループ化がお手軽にできま すが、「すべてのファイルを表示」にしておかな いと隠れてしまうので、お好みで
  12. 12. ちょっとVSCommandsの紹介 •VisualStudioギャラリーからインストール →こういうやつ •こんな感じでグループ化できます
  13. 13. ちょっとVSCommandsの紹介 •VisualStudioギャラリーからインストール →こういうやつ •こんな感じでグループ化できます
  14. 14. ちょっとVSCommandsの紹介 •VisualStudioギャラリーからインストール →こういうやつ •こんな感じでグループ化できます
  15. 15. ちょっとVSCommandsの紹介 •VisualStudioギャラリーからインストール →こういうやつ •こんな感じでグループ化できます
  16. 16. VSCommandsつづき •グループ化自体は「.Designer.vb」などと同じ でVisual Studio標準の機能で実現している ので、VSCommandsのない環境でもちゃんとグ ループとして表示される •ちなみにやっぱりグループ化をやめたい場合
  17. 17. Option Strict Offの場合 •そうはいってもいろんな理由でOption Strict Offにしなきゃいけないことがある →エライ人が聞く耳持ってくれないとか →今さら変えられないとか •そんなコードには知ってか知らずか、大抵暗黙 の縮小変換が多用されている
  18. 18. 縮小変換って? •「縮小変換とは、常に成功することを証明で きない変換、情報が失われる可能性が既知 の変換、および縮小表記が必要になるような 異なる型のドメイン間で行われる変換です。」 →Microsoft® Visual Basic® 言語仕様 8.9節 縮小変換より →言語仕様はあとで紹介します •Option Strict Offだと、必要に応じてこれが 自動的に発生する
  19. 19. 暗黙の変換のクセを把握しよう •暗黙の縮小変換が行われる場合、多くの場 合は比較的直感的な変換になる →だからこそ初級者に受けがいいわけだけど・・・ •でも常に期待通りとは限らないので、どんな動 きをするかきっちりと把握しておくことが大事 •全部を覚えるのはムリでも、必要に応じて調 べる術を用意しておきましょう
  20. 20. さてここでクイズです(1) •次を実行した場合、出力されるのは True/Falseのどちら? →Option Strict Offにしてます Dim foo As Decimal = 0.1D Dim bar As String = "0.1" Console.WriteLine(foo * bar = 0.01D)
  21. 21. 答え(1) •答えはFalseです
  22. 22. 答え(1) •答えはFalseです •Stringの”0.1”がDoubleに変換されるので、丸 め誤差が発生する →Decimalにしてくれてもよさそうですが、まぁわか らなくもない
  23. 23. 答え(1) •答えはFalseです •Stringの”0.1”がDoubleに変換されるので、丸 め誤差が発生する →Decimalにしてくれてもよさそうですが、まぁわか らなくもない •イメージとしては次と同等な感じでしょうか・・・ Dim foo As Decimal = 0.1D Dim bar As Double = 0.1 Console.WriteLine(foo * bar = 0.01D)
  24. 24. ではもう1問クイズです(2) •ではこちらを実行した場合はTrue/Falseどっ ち? Dim foo As Decimal = 16.4D Dim bar As String = "100" Console.WriteLine(foo * bar = 1640D)
  25. 25. 答え(2) •これもやっぱりFalseです
  26. 26. 答え(2) •これもやっぱりFalseです •今の流れだといかにもという感じですが、こち らだけパッと見るとTrueになりそうな気が・・・ →私だったらしてしまいます
  27. 27. 答え(2) •これもやっぱりFalseです •今の流れだといかにもという感じですが、こち らだけパッと見るとTrueになりそうな気が・・・ →私だったらしてしまいます •これと同等ではありません →こちらはちゃんと(?)Trueになってくれます Dim foo As Decimal = 16.4D Dim bar As Integer = 100 Console.WriteLine(foo * bar = 1640D)
  28. 28. 何が起きているの? •暗黙の縮小変換はコンパイラの仕事なので、 ILSpyなどを使ってコンパイル済みアセンブリを 覗くと、何が起きているかわかります •念のため、ILSpyは以下で配布されています →http://ilspy.net
  29. 29. 暗黙の縮小変換の挙動(1) •さきほどのクイズ(1)のコンパイル結果 Dim foo As Decimal = 0.1D Dim bar As String = "0.1" Console.WriteLine(foo * bar = 0.01D)
  30. 30. 暗黙の縮小変換の挙動(1) •さきほどのクイズ(1)のコンパイル結果 •DecimalもStringもDoubleに変換 →0.1ならDoubleで納得ですね Console.WriteLine( Convert.ToDouble(foo) _ * Conversions.ToDouble(bar) = 0.01) Dim foo As Decimal = 0.1D Dim bar As String = "0.1" Console.WriteLine(foo * bar = 0.01D) 宣言は同じなので省略
  31. 31. 暗黙の縮小変換の挙動(2) •今度はクイズ(2)のコンパイル結果です Dim foo As Decimal = 16.4D Dim bar As String = "100" Console.WriteLine(foo * bar = 1640D)
  32. 32. 暗黙の縮小変換の挙動(2) •今度はクイズ(2)のコンパイル結果です •やっぱりDecimalもStringもDoubleに変換 →あれ?100なのにIntegerでなくDoubleですか?? Console.WriteLine( Convert.ToDouble(foo) _ * Conversions.ToDouble(bar) = 1640.0) Dim foo As Decimal = 16.4D Dim bar As String = "100" Console.WriteLine(foo * bar = 1640D) 宣言は同じなので省略
  33. 33. 暗黙の変換の原則 •縮小変換に限らず、暗黙の型変換は、変換 前の型情報と演算子によって変換先の型が 決まる →変換前の値までは見てくれない •先の例だと、Stringが”0.1”だろうが”100”だろ うがDoubleに変換される
  34. 34. コンパイルする前に知りたい! •ちょっと調べたいだけなのに、いつもコンパイル してILSpyって面倒・・・ •MSDNに載ってない? →完全なものは私は見つけられませんでした →以下に少し載っていますが、今回のような DecimalとStringの四則演算などは記載なし http://msdn.microsoft.com/ja- jp/library/ms235255(v=vs.120).aspx •じゃあ何を見ればいいの?
  35. 35. VBの言語仕様の所在 •Visual Studio 2010以降かつ Professional以 上には、VBの言語仕様が付いてくる →量が多いしとっつきにくいけど、一番確実です •Visual Studio 2010の場合(デフォルト) →C:Program Files (x86)Microsoft Visual Studio 10.0 VBSpecifications1041 Visual Basic Language Specification 10.0.docx •Visual Studio 2012/2013の場合 →紙面の都合で割愛しますが、2010と似たような ところにあります(10.0が11.0や12.0だったり) →2012と2013は、パスは違うけど内容は同じです
  36. 36. 早速見てみましょう •暗黙の型変換の詳しい挙動については、 11.12 演算子~11.18 シフト演算子あたりに 記載されています →「演算の型」で検索してもよいです
  37. 37. 見てみましょう(2) •先のクイズのようなDecimalとStringの乗算に ついては、11.13.5 乗算演算子に載ってます →ごらんのとおり、Doubleです(※同節より抜粋) Bo SB By Sh US In UI Lo UL De Si Do Da Ch St Bo Sh SB Sh Sh In In Lo Lo De De Si Do Err Err Do SB SB Sh Sh In In Lo Lo De De Si Do Err Err Do By By Sh US In UI Lo UL De Si Do Err Err Do Sh Sh In In Lo Lo De De Si Do Err Err Do US US In UI Lo UL De Si Do Err Err Do In In Lo Lo De De Si Do Err Err Do UI UI Lo UL De Si Do Err Err Do Lo Lo De De Si Do Err Err Do UL UL De Si Do Err Err Do De De Si Do Err Err Do
  38. 38. ところでExpressの場合は? •残念ながら、Expressの場合は言語仕様が付 属しません →そもそも業務なのにExpressなんてことは・・・少な くとも私はあったので否定できません •しかしながら、Professional以上の評価版を インストールすることで入手可能 →ただ、本体の評価期限が過ぎた後の取り扱い は、?です →単なるWord文書なので開けなくなることはない ですが
  39. 39. 2008以下の場合は? •2008以下の場合、エディションにかかわらず VBの言語仕様がインストールされない →英語版ならダウンロードセンターで入手可能な ので、英語に自信のある方はそちらをどうぞ •ちょっと大変ですが、最終章にバージョンごと の変更がまとめられているので、逆適用するこ とで下位バージョンの仕様を知ることが可能 →ただし演算時の型変換に限れば、8.0(2005相 当)で符号なし整数型が加わった以外の変更は ないです
  40. 40. 既定のインスタンス
  41. 41. 既定インスタンスってどうよ? •最近はWinForm自体が枯れたせいか、あまり 話題にならなくなりましたが、登場当初はわり と評判の良くなかった既定インスタンスさん •私も単にダサいと思ったので近寄らないように してましたが、この機会に改めて自分の目で 動作を確かめてみました →言語仕様の11.6.2 既定インスタンスを読んだけ ど、よくわからない部分があった・・・
  42. 42. 既定ぶりを検証(1) •先に明示的なインスタンスが存在している場 合は? '先に明示的なインスタンスを表示して Dim frm As Form2 = New Form2 frm.Text = "foo" frm.Show() '同じフォームの既定インスタンスを通して 'タイトルを変更 Form2.Text = "bar"
  43. 43. 既定ぶりを検証(1) •先に明示的なインスタンスが存在している場 合は? '先に明示的なインスタンスを表示して Dim frm As Form2 = New Form2 frm.Text = "foo" frm.Show() '同じフォームの既定インスタンスを通して 'タイトルを変更 Form2.Text = "bar"
  44. 44. 既定ぶりを検証(1) •先に明示的なインスタンスが存在している場 合は? →既定インスタンスはあくまで固有の存在のよう です '先に明示的なインスタンスを表示して Dim frm As Form2 = New Form2 frm.Text = "foo" frm.Show() '同じフォームの既定インスタンスを通して 'タイトルを変更 Form2.Text = "bar"
  45. 45. 既定ぶりを検証(2) •既定インスタンスをCloseしたらDisposeされ る?されるならその後は? '既定インスタンスを開いてClose(Disposeされる?) Form2.Show() Dim foo = Form2 Form2.Close() '再度既定インスタンスを開いてみる 'ObjectDisposedException来ちゃうかな・・・ Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  46. 46. 既定ぶりを検証(2) •既定インスタンスをCloseしたらDisposeされ る?されるならその後は? '既定インスタンスを開いてClose(Disposeされる?) Form2.Show() Dim foo = Form2 Form2.Close() '再度既定インスタンスを開いてみる 'ObjectDisposedException来ちゃうかな・・・ Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  47. 47. 既定ぶりを検証(2) •既定インスタンスをCloseしたらDisposeされ る?されるならその後は? →CloseとともにDisposeされ、その後はまた新しい インスタンスが作られる '既定インスタンスを開いてClose(Disposeされる?) Form2.Show() Dim foo = Form2 Form2.Close() '再度既定インスタンスを開いてみる 'ObjectDisposedException来ちゃうかな・・・ Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  48. 48. 既定ぶりを検証(3) •じゃあShowDialogで開いたのをCloseした場 合は? '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない Dim foo = Form2 '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  49. 49. 既定ぶりを検証(3) •じゃあShowDialogで開いたのをCloseした場 合は? '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない Dim foo = Form2 '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  50. 50. 既定ぶりを検証(3) •じゃあShowDialogで開いたのをCloseした場 合は? →とくに驚きはなく、インスタンスは生きている '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない Dim foo = Form2 '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  51. 51. 既定ぶりを検証(番外編) •Usingも既定インスタンスで Dim foo As Form Using Form2 '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない foo = Form2 End Using '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  52. 52. 既定ぶりを検証(番外編) •Usingも既定インスタンスで Dim foo As Form Using Form2 '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない foo = Form2 End Using '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  53. 53. 既定ぶりを検証(番外編) •Usingも既定インスタンスで →これも結果は納得ですが、コードの見た目が・・・ Dim foo As Form Using Form2 '既定インスタンスをShowDialog Form2.ShowDialog() 'Form2が自身を閉じないとここには来ない foo = Form2 End Using '再度既定インスタンスを開いてみる Form2.Show() '1回目と2回目のインスタンスは同じもの? Form2.Text = (foo Is Form2).ToString()
  54. 54. で、使えそう? •やっぱり動作にクセがある感じでしょうか →個人的には明示的インスタンスと組み合わせた (1)の挙動が引っかかるし、チーム開発でやられ るときつい •なるほどSIer的には悪評も納得・・・ →もちろんみんながわかってて使う分にはいいかもで すが、期待薄
  55. 55. 使いたくないけどどうしよう? •既定のインスタンスを警告してくれるコンパイ ルやコード分析のオプションとかないの?
  56. 56. 使いたくないけどどうしよう? •既定のインスタンスを警告してくれるコンパイ ルやコード分析のオプションとかないの? →ないです
  57. 57. 使いたくないけどどうしよう? •既定のインスタンスを警告してくれるコンパイ ルやコード分析のオプションとかないの? →ないです •逆にいっそ既定のインスタンスしか使えなくす るオプションとかあればいいのでは!
  58. 58. 使いたくないけどどうしよう? •既定のインスタンスを警告してくれるコンパイ ルやコード分析のオプションとかないの? →ないです •逆にいっそ既定のインスタンスしか使えなくす るオプションとかあればいいのでは! →だからないですってば
  59. 59. 使いたくないけどどうしよう? •既定のインスタンスを警告してくれるコンパイ ルやコード分析のオプションとかないの? →ないです •逆にいっそ既定のインスタンスしか使えなくす るオプションとかあればいいのでは! →だからないですってば •Option Strict Offにできない場合と同じように、 誰かが頑張って拾うしかない
  60. 60. One more thing...
  61. 61. 前言撤回 •既定のインスタンスを警告してくれるオプショ ンはないと言ったな、あれは嘘だ •それどころか、完全に禁止することができちゃ います!
  62. 62. 禁断の秘儀? •Visual Studio 2010 SP1以降に限ります が、.vbprojファイルに以下を追加することで、 それが可能に →VB6.0系の機能を排除するためのオプションで、 その一環として既定インスタンスも禁止される →ちゃんとエディタ上でエラー出してくれます •コマンドラインコンパイラの/vbruntime*オプ ションに相当 <PropertyGroup> <VBRuntime>Embed</VBRuntime> </PropertyGroup>
  63. 63. これは何者? •もともとWindows Phone 7やXNAのように、 C#専用とされていたプラットフォームで、VBでも 開発が行えるように導入されたもの →だからVB固有の機能はほぼ削られますが、極一 部の要素はアセンブリに埋め込まれるため使える •これを利用して、VBでも厳格なコーディングを 強制することが可能に!
  64. 64. 使えるもの、使えないもの(例) •使える →モジュール →暗黙の縮小変換 →メソッド名に代入 →With →AscW/ChrW →vbXxxxx定数 •使えない →遅延バインディング →既定インスタンス →On Error Goto →Like演算子 →多くのVB6.0互換関数 •モジュールは拡張メソッド定義用の措置かと •メソッド名に代入は消えてほしかった・・・
  65. 65. 注意点 •.vbprojで制御する方法はVBチームのブログで 見つけたものの、MSDNには記述なし →何か理由があって推奨されてないとか? •動的型付を行う場合は、そこだけプロジェクト を分ける必要あり •そもそもこんなのVBじゃない論 →そして、ここまでするならいっそC#使え論 •こっそり導入すると、揉めたりするかも
  66. 66. 最後に
  67. 67. まとめ •VBはゆるふわ →遅延バインディングとか暗黙の縮小変換とか既 定インスタンスとか、むしろそれこそが持ち味 →こまけぇこたぁいいんだよ! •でもSIer的業務アプリはそうじゃないので、しっ かり手綱を握ってあげましょう •たまには言語仕様を読んでみるのも悪くない •VBRuntimeオプション超強力ですが、ご利用 は計画的に

×