/** @deprecated Use function2 */
Which in turn will create the deprecated lint warning and the strikethrough over the code in the frontend call sites where this method is called.
That way I’m communicating deprecation intent directly with the frontend devs who are consumers of the API without confusing back and forths.
And once they’ve upgraded their code to remove usage of the deprecated API, they can be removed from the backend codebase. And CI can run compile time checks on frontend TypeScript, to catch any errors, in case API still in use.
One value proposition of the IC is that canister methods can be invoked by other canisters, and the main purpose of Candid is describe such public interfaces. You can not generally know which other canister depend on yours and when those will be updated, or if ever. So in the interest of not breaking others, removal of public methods (or other backwards-incompatible changes) should generally be avoided on the IC. In that light, deprecation of methods ought to be discouraged as well.
But a deprecation is not removal. A deprecation is a notice to the consumer of the API that this might get removed in the future.
I’m not convinced that the argument of discouraging methods works in this case. It’s about giving developers more power and choice if they choose to use it.
Some thoughts to support the opinion above:
Other standards that perform a similar objective as Candid such as protocol buffers and GraphQL support deprecation as shown here and here
As you pointed out, canisters exposing public APIs can be called by other canisters. These canisters could either be canisters belonging to the same project/backend or could be external canisters that are not controlled by the callee canister developers.
IF the calling canister is controlled by developers who control the callee canister, in that case, they already have control of both and it is an intentional change.
IF however, the calling canister is a third party developer and they are basing their business/application on the API provided by another developer, they should base it on a different trust assumption. That either the callee canister is a blackholed canister and cannot be upgraded or that the callee canister is controlled by an autonomous entity like an SNS DAO
Finally, smart contracts (canisters) on the IC have the super power of upgradability. However, saying that upgrades should only be additive in nature is trying to limit practical application development to unrealistic standards.
Frankly, there’s nothing stopping an application developer from ripping out any public API that they choose for a canister they are a controller of.
Deprecation just provides a safer way to do it where they can communicate their intent better to consumers of the API
It’s not a one-way street, though. With more power on one side you have less on the other: devs can rely less on other devs’ services to get their job done.
Such an assumption would make canister API reliability and upgradability mutually exclusive, which would be defeating the purpose.
True at the moment, but that doesn’t imply that they normally should. Or that there should be tool support that encourages it.
That all said, I agree that there is still value in deprecating API as a way to steer active dependencies towards superior API. But you must always assume that there will remain customers depending on the old version. That’s the price of an open platform. The only methods you can safely change are those that already access-check their caller.