0

Deprecation

The supported way of marking functions as deprecated is something like this:

type MyStruct struct {
}

// MyFunc returns hello
// Deprecated: Use YourFunc
func (m MyStruct) MyFunc() string {
  return "hello"
}

Modern IDEs will highlight any usages of this function and linters might also raise warnings (I haven't personally checked this)

Showing the IDE highlight

Accept interfaces. Return structs.

A popular best practise is "Accept interfaces. Return structs." - which tends to encourage SOLID design in software.

However, the following code - which follows this best practise - conceals the deprecation warning:


// MyInterface specifies a single function that we require from a dependency
type MyInterface interface {
    MyFunc() string
}

func main() {

    var v MyInterface
    v = MyStruct{}
    v.MyFunc()

}

Showing the lack of IDE highlighting

Question

Is there a solution to this problem?

If I were, for example, a library maintainer: how can I ensure that my deprecation warnings are seen by users of the library who are also following best practises and defining their own dependency interfaces.

Brad Johnson
  • 1,776
  • 1
  • 20
  • 26

1 Answers1

3

That seems logical since the method of the interface has not been deprecated. Adding the Deprecated: line to the interface function might help in this case (didn't test, since VSCode doesn't do this yet).

// MyInterface specifies a single function that we require from a dependency
type MyInterface interface {
    // Deprecated: use YourFunc
    MyFunc() string
}

In this case, because the interface only has 1 function you should deprecated the whole thing. Which I know is supported by godoc/pkg.go.dev, take Queryer for example.

// MyInterface specifies a single function that we require from a dependency
// Deprecated: use YourInterface
type MyInterface interface {
    MyFunc() string
}
Dylan Reimerink
  • 5,874
  • 2
  • 15
  • 21
  • One of the core facets of the question, however, is "as a library maintainer, how can I ensure my deprecation notice is seen by end users?" The library maintainer has no control over the user's interface definitions, so they can't reach in and add deprecation warnings there. – Brad Johnson Nov 26 '21 at 15:31
  • It seems odd to me that a library provides a struct and the user provides an interface which the struct of the library implements. If this is a scenario you are worried about, it would be smarter to deprecate your whole struct, which should should cause the `v = MyStruct{}` to become stricken through – Dylan Reimerink Nov 26 '21 at 16:24
  • "It seems odd to me that a library provides a struct and the user provides an interface..." Is that not what the interface segregation principle encourages? – Brad Johnson Nov 26 '21 at 23:25
  • 1
    As far as I know, the interface-segregation principle is about breaking big interfaces into smaller interfeaces, much like the "The bigger the interface, the weaker the abstraction." go proverb. I think the dependency inversion principle is more at play here. You typically want to use interfaces as parameters so the actual implementation can be swapped out. So it is logical to define an interface in a package and use it as input. But I don't know of any common use case where the user of a package defines an interface which the library struct implicitly implements. – Dylan Reimerink Nov 27 '21 at 13:13