vb.netでSQL実行を手助けするライブラリを作ってみる。経過報告書

投稿者: | 2018年11月13日

visual studioでデータベースを扱うアプリを作ることがあるので、せっかくだしライブラリを作成しました。

経緯

詳しくはこちらのほうにまとめています。

このメモはその経過報告です。

プロジェクト

これがプロジェクトです

https://github.com/kura2391/vbsql

今まででできたこと

ここまででできたのは以下の通り。自分なりに工夫した点を述べておきます。

  • sqlを実行する関数の作成
  • sql文をすべてベタ書きする必要がないように
  • sql文の実行を数行でできるように
  • Hashtableを利用して、(特にinsert, update時)の多くの項目をそれなりに管理しやすく
  • ユーザー入力の可能性がある欄をプレースホルダーに

ここまでの感想

ここまでやってきたうえでの感想ですが、

大変でした。

多分これは私が初めて、オブジェクト指向を意識しながら書いたためだと思います。オブジェクト指向を意識しなかったらもっと早く作れたかもしれません。

でも、ここまででも十分にオブジェクト指向の良さを実感することができました。例えば、作成するクラスを大幅に変更することを決めたときです。

最初、vbに既に存在する、SqlClient.SqlParameterの機能を補うために、Parameterクラスを作り、こいつをリスト管理しようと考えたのですが、やっていくにつれて、

「最初から、複数形のParametersクラスにして、中にSqlClient.SqlParameter()を保存したほうが、オブジェクト指向ちっくなんじゃね?」

と思い変更することにしました。この時点で、Parameterクラスを使ってほぼすべての機能を実現していたので、絶対時間かかるやん、とめちゃくちゃ抵抗があったのですが、ところがどっこい。

1時間で終わった。すげぇ

いや、たぶん皆さんからしたら「小規模のアプリなんだし、そんなもんだろ。むしろ遅い」でしょうけど、私からしたら驚きでした。

まず作ることに抵抗が薄くなる。作っちゃおうと思えたことです。

前のような、手続き型でたくさん書いていくと、新規で作成するコードを同じファイルに書くことになり、ところどころコメントアウトしたり、ソースコードがすごく長くなって見にくくなったりしてました。
しかし、オブジェクト指向にすると、まずファイルが分かれる。そして、作成したプログラムは、別に呼び出さなければ使われることはなく、変更前の実行結果をすぐに取り戻すことができる。さらに、作成したプログラムを適用しよう!となったときも、必要な部分だけを変更するだけでほとんど正常に動くので「これは強い」と思いました。

想像以上にバグが少ない。

これは手続き型でもオブジェクト指向でも同じですが、機能改修の際は依存する箇所を探して変更しなければなりません。だもんで、手続き型だと、どの変数が依存していてどの関数が依存していないのかを見分けにくかったので、よくバグがこんにちはしました。授業と授業の間の5分休憩の時に毎回話しかけてくる、隣のクラスの(仮名)林君並みでした。あくまで表面的な例えです。

しかしオブジェクト指向だとどうでしょう。変数と関数はすべてクラス内にまとまっているため、基本的に変える場所は、クラスを呼び出しているところだけでよいのです。検索もしやすく、あっという間に終わりました。カプセル化(各関数のすることは決まっているが、関数の外側の人は具体的な処理を気にしなくてもよい構造)の考えを頑張って意識していたおかげかもしれません。

そして、依存関係が管理されているから、引き起こされるバグも心なしか少なく済みました。昼休みや放課後のまとまった時間に、ゲームやスポーツやらをして遊んだ(仮名)松坂君並みでした。

これだけで終わったなら幸せなのですが、もちろん大変なこともありました。

どうやってクラス分けするか

これです。この言葉に尽きます。子供たちの人間関係、学力差、男女比、様々なことを考慮しなくてはいけないので本当に大変でした。嘘です。

例えば、上述したParameter君。このアプリ作成当初の彼はとても扱いに困っていました。自分の考えた時系列順に述べていきます。

Parameter君には、プレースホルダーを管理してもらおうと考えました。つまり、

  • Where句でのプレースホルダー
  • Update, insert 句でのプレースホルダー

の二つを管理してほしかったのです。そうすると少し問題が生じました。

Update, Insert句では、ユーザーの入力文字列と、その文字列と対応する列名が必要なのですが、Where句では、対応する列名、という概念はありません。

具体例を挙げますね

この文では、Parameter君は二人必要で、
Parameter0君には、「id=?」の「?」の値(=110)を持ってもらい、
Parameter1君は、「date < ?」の「?」の値(=”2018-10-10″)を持ってもらえばよいのです。

しかし、この文では、
Parameter0君には、「id」と「?に入る値」を持ってほしく、
Parameter1君には、「date」と「?に入る値」を持ってほしかったのです。

この段階で、where句に使用するプレースホルダーと、update, insert句に使用するプレースホルダーは別物であるというとらえ方ができます。じゃぁクラス分けたらいいやん、となります。

が、どちらのプレースホルダーでも、8割以上同じ処理をしているのです。

ここでとれる選択肢は二つ。

  • 二つのParameter君を作り(=双子にする)、親となるクラス(=両親)を作って、同じ処理の部分は親から受け継ぐ
  • Parameter君はParameter君なので、個として強く生きてもらう(=何とかして一つのクラスで済ませる)

でも、Parameter君のソースコードの長さから考えても、絶対に双子にするのはコストの無駄だと思いました。

教師が生徒に対し、「お前は今日から双子だ」とは言えません。

どうしようどうしようと考えた結果、今のように、Parameters君になったという流れです。n人兄弟ならいいよね。良くないか。

変な例えがたくさん入っているので意味わからないとは思いますが、
要するに、私からすると

クラス分けの基準が難しい

のです。正直現段階で作成しているものも、こんなのでいいのか?と疑問符が付きます。一応、Zend Framework3のsqlAbstractの部分をチラ見して外側だけ真似しては見ましたが…不安。

これからすること

これからは主に

  • Transactionの仕組みを導入する。
  • where句の書き方が、バグを起こすことが分かっているのでその修正。
  • Where句の書き方をもう少し工夫してみたい。
  • 余裕ができたら、フォームのコントローラと列名を対応付けするライブラリの作成

をしていこうかなと。
ただ、バグを取り除けば、私の最低限の目標は達成できたと考えているので、少し頻度は落ちるかもしれません。

NuGetに公開するのか

NuGetとは、マイクロソフト公式のサイト(パッケージマネージャー?)で、有志が作成したライブラリを公開する場所です。ほかの人たちは、それらのライブラリを簡単にダウンロードし、使用することができるというものです。便利。

せっかくなら公開したらいいんじゃない?とは思ったのですが、いかんせんまだバグが残っているのですぐには公開しません。

また、実は似たような機能が、すでにVB側で実装されていることがわかっているので(CommandBuilderというらしい)、意味がないとまでは言いませんが、もう少し付加価値をつけてからのほうがいいのかなぁ。とか思っています。最低限のsql実行機能しかついていませんしね。せめてトランザクション等はしておきたい。

まとめ

以上、進行中のVbsqlの経過報告でした。
今後は若干落ちるかもしれませんが、時間のある時に進めて、まとめていきたいと思います。

後はほかの人たちからのアドバイスほしいかなぁ。
ぼこぼこにされるだろうけど。

ちなみに、私は「入り口は広いほうが良い」と考えている人なので
使い方のドキュメントもそれなりに頑張って作りたいと思います。Readme.mdファイルがその例です。初心者にとって、あれくらいは要ると思う。絶対いる。
一般的に、説明書が悪いと取り掛かりにくいですからね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA