-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: "APIデザイン ガイドライン"を追加 #870
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# APIデザイン ガイドライン | ||
|
||
## Rust 以外の言語の API | ||
|
||
VOICEVOX CORE の主要機能は Rust で実装されることを前提としており、他の言語のラッパーでのみの機能追加はしない方針としています。これは機能の一貫性を保つための方針です。 | ||
|
||
ただし機能追加ではない範囲で、各言語の習慣に適合するような変更は積極的に行っていきます。例えば: | ||
|
||
* [`AudioQuery`](https://voicevox.github.io/voicevox_core/apis/rust_api/voicevox_core/struct.AudioQuery.html)といったJSONで表現可能なデータ型は、Pythonなら[Pydantic](https://docs.pydantic.dev)、JavaScriptなら[Zod](https://zod.dev/)といったライブラリを使って表現すべきです。 | ||
* Rust APIとやりとりする際はJSONを介して変換します。 | ||
* [`StyleId`](https://voicevox.github.io/voicevox_core/apis/rust_api/voicevox_core/struct.StyleId.html)といった[newtype](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html)は、そのままnewtypeとして表現するべきです。 | ||
* 例えばPythonなら[`typing.NewType`](https://docs.python.org/ja/3/library/typing.html#newtype)で表現します。 | ||
* オプショナルな引数は、キーワード引数がある言語であればキーワード引数で、ビルダースタイルが一般的な言語であればビルダースタイルで表現すべきです。 | ||
* 「範囲」を表すデータ型が言語レベルである場合は、可能な限りそのデータ型を用いてAPIを構成するべきです。 | ||
* 例えばSwiftやRubyでは`Range`という名のデータ型を使って表現します。 | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これ、その言語のRangeがサポートしているものと、APIがサポートするrangeが異なる場合があってややこしいかもです!
例えばたしかPythonは
range(0, 3, -1)
とかにすると、逆向きの範囲を指定できます。たぶん[2, 1, 0]
。あと飛び飛びの範囲も指定できます。
range(0, 4, 2)
だとたぶん[0, 2]
。このとき、例えば
render()
で期待されるレンダリング結果は何になるべきなのか考えれなそうです。一言でいうと、
range
は範囲だけを表してるものではないので、範囲だけを表したい場合にrangeを使うのは良くないのかもと・・・(今気づきました)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これの対象は
Synthesizer::render
の引数ですね。なのでPythonだとおそらく、仮にstepに対応したとしてもrange
― というより多分slice
オブジェクトですが ― を引数に取るのはやめた方がよいという感じになると思います。多分正しいのはRust APIの
render
の引数をRange
にした上で、そのrender
を名指しして他のAPIもそうしろという感じになると思うのですが、今はまだ #867 でもそうなっていないわけでどうしたものか…という感じでいます。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ〜〜〜なるほどです、RustのRangeは本当に範囲で、かつend >= startなんですね!
たしかにすくなくともRustは使ってもよいのかも。
いやでもrender()はend=startのときにエラーを返す設計になるかもな気がします。
個人的には一旦何も書かず、render側でRangeを使おうってなったら書き足すのが良い気がしてます。
(Range使いたい寄りだと把握しました!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど。そうしましょう!
0832bdd
(#870)(消したと同時にtodoを残しました)
start > end
はともかくstart == end
だと空と解釈されると思います。他言語的にもそれが自然かと。(実装レベルだと空テンソルをONNX Runtimeに渡したらどうなるのか私は知りませんが、別途チェックすればよさそう)
start > end
だと、この(↓)表とかを考えると慣習に反しうりそうなので補足は要りますね。#867 (comment)
ちなみにRustでリテラルを使って
20..10
とか書くと、deny
レベルで怒られます。[追記] エラーのスクショがちょっと適切じゃなかったので差し替え
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start
は含むけどend
は含まないの、普通の感覚で行くとものすごい分かりにくいということに気づきました 😇Rangeだとかがそうなってるのは、「そう設計しておくと色々便利だから」以外に説明が思いつかず、APIで同じことをすると不慣れな人にとってはなぜそうなっているかわからない気がしました。。。
(例えばstart: 10・end: 10だったとき、10を含まないのが直感的じゃない)
開区間、あるいは閉区間になってることが分かりやすい用語を探しました。
採用するかは置いといて、
min
とmax
が一番わかりやすそうではありました。(けど予約語なことも多そうなので迷いどころ)from
とto
も良さそうだけど、小さい値がどちらかは分かりづらそう。offset
とcount
(length
)も悪くなさそう。https://chatgpt.com/share/673102c7-9858-8008-a5d1-fb36a5ac0382
これめちゃくちゃ厄介ですね。。。
RustはRangeで良いかもだけど、例えばC APIでstart・endにしてendは開区間にすると、まあ間違いなく閉区間だと思ってバグって使う人が出てくる気がする。。
まあrender()したものを聞いたときに、音声が不連続になるので違和感には気づけそうですが・・・・・・・。
追記:おそらく
(offset, length)
が使いやすい&わかりやすい気がする。RustはRangeでも良いかも。このとき
Range(offset, offset+length)
と書けるので相性も良い。start=endのときの挙動は、サポートしてもしなくてもどちらでも良さそう。どちらにせよドキュメントに明記したい。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これ(↓)は以前私がした提案ですが、C APIとJava APIだけKotlinにならって
begin
/start
,end_exclusive
とし、他の言語では言語に合った名称 ― 例えばPythonではstart
,stop
― にしておけば十分なのではと思っています。#854 (comment)
というのも
Range<_>
とRangeInclusive<_>
といったくくりのオブジェクトで取り回す文化であるため、問題ではないend_exclusive
とでもすればよいだと思った次第です。
参考:
https://discord.com/channels/879570910208733277/893889888208977960/1296122640406417468
ユーザーのニーズには多分合っていると思うのですが、今現在はみ出すような範囲指定を不正入力扱いすると決めているため、"end"側の処理については絶対位置を意識せざるを得なくなり不便なのでは、という気もします。
ちなみに豆知識その2
Rustでは$(i, j]$ や $(i, j)$ も一応は表現できます。他の言語にはあまり無さそうですが…
render
の話になってきたので。CC: @Yosshi999
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
たぁしかにlengthにすると最後部分の計算が面倒ですね…。
(chagpt君も全く同じ意見だった https://chatgpt.com/share/67319e1d-53b0-8008-8a27-1ebec0b8cef3 )
少なくともmin,max指定はダメそうですね!!
例えば将来秒指定するAPIができた時に詰みそう。
lengthで範囲を指定し間違えるとエラーになってくれますが、endの解釈を間違えると変な音が出るだけなので、そういうものかと品質の誤解になりえるかも。
まーーーでもこれだけ考えて決定打が出ないということは、わりとどちらも一長一短で決まりな気がしますね!!
とりあえず今のところ、endにしてドキュメント書くでも、lengthにするでもどちらでも良さそう!!
また時間置きますかぁ。