Prompt
When evolving APIs, maintain backward compatibility to prevent breaking changes for existing consumers.
Key approaches:
- Retain removed members with obsolete attributes: When removing or replacing public methods, mark the original as obsolete but maintain its functionality.
// Old method
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use UpdateAsync(WaitUntil, ConnectorPatch) instead")]
public virtual Response<ConnectorResource> Update(ConnectorPatch patch,
CancellationToken cancellationToken = default)
{
// Call the new implementation
return UpdateAsync(WaitUntil.Completed, patch, cancellationToken).EnsureCompleted();
}
// New method
public virtual ArmOperation<ConnectorResource> Update(WaitUntil waitUntil,
ConnectorPatch patch, CancellationToken cancellationToken = default)
- Handle constructor parameter changes: When a required parameter becomes optional, keep a constructor overload that accepts the previously required parameter:
// Old constructor required publisherId
public MarketplaceDetails(string planId, string offerId, string publisherId)
: this(planId, offerId)
{
PublisherId = publisherId;
}
// New constructor makes publisherId optional
public MarketplaceDetails(string planId, string offerId) { }
- Add code-gen attributes for serialization: When properties are removed from models, use code generation attributes to maintain serialization compatibility:
[CodeGenSerialization(nameof(BlockResponseCode), "blockResponseCode")]
public partial class DnsSecurityRuleAction
{
[EditorBrowsable(EditorBrowsableState.Never)]
public BlockResponseCode? BlockResponseCode { get; set; }
}
These approaches ensure that existing code continues to work while allowing APIs to evolve with improved designs.