質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

1293閲覧

(プログラミングの手法、方針について)Utilityクラスを作らないようにしたい

notgoodpg

総合スコア37

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2019/04/05 07:37

編集2019/04/09 00:04

結論

クラスを作成しstaticなメンバ関数を利用する方法とnamespaceを定義して非メンバ関数を利用する方法で悩みましたが、
最終的にnamespaceを定義する方向がよいのではないかという結論に至りました。

  • クラスはメンバ変数を追加したり利用したり出来るので「ついうっかり」神クラス化してしまうリスクがある
  • 汎用ライブラリでも同じ手法がとられている

ことが理由です。

前提・実現したいこと

宜しくお願い致します。

具体的に発生している問題を解決したいという質問ではなく、クソコードを量産したくないけどどうすれば良いだろう?という抽象的な質問です。

Utilityクラスを作らないようにしたい

仮に、
画像/映像処理オープンソースライブラリであるOpenCVを利用したプロジェクトにおいて
画像からあるスコアを算出するという目的を持ったクラスCImgPrf内で
「画像データを格納できる型Matに格納したデータを2値化したい!」という機能を以下ように実装したとします

c++

1// 20190408 ソースに戻り値の型がない問題、宣言していない変数を使っている点を変更しました。 2cv::Mat CImgPrf::MyThreshold(const cv::Mat & srcImg, const int lowThreshold, const int hightThresold) 3{ 4 //グレースケール化 5 cv::Mat gryImg; 6 cv::cvtColor(srcImg, gryImg, CV_BGR2GRAY); 7 //2値化 8 cv::Mat binImg; 9 cv::threshold(gryImg, binImg, lowThreshold, hightThresold, CV_THRESH_BINARY); 10 return binImg; 11} 12

ところがこの2値化する処理は、画像にある処理を施してその画像をメンバのリストに追加するCEditImgList内でも必要である
さらにその後、この2値化処理を必要とするクラスが後にどんどん増えてゆく・・・

とします。

そうした場合、

  • Utilityクラスを作っちゃうパターン

クラスを作ってメンバ関数として実装。
MyThresold()関数のみをメンバーに持ち、メンバ変数も活用しないごく短いクラスになるでしょう。

  • 静的関数だけのUtilityクラスを作っちゃうパターン

クラスを作ってpublic:static属性のついた関数として実装。
個人的にはここまでするとクラスとして定義する理由が希薄に感じます。

  • オブジェクト指向とは?パターン

namespaceを定義してその中に非メンバ関数(free-function)として実装。
クラスの旨みを使わないならクラスを使わなければいいんだ!的な発想。将来的にどうなってしまうか3つの中でもっとも想像のつかないパターンです。

の3パターンが思いつくのですがどの手法がよいか、または別に適切な方法があればご教授ください。
どの方法がどう駄目か、という意見でもありがたいです。
正しい方法は場合によりけりと思いますが、基本的な方針を決めることでコードの品質を上げられると思っています。そのために皆様にご意見を頂けると助かります。

###当質問のクローズ条件

もし回答をいただけなくても1週間程度でクローズします。

補足情報(FW/ツールのバージョンなど)

  • VC++
  • VisualStudio2015 SP1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

Utilityクラスを作らないようにしたい

なぜ? 適当なnamespaceにfree-functionを実装したら Utility名前空間をつくることになるけど、それならOKなの?

投稿2019/04/06 03:13

編集2019/04/06 03:19
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2019/04/08 02:44

ご回答ありがとうございます。 Utilityクラスを作りたくないのは永久に肥大化するコードを作りたくないためです。 ですが考えてみればUtility名前空間を作ってそのソースファイルに関数を追加していっても同じことですね・・・
episteme

2019/04/08 19:46

静的関数だけのUtilityクラスを作っちゃうのも実質名前空間内にfree-function並べるのと同じ。
notgoodpg

2019/04/08 23:54

ありがとうございます。 やっていることは同じなのですね。 クラスにstaticなメンバ関数を追加する方法だと 他人の手に管理が渡ってしまった場合やウッカリで、クラスとしての機能を拡張して神クラス化してしまうリスクを考えるとnamespaceを利用したほうがよさそうであると考えがまとまりました。
guest

0

または別に適切な方法があれば

共通化しないという選択肢.

「2値化」するにしても

  • 入力データのフォーマット
  • バッファを使いまわすかその場で作るか
  • どういう方法で2値化するのか,閾値等の決め方はどうするのか
  • etc

がふつーはその場その場で違うハズ.
そういうものを強引に纏めようとするメリットがどれだけあるのか疑問.

投稿2019/04/06 03:23

fana

総合スコア11632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2019/04/08 01:28

ご回答ありがとうございます。 確かにそういった要素がバラバラならば同じ関数を使いまわす必要はありませんね。
guest

0

汎用ライブラリの代表的なものとして Math ライブラリがありますので、「cmath (math.h)」や .NET Framework の「Math クラス」を参考にされるのが良いかと思います。

投稿2019/04/05 22:22

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2019/04/08 02:47

ご回答ありがとうございます。 既存のものを参考にしてみるのひとつの手ですね。
guest

0

あなたの思うそのそれぞれの方法で実際に実装してみましょう。
そして、それで実際にどうなるのかを自分自身で確かめてみることです。

きっとそれぞれの方法で何らかのメリットもあればデメリットもあるでしょうけど、それを判断するのはあなた自身でやってください

投稿2019/04/05 21:59

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2019/04/08 03:00

ご回答ありがとうございます。 方法としてはそれが一番確実ですね。 ただ、今までの試行錯誤で結局どの方法が良いのかが判断しきれないためにご意見を求めていますので「自分ならこうする」という意見を頂けたら助かります。
y_waiwai

2019/04/09 00:13

ならこれはダメという前提をつけるべきではないのでは
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問