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

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

新規登録して質問してみよう
ただいま回答率
85.35%
リファクタリング

リファクタリングとはコードの本体を再構築するための手法であり、外見を変更せずに内部構造を変更/改善させることを指します。

Q&A

0回答

523閲覧

自前ではないライブラリを自前に改造したときの関数名について

poni

総合スコア0

リファクタリング

リファクタリングとはコードの本体を再構築するための手法であり、外見を変更せずに内部構造を変更/改善させることを指します。

0グッド

1クリップ

投稿2021/02/12 04:25

こんにちは.私は大学4年生で,研究で外のライブラリを使おうと思っています.
リファクタリングの観点で,ライブラリの運用について悩んでいることがあるので質問させていただきます.
前提として,使用するライブラリのライセンス的に以下の行為は問題ありません.
また,gitによるバージョン管理はしているので変更前に戻すことは可能です.

私がしたいことは,外から拾ってきたライブラリの一部を自分用にアレンジすることです.
ある関数を変更するとなったときに
1.元の関数の名前を変えずに上書きする
2.名前を変えてライブラリの中,もしくは別の場所に置く
の2つの方法があると考えています.

1.を採用したときのメリットは,変更を適用後,呼び出し側の使い方が変わらなければその関数を呼び出している別の関数を変更しなくてもよい.また,関数名が長くならなくて済む.などがあると思います.

2.を採用する利点は,関数を変更後も元の関数が残ること,変更したことが関数を見ただけで分かること.欠点は呼び出し側の使い方が変わらなくてもそれを呼び出してるすべての他の関数を変更しなければならない,などがあります.

私のつくるプログラムは他の人も使うことが考えられるので,運用・保守の観点で一番良い選択をしたいと考えています.
もしよければ,理由も添えてアドバイスくださると大変ありがたいです.
よろしくお願いいたします.

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

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

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

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

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

Zuishin

2021/02/12 04:28

元の関数を残した上で新しいラッパーを実装すれば上位互換になります。
poni

2021/02/12 04:38

クラスではなく関数ファイル(function)で,一部分だけ変えたいという感じです...
Zuishin

2021/02/12 04:42

変えたくても我慢するのが良いという意見です。
poni

2021/02/12 04:45

なるほど.ありがとうございました. 今回はどうしても変える必要があるという旨でした.
Zuishin

2021/02/12 04:46

変える必要があるというのがおそらく勘違いだと思います。
miyabi_takatsuk

2021/02/12 05:02

> クラスではなく関数ファイル(function)で,一部分だけ変えたいという感じです... ラッパー = クラスとは限らないかと。 言語によってはクラスにする必要があるかもしれませんが・・・。 しかし、クラスベースだろうがプロトタイプベースだろうが、 元の関数を拡張することは可能ですし、別のオリジナルの名称関数で、その中で元の関数を実行するなら、 元を変える必要はありません。 Zuishinさんの言われる"ラッパー"とはそういうことだと思います。 ライブラリは、関数同士やクラス同士で、密接に繋がっている可能性があるので、 おいそれと名称を変えると、ライブラリ自体が動かなくなる可能性が高いです。 なので、元を変えるのは、凶とではしても、吉になることは非常に稀です。
meg_

2021/02/12 05:15

> 私のつくるプログラムは他の人も使うことが考えられる どのような状況(環境)が想定されますか? Dockerなどで環境ごと「私」が整備するのであれば1.でも運用可能かもしれませんが、ユーザー毎の環境であればライブラリが上書きされて使用される気がします。
poni

2021/02/12 07:04 編集

>> Zuishin様 >> miyabi_takatsuk様 元を変える必要があるというのはおかしいのでしょうかね... 業務で使うパッケージなどを想定したらそうかもしれませんね. 具体的なコードを書いていない私の伝達不足でしたが,今回のはMATLABを使った計算ライブラリであり例えばなのですが,普通のfor文をgpuで高速化する必要が生じたのでループの関数だけを普通のforから上位互換のpayforという関数に変えたいといったところです. ラッパーという言葉自体も初耳でして,ぱっと調べたところ内包して一部を追加したり引数を入れ替えたりといった使い方(例えば下リンク)しか出てこなかったので一部のコードを変えたいという使い方にどうもっていけばいいかわかりませんでした. https://affiliate-copywriting.tokyo/js-wrapper-function/ もしよろしければなのですが今回のような例をラッパーで対処する例なり説明している書籍などをご教授いただけませんでしょうか?
poni

2021/02/12 06:58

>> meg_様 私のコードを使うのは未来の研究室の後輩です. 環境自体はMATLABというソフトウェアを入れれば動くのでコードをそのまま譲渡することになると思います.
Zuishin

2021/02/12 07:06 編集

内部を変更して高速化するだけならシグネチャを変える必要はなく、更新したものを新バージョンとしてコミットすれば良いと思います。 シグネチャを変える必要があるなら名前を変えて別の関数として提供するのが良いと思います。この場合は可能であれば元のライブラリは変更せず、それを使用した別のライブラリとして提供します。
Zuishin

2021/02/12 07:07

miyabi_takatsuk さん、フォローありがとうございました。
poni

2021/02/12 07:12

>>Zuishin様 なるほどなるほど.外から見た使い方が同じであればそのまま.そうでなければ名前を変えるということですね. 関数名を変えない場合でもgit管理しつつ変更内容をコメントなどで変更内容を残しておけば後からでもわかるようになると思います. 今のところそれが一番良いと思いました.
poni

2021/02/12 07:27

>> Zuishin様 ありがとうございました.
meg_

2021/02/12 07:34

> 私のコードを使うのは未来の研究室の後輩です. 環境自体はMATLABというソフトウェアを入れれば動くのでコードをそのまま譲渡することになると思います. MATLABを使ったことはないのですが、ライブラリのアップデートはしないのですか?アップデートしたら上書きされるのでは?という懸念でコメントしました。
poni

2021/02/12 07:57 編集

meg_様 仰り通りです. 自動で上書きしてくれるようなライブラリではないので新バージョンがリリースされると手動でダウンロードして変更内容を見ながら修正することになると思います. 別の人がそれをすることになることを考えると,同じ名前だと上書きされる可能性があるので名前を変えた方がまだましということでしょうか? それともやはり前のお二人がおっしゃるようにライブラリに手を加えるということがそもそも間違っていて,関数のラッパー(まだよく理解できていないですが)というのを施して,元のライブラリにできるだけ干渉しないようにした方がよいのでしょうかね...? 別の方の返信の内容を含めてしまい申し訳ありません.
poni

2021/02/16 06:36

>>hoshi-takanori様 返信遅くなって申し訳ございません そうですね...ありがとうございます
poni

2021/02/16 06:55

少し時間をおいてもう一度考えなおしています. Zuishinさんやmiyabi_takatsukさんにアドバイスいただいたラッパーは最初ぴんとこなかったのですが 元の関数名 { 条件1 元の関数の処理 条件2 元の関数を一部改変した処理 } ということだと認識しました.(あっていますかね..汗) また,私の言っているpayforはMATLABに追加ライセンスをもらうと使えるようになる関数で,ライブラリの作者にパッチを送って修正,というわけにはいかないと思います. meg_さんに言及していただいたように研究室内で他の人が上書きする可能性を懸念すると,一部変更した関数は名前を変えて別の場所に置いておく必要があると思うので元の関数の処理自体には手を加えない形で 元の関数名 { 条件1 元の関数の処理 条件2 元の関数を一部改変した関数を呼び出す } とすることが今のところ最善?のような気がします. 他になにか意見があれば募集したいのと私の考えもまた変わるかもしれないので,もうしばらく未解決とさせていただきます.
miyabi_takatsuk

2021/02/16 10:29

> ということだと認識しました.(あっていますかね..汗) 違うと思います。 新名称関数 { 条件1 元の関数の処理 条件2 元の関数を一部改変した処理 } もしくは、 新名称関数 拡張 元の関数名 { 条件1 元の関数の処理 条件2 元の関数を一部改変した処理 } かと思います。 元の関数名をそのまま使う場合は、 オーバーライド 元の関数名 { 条件1 元の関数の処理 条件2 新子関数名 () { 親関数の関数実行 } } 言語によって、処理系統や、関係などは変わりますが、 とかく、元を変えない、を原則とした時こうなります。
poni

2021/02/16 14:18

miyabi_takatsukさん ありがとうございます. 元を変えない原則については理解しました. しかしやはり関数(クラスメソッドではない)を拡張したりオーバーライドしたり,というのがよく分かっておりません. Kotlinとかの拡張関数のことでしょうか? 私が知っているのはJava,MATLABでそれらには関数オンリーで継承したりするような文法はなかったと思います.それともまだ私はなにか誤解をしているのでしょうか? 理解力が無くてごめんなさい.何度も助け船をありがとうございます.
poni

2021/02/16 14:32 編集

継承を使わない方の 新名称関数 { 条件1 元の関数の処理 条件2 元の関数を一部改変した処理 } の方は元の関数を変えないというのはそうなのですが, 結局外からは新名称関数を呼びだす必要がありますし新名称関数の中に元の関数をいじったものが含まれているので 2.名前を変えてライブラリの中,もしくは別の場所に置く と変わらないような気がします. 違いは関数の中で条件分岐するかしないかですが,元の関数を呼び出す可能性があり, 条件分岐したければ呼び出し側で分岐させればいいので. むしろ新名称関数のコードが大きくなってしまうのと新名称関数に条件分岐の引数を渡さなければいけない?となってしまいそのようにする意味があまり分かりませんでした.
poni

2021/02/16 14:34

分からないの一点張りで心苦しいです... 理解したいという意欲はあり,自分が正しいとは全く思っていません.
miyabi_takatsuk

2021/02/16 15:16 編集

これ以上は、具体的な話にするには、言語を指定しないと無理です。 なぜなら、言語によって継承のやりかたも違えば、構文も違うからです。 よって、より理解を深めたいなら、言語の指定をしましょう。 あと、どのような構文をどうしたいか、も、 具体的なソースコードを記載しましょう。 でないとこれ以上話は進展しないですし、 回答もいつまで経ってもつかないことでしょう。 ちなみに、 JavaScriptであれば、関数自体を、継承させ、拡張したりなどが可能です。 (プロトタイプベースだからだと思われる) なんにせよ、言語指定と、 具体的な構文を掲示してください。
meg_

2021/02/16 15:23

質問者さんが書くコード(関数を使う側)には「新名称関数」のみが現れるということではないですか?GPUがない場合は新名称関数内で元の関数が呼び出される、というイメージでしょうか。(違っていたらスミマセン)
hoshi-takanori

2021/02/16 15:24

どういう改変をしたいのかによってやり方は変わるわけで、 ・パフォーマンス改善のために for を parfor に変えたい (おそらく計算結果そのものは変わらないのですよね?) ・parfor は有料オプション という要件であれば、元の関数をラップする方法では解決出来ないので、関数名はそのままでライブラリ名を変える (ライブラリを入れ替えるだけで高速化する) という方針でいいのでは。 内部で分岐するという案は、私の以前のコメントに貼ったリンク先でも議論されてますが、C 言語のような条件コンパイルはできないので、パフォーマンスはむしろ落ちるのではないかという話になってました。
poni

2021/02/16 22:50

miyabi_takatsukさん 途中の返信でありましたが言語はMATLABです. ソースコードはのせることは最初の段階では難しかったです. なぜなら改変箇所はたくさんあるからです. 回答者からすると答えずらかったかなと反省しています. 次回からサンプルコードをいくつか作ってのっけるようにします. JavaScriptだと可能なのですね.MATLABはおそらくクラスベースだと思うので厳しそうです. 非常に勉強になりました.ありがとうございます.
poni

2021/02/16 22:52 編集

meg_さん はい.そのようなイメージです.
poni

2021/02/16 23:09

hoshi-takanori 具体的なコードを提示できず申し訳ありません. パフォーマンス改善のためにforをpayforに変えたい(計算結果そのものは変わらない)のは一つの例です.変わる変更もあり(これは必要な変更です),両方あります. 条件分岐でパフォーマンスが落ちるなら考えますが,呼び出しても1回か2回程度の関数が多いので, 条件分岐で多少遅くなるくらいは問題ないと思います.(MATLABについて調べていただき本当にありがとうございます.) 振る舞いが変わるとなると関数の名前を変える必要があるということなので,それならば振る舞いが変わらなくても全て統一するために 元の関数名_gpu のように名前を変更して別のフォルダにおくのが最善な気がしています. 呼び出すときは if 1. 元のコード 2. 一部変えたコード end とするかライブラリ使用者が変更を理解していれば 片方コメントアウトして必要な方を呼び出す ・改変した方をつかう // 元の関数 一部変更した関数
miyabi_takatsuk

2021/02/17 01:14 編集

> 次回からサンプルコードをいくつか作ってのっけるようにします. 質問本文は編集可能なので、 本質問にて記載してください。 また、全部が全部でなくても大丈夫です。 一部のみでもけっこうです。 (代表的な箇所でいい) 全て目を通しておらず申し訳ございませんが、 言い訳ではないですが、このコメント蘭を全て追うのはけっこう苦しいものがありますので、どうか、質問本文の修正・編集をお願いします。
miyabi_takatsuk

2021/02/17 01:15

また、質問タグも編集で付け替えができますので、 MATLAB を追加しましょう。 (あるはず)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

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

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

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問