Scope: managed applications, mobile applications, and ordinary applications.
1. When you develop libraries, ensure backward compatibility (hereinafter referred to as "compatibility") between libraries of different versions within a single library subrevision.
For example, libraries 2.0.1, 2.0.2, and 2.0.5 must be compatible. It is acceptable if next revision 2.1 has big changes that violate this rule.
Compatibility of library versions allows you to significantly minimize costs related to update of the library in configurations, as developers do not need to revise the code several times and adapt metadata objects in their configurations to changes made to the library. Applications can use old library features since migration to new versions is no more urgent.
If you develop several libraries that support each other, compatibility allows you to co-develop adjacent libraries based on different versions of the basis library without the need to frequently update the entire library tree.
|What's new in the version?||RR||.SS||.VV||.CC|
compatibility is broken
(migration instructions are available)
- RR (revision) means that compatibility is significantly violated. There are major architecture or other significant changes in the library.
- SS (subrevision number) means that compatibility is violated. Make sure you follow the instruction on how to migrate to this version. Otherwise, the configuration will not function.
- VV (version number) means that only new functions for users or developers are available. Automatic import of library metadata to configurations is available. You do not have to strictly follow the instructions on how to migrate to this version.
- BB (build number) contains only fixed errors. Automatic import of library metadata to configurations is available.
The exceptions are cases agreed with library users in advance, such as legislative amendments. In case of legislative amendments that become effective before the next version is released, issue corrective builds with these amendments for all supported branches, even if these changes add new functions or break compatibility. In such cases, forced broken backward compatibility must be included in the supporting documentation according to cl. 1.8.
1.2. In libraries with multiple functional subsystems, violation of compatibility in at least one subsystem means that the library subrevision number (the 2nd digit) increases.
- Allocate the library API making all details of its implementation unavailable to its consumers.
- Do not change the API and behavior. It can be extended only.
Backward compatibility requirements take precedence over the following development standards:
- Names, parameters, and behavior of export procedures and functions available in the API section.
- Names, parameters, and behavior of all export procedures of overridable common modules.
- Names of metadata objects (including their attributes, tabular sections, and other) that can be accessed directly from the application code or queries.
- Add new functions to modules
- Add procedures to overridable modules
- Add another optional parameter to the end of the list of formal parameters of existing functions
- Add new attributes to catalogs, registers, and other (which can be accessed directly in the library).
At the same time:
- A corrective library release is not expected to have a new API or include new API parameters (this is unacceptable is 4th digit).
- Even if parameters and names of procedures remain unchanged but their behavior changed, this is the violation of compatibility (that is, this is acceptable in the 2nd digit only).
- For example, the Sum(a, b) procedure starts to calculate the difference instead of the sum.
1.8. In other cases, if compatibility can be abandoned according to cl. 1, specify any changes that violate compatibility in the library supporting documentation. The documentation must include instructions for application developers related to adaptation of their configurations to a new library API.
Examples of documentation fragments:
- The ExternalTasksOverridableServerCall common module is renamed to ExternalTasksServerCallOverridable. Replace all references to this module in the configuration code.
- The SetArbitraryApplicationCaption procedure of the StandardSubsystemsClient common module is renamed to SetExtendedApplicationCaption. Replace all references to this procedure in the configuration code.
- The PerformerDisciplineSummary report is deleted. Use the Tasks report option instead. Replace all references to this report in the configuration code and metadata.
- Add the AddDataOfPersonalDataOperatorCompany procedure to the PersonalDataProtectionOverridable common module by transferring its definition from the library.
- The interaction subject is transferred from the document attribute to the Subject attribute of the InteractionsFolderSubjects information register. Replace all references to the Subject attribute of interaction documents with the Subject attribute of the information register.
When they are placed in different common modules, modules with internal procedures and functions can have the Internal postfix.
- The MessageExchange and MessageExchangeClient common modules represent the "Message exchange" subsystem API.
- The MessageExchangeInternal common module represents internal subsystem procedures and functions that cannot be used in the configuration code.
Such API placement in separate common modules allows you to do the following:
- Have the entire library API in a relatively small and manageable number of common modules.
- Display only procedures and functions that are indeed a part of the API in a tooltip upon module text input. For example, after dot in the MessageExchange line in the module text editor, configuration developers can see only the functionality they really need to use in their activities.
2.2. The API section can also contain procedures and functions to be called by specific end users from other functional library subsystems or other libraries. Place such procedures and functions in a separate subsection named For calls from other subsystems designed as the InterfaceImplementation area. .
Inside the subsection, divide procedures and functions into groups of comments with a name of the end user that will use them. For more information, see Developing configurations with repeated use of common code and metadata objects. For example:
// Enter code here.
// Enter code here.
// End StandardSubsystems.BatchObjectModification
// Enter code here.
// End SaaSTechnology.DataExportImport
// Deprecated: Use the ConvertAtRate function
Function ConvertCurrencies(Sum, CurrencySrc, CurrencyDst, AtRateSrc, AtRateDst, ByMultiplierSrc = 1, ByMultiplierDst = 1) Export
and place an updated function with new name (ConvertAtRate in the example).
Move the deprecated function to the Deprecated common module area available in the Public area. In procedures and functions available in the Deprecated area, deviations from other development standards according to cl. 1.1 are allowed.
In this case, there is no need to rewrite the existing application code. If the decision is taken to delete all obsolete functions upon release of a new library revision, such functions can be easily identified in the library code and deleted.
Replacement recommendations for each obsolete function are given in the library supporting documentation as follows:
- The ConvertCurrencies procedure of the Common common module is deprecated. Use ConvertAtRate instead. The deprecated function is left for backward compatibility.
3.2. In some cases, even if an error that changed the export function (procedure) behavior is fixed, it is recommended that you do not delete this function, mark it as deprecated, and place a revised function version with a new name. This allows you to ensure that the application code of the incorrect behavior functions correctly. Immediate code refactoring is not required as there might be numerous call sites.
The behavior change can be unwanted even in abnormal or undocumented cases of export functions (procedures) calls.
For example, a calling code with incorrect values of input API function parameters waits for (processes) the undocumented Undefined return value, and this function is modified and throws an exception in this case in the updated library. Although a new behavior is designed as more correct and even becomes documented, it can cause mass errors in all its call sites.
Function ConvertCurrencies(Sum, CurrencySrc, CurrencyTrg, AtRateSrc, AtRateTrg, ByMultiplierSrc= 1, ByMultiplierTrg= 1) Export
If there are a lot of parameters, it is recommended that you provide the last parameter of the Structure type whose properties can be expanded later:
Function ConvertCurrencies(Sum, CurrencySrc, CurrencyDst, AtRateSrc, AtRateDst, ConversionParameters = Undefined) Export
We recommend that you use this approach in advance in procedures and functions, in which the number of parameters and modes are most likely to increase.
3.4. You can use parameters of the Structure type to maintain compatibility of the API the library used to access configuration objects. For example, the OnDefineSettings procedure of the overridable module enables the library to add new operation modes without losing compatibility:
Procedue OnDefineSettings(Settings) Export
Settings.OutputDetails = True;
Settings.Events.OnCreateAtServer = True;
Settings.... = ...;
This approach also allows you to maintain compatibility of the API the library uses to access configuration objects. In the example above, "Settings.Events.OnCreateAtServer = True;" means that the end user configuration has a defined library event handler with the same name to be called from the library. A new event added in the next library version does not necessarily require to add its empty handler in all configurations. Similarly, 1C:Enterprise platform does not require to insert empty stubs of standard event handlers in modules and object managers.
3.5. To minimize scenarios when configurations need to directly access library metadata objects (attributes, catalog tabular sections, documents, and other), provide API for the application code to interact with the library. It reduces dependence of the application code on library implementation specifics and improves its resistance to library updates.
For example, instead of a direct query to the library register from the application code:
Query = New Query;
Query.Text = "SELECT
| InformationRegister.DataAreas AS DataAreas
| DataAreas.DataAreas = &DataArea";
DataAreasTable = Query.Execute().Unload();
ApplicationIdentifier = ?(DataAreasTable.Count() = 0, "", DataAreasTable.Get(0).Get(0));
Provide an export function in the library to be used in the application code:
ApplicationName = SaaS.ApplicationName();
If the current library version has no dedicated function and there is a need to access its data, we recommend that you implement a temporary function in the application code that can be easily replaced with a library equivalent upon next library update.
- In the first library version, an export function of the common module with reusable return values was provided.
- In the subsequent library version, a standard common module, to which this function was transferred, becomes available.
In this example, not to replace the previous function with a new one in all calls, place this export function in a standard module in the API section. Depending on the current design, this function can call an internal function from the module with repeated use of return values or from any other module or directly contain its implementation. The function location remains unchanged in subsequent library versions.
4. To facilitate control over application interface changes in upcoming library versions, use the attached data processor.