• ベストアンサー

ゲッターを使わないで変数にアクセスする(java)

経験10年以上のベテランの人が privateフィールドに対してゲッターを使わないで、if (!checkExist(this.productCode))としていました。 自分は未経験ですが、privateフィールドのアクセスはゲッターを使うべきだと思いましたし、“!”を使うのは分かりにくいのでif (checkExist(getProductCode()) == false)としました。 どちらの方が良いコードですか?

  • Java
  • 回答数8
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

ベテランの書き方のほうが自分はいいと思います。 何かを金科玉条のごとく信じるほうが簡単で楽ですが、時間が経つとそういう根拠がわからない金科玉条は有害でしかありません。getter / setterを常に使うという金科玉条があるようですが、その盲信を自分は有害だと思います。 そもそも、getter / setterって何のためにあるのでしょうか? 自分は内部のデータ構造を外部に見せないためのカプセル化やData Abstractionの実現のためにあると思います。 ありがちな例で恐縮ですが、座標を表すPointクラスを実装することを考えましょう。 直感的にもわかりやすく、画面へのプロットもしやすいので最初は直交座標系 (x,y) で作るでしょう。 そして、しばらくした後、回転をサポートしないといけなくなりました。今後は回転をよく使うプログラムになりそうなので、極座標系 (r,θ)で作ったほうがよさそうです。 getter / setterがある場合、このクラスの書き換えだけで内部データを極座標系に変更できます。しかし、getter / setterを使わず、クラス外から直接xやyを参照、代入されている場合はxやyを使っているプログラム全部を極座標系対応のコードに書き換える必要があり、大規模修繕が必要になります。 自分はこの状況を避けるためにgetter / setterがあると思います。 同一クラス内の場合、そのメンバーや実装に変更をする場合は必然的にクラス全体の変更を余儀なくされるでしょうからgetterに拘る必要はないと思います。this.productCodeがgetProductCode()に単純に置き換わるなら、なおさらです。それに、そこが壊れた場合ユニットテストで簡単に見つかりそうです。 "!"をboolean型に対して使うのはいいと思います。if文が条件が満たされない時に発行されると見た瞬間に理解できますので。 余談ですが、プログラムを読むときは段々英文を読む感覚で読むようになってきますし、普通checkは条件が成立する場合はtrueを返すので、if (!checkExist(this.productCode))だと、if not exist productCode と読めます。これが、if (checkExist(getProductCode()) == false)だと、if exist check for gotten productCode is falseとなります。まず、余計なgetが読みづらいですし、否定があとに出てくるので更に読みにくいです。 というわけで、ベテランになればなるほどベテランの書き方になってくると思います。また、そちらのほうが可読性が高いと思います。

その他の回答 (7)

回答No.8

No.7 の補足。 私が使っているコーディング標準ではベテラン氏の書き方でないとダメですね。 それと checkExist は私が使っているコーディング標準の命名規約では違反になってしまいます。 exits か productCodeExists でないとぺけです。 理由は英語として不自然だからです。 この規則はメソッド名が名刺から始まる得る例のひとつになっています。

回答No.7

>if (!checkExist(this.productCode)) 普通だと思います。private のフィールドが属すクラス内でまで setter/getter にこだわるのは変。目的を振り返りましょう。 必要に応じて使い分けましょう。 >if (checkExist(getProductCode()) == false) 見慣れないので見にくいですね。! の方が好きです。 でも Pascal 系の not はもっと好きです(^^;

  • root139
  • ベストアンサー率60% (488/809)
回答No.6

この質問には、下記の2つの問題が含まれているかと思います。 a. private フィールドに対するアクセッサ(getter, setter)使用の是非 b. if文においての boolean メソッド・フィールド・変数の扱い まず、aのアクセッサの件ですが、個人的な意見としては、使う必要性が特に無い場合は直接アクセスでも問題無いと思います。もちろん遅延初期化/キャッシュなどを行っている場合はアクセッサを使用する必要が出てきますが、必要になった段階で変更すれば良いでしょう。 アクセッサを使う事でプロパティの実装に関するコードを局所化できるというメリットは有りますが、private フィールドの変更が負担になるほどクラスが肥大化しているなら、そっちの方が問題かと思います。 著名なプログラミングに関する本でも杓子定規にアクセッサを使用することは無いという意見がが多い様に感じますが、スコット・W・アンブラーはアクセッサ使用派ですね。 http://www.alles.or.jp/~torutk/oojava/codingStandard/writingrobustjavacode_pidid93_c3.html#doc1_id785 次に、bのif文やwhichなどにおいての boolean メソッド・フィールド・変数の扱いですが、こちらも「== true」「== false」は付けない方が分かりやすいと思います。 下記の様なコードを考えてみたとき・・・ ---------------------------------------- List<?> bookList = new ArrayList<Book>(); if (bookList.isEmpty()) { // (1)  // ・・・ } if (bookList.isEmpty() == true) { // (2)  // ・・・ } ---------------------------------------- (1) は「If bookList is empty ・・・」(もしブックリストが空ならば、・・・)と素直に読めますが、(2)は「If bookList is empty equal true ・・・」(もし『ブックリストが空』が真と同じならば、・・・)の様な回りくどい表現に感じます。確かに「!」が入ると素直には読めなくなりますが、それでも「== false」を付けるよりはストレートに条件を表現していると思います。 否定形よりも肯定系の方が分かりやすいという面はありますが、文全体を見て判断する必要が有ります。日本語で考えても「今日でなければ」という表現を「『今日であれば』が違っていたら」と否定形を使わずに言い直しても、かえって分かりづらいでしょう。 また、間違えて「=」にした際もコンパイルエラーにならない場合がある点も嫌ですね。 例) ------------------------------------ if (hoge = false) { // コンパイルエラーにならず、このブロックは絶対に実行されない  // ・・・ } ---------------------------------------- 確かに、if文やwhich文の条件式に比較演算子が入らないと分かりづらいと感じる人は少なくないようですが、Javaのコーディング標準に良く見られる「bool値を返すメソッドは、is + 形容詞、もしくは三単元動詞とする」という形式は、明らかに比較演算子を使わない書き方を意識しているものと思われますので、Javaのコーディングに限ってはその様な形式に慣れてもらった方が良いでしょう。 長々とコードの形式の是非を書いた後で恐縮ですが、この様な書き方に関する問題はコーディング標準やプロジェクトの慣習に従っていることの方が重要で、もしベテランの方が1人だけコーディング標準から外れる書き方をしているなら、そちらの方が悪いコードという事になります。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

個人的には「ベテランの人」の方が好みだけど.... どっちにしても「checkExist」ってメソッド名が気にいらない. #2 では「普通checkは条件が成立する場合はtrueを返す」って書いてあるけど, 私はそこまで他人 (昨日以前や明日以降の自分を含む) を信用できない. むしろ if (! existProductCode()) とかしちゃうなぁ. ただ, exist なのか have なのか has なのかで困るかも.

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.4

「なぜ、privateフィールドにgetterを使わないでアクセスできるの??」と思ったら、同クラス内の話ですか。 他の方の書いているように、ベテランの方の書き方が正しいです。 >if (checkExist(getProductCode()) == false) は、間違いとまでは言いませんが、変。 また、そもそも、getter/setterと言っている時点でオブジェクト指向での設計が足りない(クラスを構造体のように思っている)です。

  • mintia007
  • ベストアンサー率59% (16/27)
回答No.3

外部クラスからフィールドをアクセスする時にサクセッサメソッドを持たせるのでは? >if (checkExist(getProductCode()) == false) だとパッと見で外部クラスのgetProductCode()を呼び出していると思ってしまうのは自分だけかな? (「オブジェクト名.」が指定してないので自クラスって分かるけどね) thisの方が自クラスのフィールドって速攻で分かるので。 但し、ゲッターでフィールド値の取得だけではなく、何かしら判断文などの処理が入るようなら別ですが。 会議とかでコーディング規約について論議しても良いですし、品証・品管部門とかがあったら相談してみては?

  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.1

>privateフィールドに対してゲッターを使わないで、if (!checkExist(this.productCode))としていました。 それだけではなんともいえないと思います。 getterがprivateフィールドの値をそのまま返すとも限りませんし。 ケースバイケースじゃないかと。 >“!”を使うのは分かりにくいのでif (checkExist(getProductCode()) == false)としました。 別にわかりにくくないと思いますけど。 むしろ if (checkExist(getProductCode()) == false) と書く人は if (checkExist(getProductCode()) == true) と書きそうなのがいや。

関連するQ&A

  • JAVA初心者です。

    javaにおけるprivateメンバの動きについて伺いたいことがございます。 基本的にスーパークラスのprivateなメンバへはメソッド・フィールドともにサブクラスからは アクセスできないとのことですが、 例えば、以下のようなコードがあるとします。 //スーパークラスの定義 class SuperClass{ private String privateString = "スーパークラスのプライベートメンバ"; public void getter(){ System.out.println(this.privateString); } } //サブクラス class SubClass extends SuperClass{ } //実行クラス class RunClass { static public void main (String args []){ SubClass subObj; subObj = new SubClass(); subObj.getter(); } } 上記のようなコードの場合サブクラスのインスタンスであるsubObjが スーパークラスのpublicなメソッドを通じてサブクラスからスーパークラスのprivateメンバへアクセスが できてしまっています。 これは、スーパークラスのprivateが隠蔽されていないのではないでしょうか? 果たして、このときいったサブクラスのインスタンスのsubObjはどういった動きをしているのでしょうか?

    • ベストアンサー
    • Java
  • .netからアクセスへの配列変数渡しについて

    .NET 2010でアクセスのモジュールを実行させようとしております。 アクセスに配列を引数にしようとしていますが “Public ReadOnly Default Propety Chars(index as Integer) as Charに対する引数が多すぎます。” のエラーが発生しており困っております。 これはどのようなことが原因でエラーが発生しているのでしょうか。 また、解決策がありましたらご教授していただけないでしょうか。 .net側 Private sub AcsRun() Dim strdata as string Dim pData(50,10) as object Strdata =数値1 pData(1,1) = 文字2 pData(2,1) = 数値2     ・・・・・・・   ‘ここでpDataでエラーがでます。 If app.Run("AcsMdl"( Strdata, pData) = False) Then    Exit sub End If End sub アクセス側 Public Function AcsMdl (Strdata As Integer, pData () As Variant) As Integer AcsMdl = false ‘処理 AcsMdl = true End function

  • ネストしたenumへのリフレクションによるアクセス

    public class Game {   // ゲームの状態   private enum GameState{    TITLE,    PLAYING,    GAMEOVER,   }   private GameState state; } 上記のクラスに対して、JUnitのテストコードから、 メンバ変数のstateの値とenum定数 GameState.TITLEとの比較がしたいと思っています。 イメージとしては、 if(state == GameState.TITLE){ ..... } のような形です。 GameStateがprivateで宣言されているため、テストコードからはリフレクションを使用すればアクセスできるのではないかと思っているのですが、ネストしたクラスにどのようにアクセスすればよいのかがわかりません。 テストコードにて、 Game game; Class<? extends Game> c = game.getClass(); // GameState取得 Field e = c.getDeclaredField("GameState"); とすると、実行時にGameStateがないと言われてテストに失敗してしまします。 テストコードからGameStateにアクセスするにはどのようにすればよいのでしょうか?

    • ベストアンサー
    • Java
  • 「引数の書き方」と「メンバ変数とメンバ関数の名前」について、教えてくだ

    「引数の書き方」と「メンバ変数とメンバ関数の名前」について、教えてください。 クラス内のコード抜粋なのですが、下記はどういう意味なのでしょうか? ▼メンバ変数 var $j = true; ▼メンバ関数 function j($p = false){ if($p) $this->j = false; return $this->j; } $this->j(true); 分からないこと ・コードの意味全般 ・($p = false)と書かれている引数の意味 ・メンバ変数とメンバ関数の名前は同じでもよいか? 

    • ベストアンサー
    • PHP
  • タチウオを釣りたいです(ゲッター&浮き)

    釣り自体初心者でアジのサビキしか経験がありません。 周囲がタチウオ、タチウオと盛り上がるので タチウオゲッターが簡単そうだと思い、二回ほど 我流でやってみましたが、エソとかいうのが まぐれで釣れたっきりです。 周囲も、人に教えるほど上手な人がいてません。 できれば、タチウオゲッターで釣ってみたいので タチウオゲッターでの釣り方のコツみたいなのがあれば 教えてください。 自分がやったのは、泉佐野の一文字の朝マズメと 貝塚のテトラの夕マズメから午後8時迄で あたりはありませんでした。 デッドスローでただ巻とあったので、その通りが基本でやりました。 今考えると、竿の角度や、仕掛けが沈み過ぎ?あたりが 思い当たる節です。竿の角度とかも関係あるんでしょうか? 再来週あたりに、加太か兵庫方面のどちらかに リベンジしにいこうと思っています。 余談ですが、浮き釣りの方が釣れるんですか? 竿はちょい投げ用の180と磯竿の450があります。 タチウオ釣りする時の使い分けというか 向き不向きみたいなのがあれば、それも教えてください。

  • ACCESS VBA でのCSV取込エラー

    ACCESS VBA でのCSV取込エラー ACCESSにてフォルダ内にあるCSVファイルをすべてインポートしようとしています。 インポート定義を作成して、下記のコードを書いてみましたが、 データはすべてインポートされるのですが、 カンマが無視され、フィールドとフィールドの中間で途切れてデータが格納されてしまいます。 またフィールド4は日付形式なのですがこれがインポートエラーになります。 フィールド1 フィールド2 フィールド3 フィールド4 aaa aa,bbb bbb,ccc  エラー 2日間ほどネットサーフィンをして調べたのですが、 回避方法が見つからなかったので、お知恵を拝借できますでしょうか? よろしくお願いいたします。 Private Sub cmd06_Click() Dim MyFile As String Dim MyName As String Dim strFolderName As String DoCmd.SetWarnings False DoCmd.OpenQuery "Q09_全CSVデータ削除" DoCmd.SetWarnings True strFolderName = GetFolderName() 'フォルダ選択ダイアログを表示 If Len(strFolderName) > 0 Then '選択結果を評価 MyFile = strFolderName & "\*.csv" '【拡張子csvのファイルのみ取得】 MyName = Dir(MyFile, vbNormal) Do While MyName <> "" If MyName <> "." And MyName <> ".." Then If GetAttr(strFolderName & "\" & MyName) <> vbDirectory Then DoCmd.TransferText acImportFixed, "インポート定義", "T03_全CSVデータ", strFolderName & "\" & MyName, False, "" '【取得したファイルをインポート】 End If End If MyName = Dir Loop Else MsgBox "フォルダは選択されませんでした" End If MsgBox "データのインポートが終了しました" End Sub

  • Access の非連結テキストボックスについて

    Access 2000 を使用しています。 フィールド名 データ型 Code     テキスト型(フィールドサイズ=8) Name     テキスト型(フィールドサイズ=50) というテーブルがあり、このテーブルを元に帳票フォームを作成しました。このフォームは参照用として使用したいので、 AllowEdits/更新の許可 AllowDeletions/削除の許可 AllowAdditions/追加の許可 のプロパティは全て「いいえ」にしてあります。 このフォームのフッタ部分に txtFilter というテキストボックスと cmdFilter というコマンドボタンを置き、フィルターの動作をさせるため、 Private Sub cmdFilter_Click()   If IsNull(txtFilter.Value) Then     FilterOn = False   Else     Filter = "Code LIKE """ & txtFilter.Value & "*"""     FilterOn = True   End If End Sub としました。(見やすくするため全角空白を使用しています。) さらに、txtFilter に 8文字 ( Code フィールドのフィールドサイズ ) 以上は入力できないようにしようと思い、 Private Sub txtFilter_KeyPress(KeyAscii As Integer)   If KeyAscii <> 8 Then     'Delete 以外の場合     If Len(txtFilter.Text) = 8 Then       KeyAscii = 0     End If   End If End Sub としましたが、ここで問題が起きました。 ・FilterOn = False あるいは、 ・FilterOn = True でも何レコードが表示されている状態(該当レコードが存在する文字が txtFilter に入力されている) という場合は良いのですが、該当レコードが存在しない場合、 txtFilter に入力されている文字を変更しようとすると、 txtFilter_KeyPress() 中の If Len(txtFilter.Text) = 8 Then のところで「実行時エラー'2185' コントロールがフォーカスを取得していないときに、コントロールのプロパティまたはメソッドを参照することはできません。」となってしまいます。 入力中のコントロールですから、「そんな馬鹿な!?」という感じなんですが、 If Len(txtFilter.Text) = 8 Then の前に txtFilter.SetFocus を入れても状況は同じでした。 フォームの「AllowAdditions/追加の許可」プロパティを「はい」にすれば、上記のようなエラーは発生しないのですが(なぜ、「AllowAdditions/追加の許可」プロパティの違いでそのようなことになるのかは理解できませんが)、ユーザーにデータの変更や追加、削除はさせたくないテーブルなので、追加を許すわけにもいきません。 何かいい回避方法はありませんでしょうか。 よろしくお願いします。

  • アクセスADOで更新クエリがエラーになる

    アクセスからYES/NO型をを含むテーブルをSQLサーバーへ移行したのですが アクセスから更新クエリを使ってYES/NO型のフィールドを全てFalseにしたいのですがエラーになってしまいます。 cn.Execute "UPDATE テーブル SET 返事 = False" このコードを アクセスからADOを使ってアクセスのテーブルに対して行えば問題なくできるのですが そのままSQLサーバーのテーブルに対して実行すると 「列名'False'が無効です」 となります。 そもそも列名は「False」ではなく「返事」です。 SQLサーバーでのデータ型は「bit」になっています。 何かわかる方御回答よろしくお願いします。

  • accessの文法

    access2000です。 フォーム更新後に フォーム上のテキスト34に、クエリ3のフィールド「年」を代入して表示させるとき こうでいいのでしょうか? Private Sub テキスト34_AfterUpdate() Me.テキスト34 = [クエリ3]![年] End Sub

  • アクセス2000

    教えてください。 アクセス2000で下記の構文の’原価’という項目を追加したいのですが、 テキストに参照してきてくれません。’人工’は追加できたのですが・・・・ テーブル・クエリ・等はフィールド追加しているのですが・・・ 何が悪いのでしょうか・・・ Private Sub 商品コード_AfterUpdate() 'テキストボックスに商品コードコンボボックスの値を代入します Me!品名 = Me!商品コード.Column(1) Me!単位 = Me!商品コード.Column(2) Me!単価 = Me!商品コード.Column(3) Me!人工 = Me!商品コード.Column(4) Me!原価 = Me!商品コード.Column(5)

専門家に質問してみよう