|
|
|
|
|
by xja
3443 days ago
|
|
The author is essentially saying any API change has the potential to break backward compatibility and that we should define what kind of breakage is ok. That's kind of interesting, and I'd not considered many of the scenarios mentioned (which apply beyond go). Perhaps the "correct", but cumbersome thing to do is supply different versions of the API when maintaining backward compatibility and never change the old version. |
|
The one that's not is that adding a field or method could break importing code. The scenario here is that you embed two types, one from the upgrading lib and one not, and the upgrading lib adds a name that collides with one in the other type. Rather than pick a winner in that conflict (last embed in the type definition wins, say), Go raises an error so the human can explicitly resolve it by, e.g. renaming one of the conflicting names if you control the code (gorename helps!) or changing one of the embeds to a regular member.
This can happen, but I haven't seen it occur in the time I've been around the Go community, and never adding methods doesn't make sense, and silently resolving those conflicts could _still_ cause a backcompat issue and seems worse than the status quo, and if you do hit the conflict it's often resolvable (gorename!), so I think calling it backwards compatible to add a method/field is reasonable (as well as what everyone already does).
The practical backwards compatibility things that I have seen come up tend to have less to do with folks hitting cases like that than changes that are theoretically right but expose code that was buggy but happened to work before, e.g. programs that used to rely on racy map accesses or wrong cgo pointer usage or invalid Less functions in sort working, or trickiness around net protocol interfaces and buggy clients, or parallel tests exposing something.