DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

継承より部品化


    ______
   [__l二l|__    チュウゲン ダ
   ミ ,,゚Д゚彡__    ゴルァ
   ミ | ̄| ̄ ̄|
   ミ O__| ミカン| 
   し'` J ̄ ̄


暑い日々が続いていますが、
台風がきて、涼しくて節電ばっちりな、なでしこが勝ったような、今日この頃。
いかがお過ごしでしょうか。

本日はソースコードをお届けにあがりにきました。


以前は、「継承がコードの再利用性を高める。」と盲目的に信じられていた時代がありました。
最近はそうは言われてない気がします。

多くの人の勘違いを引き起こす正しくない情報が氾濫せずになくなっていってよかったです。

継承は、あまり再利用性には寄与してないというか
人のソースを引き継ぐときに、往々にして継承によって
物事が複雑怪奇になっている害が大きい場面があるので、
とても気をつけて使わないといけません。作るほうも使うほうも気苦労が大きいです。


継承による再利用性が高くないことについて、よくわかるように書かれたページがありました。
とても勉強になるページで、お勧めです。

オブジェクト指向再入門/なぜわからなくなってしまうのか?
http://kmaebashi.com/programmer/object/naze.html

  オブジェクト指向で再利用性は高まるか?

まさに、その通りということが書いてあります。

継承が再利用に大事なのではなく、再利用性を高めることが再利用に大事なのですよ。

※継承で再利用性が高まる場面もあるにはあるけど、逆に再利用性が低くなる場面もありますわな。


再利用するにはソースコードの部品化を行う必要があります。
継承やクラスによってそれを実現するもよし、
関数によってそれを実現するもよしです。


あるレベルの人には、当たり前(ダノクラッカー?)だと思いますが、
部品化というのはどうやるか、ってのをソースで書いてみておきます。

StringListのIndexOfを実装するならこうがよさそうよ。と。そういうことです。
VCLのライブラリレベルでこのように対応して欲しいと思っていますが、
対応してないから、拡張するしかないっすね。

ライブラリ拡張を思いつき、それを実行するのが腕の見せ所。

ということで、StringListクラスを継承して拡張するのではなく
今回の場合再利用性を考えるだけで問題ないので、
次のような、StringsのIndexOfを作ってみます。

空文字への対応
文字列の完全一致、大小文字区別しない一致
先頭文字列一致、部分文字列一致。

考えると、終端一致などあったり、タブ区切り行の2列目一致とか
まあ、いろいろあるのですが、そのいろいろの全対応するためのIndexOfです。

※確か、ComboBox.Items.IndexOfは空文字で誤動作してたんじゃないかな。
 使わないから忘れてしまったけれども。

function Strings_IndexOfFunc(Strings: TStrings; SubStr: String;
CompareFunc: TIndexOfCompareFunction;
StartIndex: Integer = 0): Integer;
var
 I: Integer;
begin
 Result := -1;
 for I := StartIndex to Strings.Count - 1 do
 begin
  if CompareFunc(Strings[I], SubStr) then
  begin
   Result := I;
   Break;
  end;
 end;
end;

 function NormalIndexOf(Line, SubStr: string): Boolean;
 begin
  Result := False;
  if Line = SubStr then
   Result := True;
 end;

function Strings_IndexOf(Strings: TStrings; SubStr: string; StartIndex: Integer = 0): Integer;
begin
 Result := Strings_IndexOfFunc(Strings, SubStr, NormalIndexOf, StartIndex);
end;

 function IgnoreCaseIndexOf(Line, SubStr: string): Boolean;
 begin
  Result := False;
  if SameText(Line, SubStr) then
   Result := True;
 end;

function Strings_IndexOfIgnoreCase(Strings: TStrings; SubStr: string; StartIndex: Integer = 0): Integer;
begin
 Result := Strings_IndexOfFunc(Strings, SubStr, IgnoreCaseIndexOf, StartIndex);
end;

 function FirstStrIndexOf(Line, SubStr: string): Boolean;
 begin
  Result := False;
  if 1 = Pos(SubStr, Line) then
   Result := True;
 end;

function Strings_IndexOfFirstStr(Strings: TStrings; SubStr: string; StartIndex: Integer = 0): Integer;
begin
 Result := Strings_IndexOfFunc(Strings, SubStr, FirstStrIndexOf, StartIndex);
end;

 function SubStrIndexOf(Line, SubStr: string): Boolean;
 begin
  Result := False;
  if 0 <> Pos(SubStr, Line) then
   Result := True;
 end;

function Strings_IndexOfSubStr(Strings: TStrings; SubStr: string; StartIndex: Integer = 0): Integer;
begin
 Result := Strings_IndexOfFunc(Strings, SubStr, SubStrIndexOf, StartIndex);
end;


Strings_IndexOfFuncにて、
比較関数を外だししているので、どんな一致条件でも
利用できるようになっていますし、

毎回比較関数を書くのもめんどくさいので
通常使いそうなものは、用意して組み込みしてみました。

このあたりの隠蔽は、ジョエルオンソフトウェアで言われている
『第26章 漏れのある抽象化の法則』
に載っている内容も含めて抽象化をしています。

使いやすいように抽象化する。
場合によっては、抽象化の内部に入っていって、自在に機能を変更することも可能。

汎用的であり、抽象化もされているので、なかなかよい部品だと思いますよ。

http://local.joelonsoftware.com/mediawiki/index.php/開発抽象化レイヤ
ジョエルの抽象化といっても、こっちで載っている概念とは全然違うけどね。


IndexOfにStartIndexがなぜ存在してるのかというと、

  SearchIndex := Strings_IndexOf(StrList1, 'TEST',0);
  //処理
  begin
   while SearchIndex <> -1 do
   begin
    SearchIndex := Strings_IndexOf(StrList1, 'TEST', SearchIndex + 1);
    //処理
   end;

こうやると列挙が簡単に行えるので、StartIndex指定を仕込んでいます。

ひとつの部品として、ご利用ください。
スポンサーサイト

| 未分類 | 12:52 | comments:0 | trackbacks(-) | TOP↑

COMMENT















非公開コメント

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。