添付ファイルの追加

ログイン済のユーザのみが添付ファイルをアップロード出来ます。

添付ファイル一覧

Kind Attachment Name Size Version Date Modified Author Change note
png
custocompany1.png 3.3 kB 1 25-6-2011 03:28 ytp
png
custocompany2.png 4.1 kB 1 25-6-2011 03:28 ytp
png
name.png 8.2 kB 4 31-12-2011 21:46 ytp
png
name2.png 8.3 kB 3 31-12-2011 21:43 ytp
png
supplyer.png 3.4 kB 1 25-6-2011 03:28 ytp

This page (revision-22) was last changed on 25-7-2014 20:50 by ytp

This page was created on 23-5-2011 01:03 by ytp

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Difference between version and

At line 9 changed 2 lines
[{Image src='img.jpg'}]
「担当者姓」と「担当者名」という属性がこのクラスの中にはあります。そしてこの二つの値を使ったメソッド「担当者氏名を返す」を考えてみます。姓と名の間にスペースを挟んで返す仕様だとします。コードは次のようになるでしょう。
[{Image src='custocompany1.png'}]
「担当者姓」と「担当者名」という属性がこのクラスの中にはあります。そしてこの二つの値を使ったメソッド「担当者氏名を返す」を作ってみます。姓と名の間にスペースを挟んで返す仕様だとすると、コードは次のようになるでしょう。
At line 20 added one line
[{Image src='custocompany2.png'}]
At line 45 changed 2 lines
が、果たして本当にそうでしょうか?
例えば「仕入れ先」クラスが別にあったとして、その属性にも「担当者姓」「担当者名」があったとしたらどうでしょう? そしてそのクラスにも「担当者氏名を返す」というメソッドが必要で、「姓と名の間にスペースを2つ挟む」という仕様だったら? そのクラスにも同じようなprivateメソッドが必要になってしまい、仕様変更への対応が1ヶ所というわけにいかなくなってしまいます。\\
が、果たして本当にそうでしょうか?\\
[{Image src='custocompany1.png'}]
例えば「仕入れ先会社」クラスが別にあったとして、その属性にも「担当者姓」「担当者名」があったとしたらどうでしょう? そしてそのクラスにも「担当者氏名を返す」というメソッドが必要で、「姓と名の間にスペースを2つ挟む」という仕様だったら? そのクラスにも同じようなprivateメソッドが必要になってしまい、仕様変更への対応が1ヶ所というわけにいかなくなってしまいます。\\
At line 48 changed one line
!!privateメソッドとは何か?
!!データ構造を見逃すな!
At line 50 changed one line
privateメソッドはクラス内の共通関数に当たるのですが、共通関数を作ろうとすれば、その関数に渡すパラメータをそもそもまず共通化する必要があります。そのパラメータをひとかたまり(データ構造)とするクラスを作るべきなんです。
privateメソッドはクラス内の共通関数に当たるのですが、共通関数を作ろうとすれば、その関数に渡す__パラメータをそもそもまず共通化する必要があります__。そのパラメータをひとかたまり(データ構造)とするクラスを作るべきなのです。\\
この場合は、属性として「姓」と「名」を持つ「氏名クラス」を作るべきです。
At line 53 changed one line
パラメータの無い、つまり「共通関数ですらない」privateメソッドがなぜ必要なのでしょうか?\\
パラメータの無い、つまり__共通関数ですらないprivateメソッド__がなぜ必要なのでしょうか?\\
At line 55 changed one line
なぜならコードが長くなるのは、上記のような小物クラスを見逃しまくっていて、結果的に手続き的な記述になっているからだと断言できます。そもそも一連の処理ならばprivateメソッドなどに分割せず、処理の流れの通りに1ヶ所に書いてある方が、第三者が見た時の可読性は高いはずです。下の例を比べてみて下さい。
なぜならコードが長くなるのは、上記のような小物クラスを見逃しまくっていて、結果的に手続き的な記述になっているからだと断言できます。クラスという単位で本来分割されているべきものが一つになってしまっていれば、その中の記述が長くなってしまうのは当然です。\\
そもそも一連の処理ならばprivateメソッドなどに分割せず、処理の流れの通りに1ヶ所に書いてある方が、第三者が見た時の可読性は高いはずです。下の例を比べてみて下さい。\\
!privateメソッドに分割した例
At line 91 added one line
!一連の処理が1ヶ所に書いてある例
At line 108 changed one line
属性の周りをメソッドが取り巻いている形が解ると思いますが、これは裏返すと、「属性を隠蔽するためにメソッドが口を開けている」ということです。つまり公開されないメソッドは原則に反するのです。privateによって隠蔽するべきなのは属性であってメソッドではありません。\\
フィールド(属性)の周りをメソッドが取り巻いている形が見えますが、これは裏返すと、「フィールドを隠蔽するためにメソッドが口を開けている」ということです。つまり公開されないメソッドはこの原則に反するのです。privateによって隠蔽するべきなのはフィールドであってメソッドではないという原則がこの図からも解ります。\\
At line 111 changed one line
こういう場合に皆さんが思いつくのはユーティリティクラスと呼ばれる「関数」ではありませんか? 次のようなコードです。
「『担当者氏名を返す』メソッドはprivateではなくユーティリティクラスでいいじゃないか?」と思った人もいるでしょう。\\
次のようなコードです。
At line 133 changed 6 lines
別のページでも書きましたが、このようなユーティリティクラス(インスタンス変数にもクラス変数にもアクセスしないメソッド群)はそもそもオブジェクト指向の原則である「データ構造と関数の一体化」を崩してしまいます。その結果どういう事が起きるかを考えてみます。\\
システムを国際化対応する必要がもしも出てきて、「担当者ミドルネーム」「代表者ミドルネーム」という属性が追加になったとします。この時、「氏名を返すメソッドは全て『姓 ミドルネーム 名』(間のスペースは一つずつ)とする」という要件に替わったとします。\\
この場合の変更箇所はStringUtility.getFullName()メソッドのみではなく、それを呼び出している全メソッドが対象となってしまいます。\\
なぜそうなってしまうかというと、「データ構造と関数が分離されているから」です。オブジェクト指向のメリットは「データ構造と関数の一体化」 によって産まれるのに、それに従っていない造りだからです。\\
!!だからprivateメソッド禁止!
上記のコードがどこで間違ったかというと、privateメソッドを作りたくなった時にクラスを見逃したからです。
[ユーティリティクラス禁止]でも書きましたが、このようなユーティリティクラス(インスタンス変数にもクラス変数にもアクセスしないメソッド群)はそもそもオブジェクト指向の原則である「データ構造と関数の一体化」を崩してしまいます。その結果どういう事が起きるかを考えてみます。\\
上記のStringUtility#getFullName()メソッドは単なる関数なので、姓名の連結のみに使われる保証はありません。極端な場合は次のような使われ方をするかもしれません。\\
%%prettify
{{{
public class Jimusho {
private String yuubinBangou = "";
private String jyuusho = "";
:
:
public String getAtesaki() {
return StringUtility.getFullName(this.yuubinBangou, this.jyuusho);
}
}
}}}
/%
StringUtility#getFullName()メソッドの機能は、「1つめのパラメータと2つめのパラメータを2個のスペースを挟んで連結する」というものです。上記のように、「事務所クラスの宛先を返すメソッド」にこの機能がたまたま使えたとすれば使われる可能性を排除できません。\\
この時、システムを国際化対応する必要がもしも出てきて、「担当者ミドルネーム」「代表者ミドルネーム」という属性が追加になったとします。そして、「氏名を返すメソッドは全て『姓 ミドルネーム 名』(間のスペースは一つずつ)とする」という要件に替わったとします。\\
この場合の変更箇所はStringUtility.getFullName()メソッドのみではなく、それを呼び出している全メソッドが対象となります(当然ですが)。その際、「従業員クラスの宛先を返すメソッド」も該当しますが、事務所クラスは「ミドルネーム」を持たないため破綻してしまいます。別の関数を新たに作る必要が出てきます。\\
一方で、「氏名クラス」を利用している場合はどうでしょう?
Version Date Modified Size Author Changes ... Change note
22 25-7-2014 20:50 7.789 kB ytp to previous
21 31-12-2011 21:42 7.791 kB ytp to previous | to last
« This page (revision-22) was last changed on 25-7-2014 20:50 by ytp