Replies: 5 comments 6 replies
-
Any Comments are welcomed! /cc @shizhMSFT @qweeah |
Beta Was this translation helpful? Give feedback.
-
For option 1 and 2, do we consider |
Beta Was this translation helpful? Give feedback.
-
I think option 1 is the simplest. Everything in go is hash-based modules (or semver), so I don't think breaking change is too big a deal. |
Beta Was this translation helpful? Give feedback.
-
I like the option 1 intent, but I don't like the fact that It would be easier to use, and more idiomatic, to just define a plain type CopyOptions struct {
Var1 int
}
type ExtendedCopyOptions struct {
CopyOptions
Var2 int
}
// advanced client
opts := oras.CopyOptions{Var1: cmdOpts.var1}
if cmdOpts.recursive {
extopts := oras.ExtendedCopyOptions{CopyOptions: opts, Var2: cmdOpts.var2}
desc, err := oras.ExtendedCopy(ctx, src, ref, dst, extopts)
} else {
desc, err := oras.Copy(ctx, src, ref, dst, opts)
} I would go even further, and pick option 1 avoiding breaking changes. I think clients will value more keeping the major version the same adding Notice that option 3 is also a breaking change, as you are adding a variadic parameter to the function signature. Example of client that would be broken: // We use fnCopy instead of oras.Copy so it can be replaced and mocked in tests.
var fnCopy = oras.Copy
func Foo() {
fnCopy(...)
}
func mockCopy(ctx context.Context, src Target, srcRef string, dst Target, dstRef string) (ocispec.Descriptor, error) {
// ...
}
func TestFoo(t *testing.T) {
fnCopy = mockCopy // <----- BOOOM
Foo()
} |
Beta Was this translation helpful? Give feedback.
-
If we want to get fancy and implement functional options pattern, like option 3, I suggest an alternative implementation: type copyOpts struct {
var1 string
var2 int
}
type copyWith struct{}
func (copyWith) Var1(var1 string) func(*copyOpts) {
return func(co *copyOpts) {
co.var1 = var1
}
}
func (copyWith) Var2(var2 int) func(*copyOpts) {
return func(co *copyOpts) {
co.var2 = var2
}
}
var CopyOpt copyWith
func CopyWithOpts(ctx context.Context, src Target, srcRef string, dst Target, dstRef string, opts ...func(*copyOpts)) (ocispec.Descriptor, error) {
// ...
var co copyOpts
for _, opts := range opts {
opts(&co)
}
// ...
} The clients may use them like this: oras.CopyWithOpts(ctx, src, srcRef, dst, "", oras.CopyOpt.Var1("foo"), oras.CopyOpt.Var2(3)) Pros:
Cons:
|
Beta Was this translation helpful? Give feedback.
-
We have already supported
Copy
andExtendedCopy
functions in oras-go V2 (See #52). The current interfaces are:Next, we would like to extend some options for both the
Copy
and theExtendedCopy
functions to support advanced scenarios (See #59). Based on the current implementation, there are a few approaches to achieve this:options
struct parameteroptions
structLet's take a look at these approaches and see which one fits our scenarios better.
1. Modify the original methods to accept an
options
struct parameterSuppose we define the options like below:
To take these options, we need to modify the
Copy
andExtendedCopy
functions to accept anopts
parameter.From client perspective, calling
Copy
andExtendedCopy
would be like:2. Declare new methods which accept an
options
structFor this approach, the options definition remains the same, but the
Copy
andExtendedCopy
would be something like:The client code would be like:
CopyGraph
andExtendedCopy
3. Use the Functional Option Pattern
For this approach, the options definition would become:
The
Copy
andExtendedCopy
functions would take variadic arguments:The clients may use them like this:
ExtendedCopy
callsCopy
internally, it would need extra steps to convert...ExtendedCopyOption
to...CopyOption
WithXX
function names can be long and uglyNote: We may leverage the Go 1.18's Generics feature to simplify the naming. (Reference: (Generic) Functional Options Pattern)
Conclusion
Comparing the above 3 approaches, I think the first approach fits our scenarios better and it's simple. Although there will be breaking changes, but it's OK as we have not cut an official release yet, just that we need to update the unit tests. The second approach may not add much value. The third approach looks a bit fancier though, it does not quite fit our scenario where
ExtendedCopy
andCopy
may share some common options.Beta Was this translation helpful? Give feedback.
All reactions