既存ソースの修正で感じたこと
既存ソースの修正というのはあまりやったことがなかったが、今ちょっとボチボチとやっている。次の制約・制限がある。
C++だと、enum class(scoped enum)とメンバのsizeofは使いたかったが、これは使えない。「自分が使いたい」のは諦めればいいのだが、新しいライブリがコンパイルできないのが困った。最近のソースだと、右辺値参照が使われているものがあって、これはコンパイル通らないし、修正も難しい。
エンコーディングはShift_JIS、Doxygenはいちおう大丈夫だが設定・細工が必要。今となってはUTF-8のほうが何かと便利なのだが、しょうがないからiconvで対処する。
コーディングスタイルは、心理的にはけっこうキツいものがある。まー、これも慣れだけど。それと、絶対にスタイルを変えてはいけない、というわけではないので、どうしても気になる所は変えた。
機能追加や既存機能の拡張のときの話:
もとのソースはよくテストされて枯れたソースなので、無闇に変更はしたくない。イジらなくてよいところはそのまま使いたい。構造を変えるようなリファクタリングもリスキーだからしたくない。
で、困ったのは奥まった所にあるクラス(のインスタンス)へのアクセス。
アプリケーション(ライブラリに対するクライアント)から見えるクラスAがあって、
- クラスA -(メンバー変数b)→ クラスB
- クラスB -(メンバー変数c)→ クラスC
のようなプライベートな参照で繋がっているとする。BやCに外(アプリケーションコード)から触る必要がないのでプライベートになっているハズだ。
が、追加変更があると、トップレベルからCへの参照・操作が必要になったりする。アプリケーションから見える表層インターフェイスを担うAにメソッドを追加して、A→B→Cと、情報と指令が伝搬する経路を新設するのが正当的対処だろうがメンドクサイ。
んで、
- Aに B *getB() を追加する。
- Bに C *getC() を追加する。
- (a.getB())->getC() でCへのポインタを入手する。
- 手に入れたCを操作する。
とかしてしまう。
もともと、b→B, c→C という内部構造を隠したいからプライベートメンバーで参照しているのに、getB(), getC()を作ってしまった時点で、もとの設計の意図をダイナシにしている。一方で、表層から操作したくなるCを奥の奥のほうに隠してしまった初期設計がマズかった、とも言える。
「何を見せて、何を隠すか」という判断は設計のけっこう本質的な部分で、「隠す」と判断したものが後から「見えなくて困った」となるのは、初期設計が不都合になっているアカシだ。設計を変えるのがベストではある。が、設計から変えるのはやりたくない。だからジレンマが発生する。
既存クラスの下にサブクラスとして潜り込んで、新しいインターフェイスを作るとかも考える(一部やってる)が、必要な変数・メソッドがプライベートなので、protectedに変更する必要がある。ところが、変数のネーミングルールで、private, protected, publicの別が名前にエンコードされてたりする。鬱陶しい。
名前に色々な情報を刷り込むのは、リファクタリングのときは邪魔だなー。so-called“ハンガリアン”も、あんまり良いことはないと思うのだが、Windowsのソースコードではむしろ多数派だろう(最近は知らんが)。
僕としては、名前に接頭辞接尾辞を付けるのはやめて、プログラミング言語が提供している階層的名前空間を利用したいのだが、オーバーロードした簡潔な名前にも欠点がある。言い方を変えると、冗長な名前にもメリットがあるのだ。その話はまた別に書く。