質問するログイン新規登録
オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

6回答

574閲覧

【オブジェクト指向】ファイル形式に依存する共通処理は、どのように責務を分離するべきか

sakuusa

総合スコア0

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

1クリップ

投稿2025/09/21 00:13

編集2025/09/21 00:15

0

1

Pythonを使ったオブジェクト指向で、text / csv / excel(xlsx) のテキスト部分を書き換えるコードを書こうと思っています。
具体的にはファイルと置換前後の辞書を取り、それを書き換えたファイルを出力させたいというのがおおまかなやりたいことです。

入力:

  • file_path : "path/to/file"
  • translate_dict: {"sato": "<DELETED_1>", "kato": "<DELETED_2>", ...}

出力:

  • file_path: "path/to/translated_file" # 元ファイルのsatoを<DELETED_1>に、katoを<DELETED_2>に置換した、入力と同じ拡張子のファイル

ここでファイルの拡張子ごとにオブジェクトを作成するのが筋がよいのかなと思いました。

class (メソッドはすべて同じ):

  • TextHandler
    • _load(path: str) # ファイルを読み込む。初期化で呼び、読込結果はプライベート変数に保存。
    • to_text() -> str # ファイル内容を文字列型で表示。ロギング用。
    • replace(d: dict[str, str]) -> str # _loadで読んだプライベート変数を元に置換処理。置換結果はファイルに書き込む。置換後のファイルパスを返す。
  • CsvHandler
  • ExcelHandler

このようにすることで、それぞれの固有の置換処理を実装できると考えています。

  • text: str.formatを用い置換します
  • csv: それぞれのセルをstr.formatで置換する
  • excel: xlsxをzipとして展開し、内部の複数あるxmlファイル中の属性やテキストノードをすべて置換する

一方で、それぞれのクラス内に、一般的な処理である置換がはいるのは、どこか違和感があります。
実装的な意味では置換はtext / excelで全くしていることが異なります (textは文字列置換だが、csvはセルごとの置換で、excelはzipで解凍した複数のxmlファイルのノード置換) が、抽象的には内部の文字列を置き換える、という普遍的なことを行っているからです。
置換を拡張したい場合、それぞれのクラスのreplace関数3箇所を変更する必要があります。
しかし、置換をclass Replacer等として外に出そうとすると、Replacerは入力型としてstr, list[str], list[list[str]], list[xml_file] (あるいはpath_to_zip: str?) を扱う必要があり、責務が重い気がしています...

より良い設計があれば教えていただけると嬉しいです。
よろしくお願いします。

その他:

  • 現在のユースケースでは、置換処理は1ファイル1度しか呼ばれません。
  • 質問者について: オブジェクト指向初心者 (オブジェクト指向でなぜつくるのかを読んで、オブジェクト指向設計実践ガイドを買った) です。メインで使う言語はpythonで、大学以降6年程度触っています。会社はIT系で、プログラミングもしますが、perl / shell script / js / css 等の保守が多いです。

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

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

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

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

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

fana

2025/09/22 01:50

> 置換をclass Replacer等として外に出そうとすると、Replacerは入力型としてstr, list[str], list[list[str]], list[xml_file] (あるいはpath_to_zip: str?) を扱う必要があり (当方,pythonはわからないのですが)ココって str(単一の文字列)だけじゃダメなんでしょうか? (:文字列の集合を扱いたい場面では,その集合の各要素(:単一の文字列)について変換処理を実施するのではダメ?)
xebme

2025/09/23 14:31

単純な置換を行うとして、前後処理が必要ですね。 前処理は、分解処理を実行して置換単位(仮にトークンと呼びます)を切り出す。(DECOMPOSER) 後処理は、置換された単位を使用してもとの形式を組み立てる。(COMPOSER) 処理フロー(DECOMPOSE -> REPLACE -> COMPOSE)を固定するとして、各ファイル形式の処理のポリモーフィズムがイメージできるかですね。試作品を作れば質問が具体的になりますね。
xebme

2025/09/25 01:05 編集

> Replacerは入力型としてstr, list[str], list[list[str]], list[xml_file] (あるいはpath_to_zip: str?) を扱う必要があり この考えを一旦捨てて、XMLだけに集中してください。XMLをDOMのまま処理すれば簡単になりませんか。 つくってからリファクタリングもできますが。対話が成り立たないのでこれで終わります。
guest

回答6

0

ここでファイルの拡張子ごとにオブジェクトを作成する
これ、オブジェクトではなくクラスのことですよね。

それこそ所謂継承を使うとすっきり書ける典型例ではないかと思います。

基底クラスで共通の処理を実装し、ファイルタイプごとの処理は子クラスに実装です。ファイルタイプ ごとの処理を外に出さないので、変数などの扱いがすっきりするはず。

継承は使うべきでないという風潮はありますが、それも使いどころによるので、すっきりしたわかりやすい実装ができるのであれば、避ける必要は無いと思っています。

投稿2025/09/21 03:01

編集2025/09/21 03:06
TakaiY

総合スコア14641

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

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

0

コードが頭の中で"見えて"いらっしゃるなら、書いてみると良いのでは無いでしょうか。
で、(可能なら)それをご提示されれば、それを元に実際に分けて試す等出来ると思います。

投稿2025/09/21 02:47

jimbe

総合スコア13422

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

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

0

これってそもそも何をしたいんだろう?
普遍的に考えるとCSVやEXCELって相互にファイル変換可能で恐らくPythonにファイル形式を変更するようなライブラリもあるんじゃないかとおもう。もちろんtextにも変えられるでしょうし。(Excelをどう見るかというのはありますが。)

つまり、このケースではないけどもしも、ある文字列を置き換えたファイルを新しく作りたいってなった時、text(やCSVなどオリジナル)と置換ルールがあれば、出力結果はExcelにもCSVにもtextにも出来るという話になる。
これって別に共通化のテーマとズレた話ではないと思うのだけど、例えば継承で具体的な実装を継承すると仮定するなら一体何が得られるんだろう?

また、もっとこの質問にそったことを言えばそもそもとして置き換え機能を拡張するというのは具体的に何を想定しているんだろう?
例えば内部で定数を持っててその値を書き換えることしか出来ないというのが不便なら引数で受け取ればいい話だけど、その引数を変えることで内部的な実装を拡張するような事は起きない気がする。
多分具体的なコードを書いていて、改編時に面倒事に気づいたのかもしれないけれど想像する限り何をしたいのかが分からない

投稿2025/09/24 04:28

編集2025/09/24 04:28
u2025

総合スコア101

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

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

0

何処までオブジェクト指向プログラミングで「描くか」次第ですね
質問の中身としては下記が考えられます。

  • 結局やることが違うんだからReplaceを2-3個書けばええねん
    • これも十分正解
    • YAMLファイルやJSONファイルのキー情報は書き換えたくないよ、String型の文字列だけ検索して欲しいよみたいな要望出たらどうすんねん
  • 継承機能でSuperクラスに持たせる
    • 最近は飛び道具だらけになって読みづらいわという事で継承は敬遠されがち
  • Replaceを行う専用のオブジェクトを作ってDIコンテナで突っ込む
    • 記述量は多少増えるが、テストは死ぬほどしやすい
  • Replaceを行う処理を関数化してそれぞれが読み込む
    • これもありっちゃあり

リーダブルコード曰く「美しいコードというのは、そのコードを読んだ時に瞬時に理解して、短時間で情報を沢山吸い上げられる」と定義されています(文章そのままではないのでちょっと違うかも知れません

結局書いてみて、読んでみないとなんとも言えない所があります。
まぁ数行程度ならベターとコピペで書いちゃうのが一番だと思いますけどね。

色々実際にコードに起こしてみて比較してみましょう。
ChatGPT5に聞いてみても良いかも知れませんね。

投稿2025/09/22 04:05

miyabi-sun

総合スコア21548

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

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

0

「実装的な意味では置換はtext / excelで全くしていることが異なります」のですとそれは共通化すべきものでは無いです。それぞれの置換の中に「ちと厄介な」とか「codeのパット見では何をするか判断に一瞬掛かる」な共通なcodeがあればそれを抜き出して共通化することはありえますが。
TakaiYさんお薦めの 継承 が まずは一番簡単ですが、「継承は嫌だ」という方向で試すなら インスタンスに fileの型に応じた methodを追加、or オーバーライドするという手もあります。
ruby屋さんえなら「extendして」といえばすむのですが pythonだと それに当たる単語がないので、、、
単語は無いみたいだけど インスタンスごとに method を差し替えは可能です。ただ ruby だと extend TypeCsv で済む所ちょっとややこしいかも。
まずは 継承 で作って、勉強で 「継承は嫌だ」にトライ がお薦めかな

投稿2025/09/21 23:14

winterboum

総合スコア23678

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

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

0

その全てのファイル形式の置換したいオブジェクトを同じ形に変換し、外部に公開するという事が出来ないなら無理だと思います。それができるならそれぞれのオブジェクトは変換処理を実装するだけで良いと思います。

投稿2025/09/21 11:17

u2025

総合スコア101

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問