Monday, April 22, 2013

API Deprecation in Dynamics AX 2012


In order to minimize code upgrade cost for minor version upgrade we need to minimize the footprint of changes to the APIs. The basic need is to ensure that customers who took dependency on the API that needs to be changed will have easy time up taking the changes, ideally the code that worked in a previous release would also work in current release. In case when the changes are required the API needs to go through proper deprecation process that will ensure that customers will get quality help during code upgrade enabling them to quickly uptake all changes.

Proper deprecation of APIs for minor version upgrade


Changes from one of the below categories:
 

  •       API signature changed (class and table methods)
  •       API return type changed
  •       API number of parameters changed
  •       API parameter types changed
  •       API access specifier became more restricted
  •       API parameter order changed
  •       API parameter changed from optional to mandatory
  •       Deleted public/protected APIs (class and table methods)
  •       Deleted classes
  •       Changing inheritance hierarchy
  •       Reducing the number of interfaces implemented


should be deprecated in the following way:

  • API marked with SysObsoleteAttribute attribute
  • SysObsoleteAttribute supplied with detailed information about how to migrate code that has dependency on deprecated API (provide an alternative or link to white paper in case of major rework)
  • If the API is no longer functioning set isError = true in the SysObsoleteAttribute attribute so the compiler will report any usage of that API as an compiler error


In order to deprecate an API use the SysObsoleteAttribute on a method level as on the below
example:

[SysObsoleteAttribute('Use method Args::create() instead', false)]
public static Args create(container _pack)
{
    Args sysArgs = new Args();
    sysArgs.unpack(_pack);
    return sysArgs;
}

In order to deprecate class use the SysObsoleteAttribute on a class level as on the below example:
[SysObsoleteAttribute('Use Args class instead', false)]
class SysArgs extends Args
{
}

If an API is no longer functioning use the SysObsoleteAttribute and set the isError parameter to true, that way the compiler will report any usage of that API as an error
[SysObsoleteAttribute('Use method Args::create() instead', true)]
public static Args create(container _pack)
{
    Args sysArgs = new Args();
    sysArgs.unpack(_pack);
    return sysArgs;
}

Additionally, for APIs that return void  you should remove all the code from the method body, for APIs that returns non void value you should replace the method body with the following code:

throw error(Error::wrongUseOfFunction(funcname()));


Adding new parameters:


  • New parameters should be added as the last ones in the parameter list.
  • In case when a new parameter can be added with default value the deprecation is not necessary as that does not break the contract.
  • In case when new parameter does not have a default value and the API has parameters with default value the API should be deprecated and a new one should be introduced.

Changing inheritance hierarchy:


  • Changing inheritance hierarchy has tremendous impact on during code upgrade. The general recommendation is to avoid it unless it’s absolutely necessary. Then depending on the magnitude of changes and the impact on API compatibility either provide a new hierarchy and deprecate the old one providing detailed information how to move dependent code forward.
  • Deprecation of metadata artifacts that can be used in the code
  • Changing EDT type of fields
  • Changing EDT type of field to a non-compatible EDT (outside of hierarchy) is considered as breaking public contract because if there is a customer code that relies on field type this code will no longer compile. If possible  such changes should be avoided or documented (use known issues process).

Deprecation of enum items:


The general recommendation is not to delete enum items since it’s a change that’s intrusive from code upgrade. If the change is absolutely necessary it needs to be documented (follow known issues process). Additionally if that enum is being used in business data you have to provide appropriate data upgrade script.

Renaming fields:


In order to document data model changes please document every single field rename following known issues process.
Fields must not be deleted beetween minor versions.

Deprecation of metadata elements:


For minor version upgrade the goal is to limit intrusive changes that would have to be address during code upgrade as much as possible. If the changes are absolutely necessary the team owning given metadata needs to provide documentation concerning moving code/metadata that’s dependent on deprecated elements.

No comments:

Post a Comment