Category: In English

[LinkSet] Compatibility

Theoretical part

 

Articles from Oracle

http://JEP 223: New Version-String Scheme

 

Six kinds of compatibility

Each Joda-Time relase has descriptions of incompatible changes categorized by six kinds:

Compatibility between 2.8 and 2.9
———————————
Build system — Yes
Binary compatible — Yes
Source compatible — Yes
Serialization compatible — Yes
Data compatible — Yes
— DateTimeZone data updated to version 2015g
Semantic compatible — Yes

When binary compatibilities are broken then Majour Version changed. For example v2.0 changelist

Explanation from  Stephen Colebourne, author of Joda-Time:

Build system

Not part of compatibility, just a fact about the build system in use

Example:  in v2.2

 - Ant build removed. Build only on Maven now.

Also, I think, it may be changing in artifact coordinates: groupId, artifactId or even changed repository. Maybe some changes in manifest, for example required dependencies. Or added OSGI manifest info. Maybe some classes was repackaged. Or old artifact was built with ANT and doesn’t contains a Maven’s pom.xml manifest like horrible Xerex library  and then was mavenized.

It also may be recompilation with optimizations or without debug information.

But I think that changing in packaging may be a separate kind of compatibility change.

Binary compatible and Source compatible

Whether the whole API is binary compatible or source compatible. See this document

Serialization compatible

Whether the serialization format is compatible with the previous version.

Data compatible

Whether the data, time-zone data in this case, has changed.

For example: some time zone was changed or even removed. If your database stores old timezone id and application trying to create a date object with this timezone id you’ll get an exception.

Semantic compatible

Whether there is some other semantic change. This is relevant when the classes and methods have not changed, but the meaning of a method has.

See section Serialization incompitables below

For example:  v2.0 has a lot of semantic changes

Previously, DateTimeZone.forID matched time zone names case-insensitively, now it is case-sensitive

I think it always hard to separate semantic changes when dealing with bugs. For example, JDK has bug when using null as key in Map

And that was a question is this a bug or feature.

Another one example, is Apache Commons Lang library. In version 3 the methods StringUtils.isAlpha(), isNumeric() and isAlphanumeric() now all return false when passed an empty String. Previously they returned true.

Semantic looks like correlated with behavior compatibility. When changed not signatures but they flow or contract.

Also it’s often situation when behavior was just undefined by contract. For example old class Vector doesn’t declare behavior about removing elements during iteration.  That’s why was created new class ArrayList and Vector was accepted as Superseded.
So, deprecation, as any changes in contract may be also some kind of semantic change.

 

Serialization incompitables

Compatible incopatibility

Also I think that it should be some kind of «reverse compatibility» that means a contract usage. For example, I saw an issue when subclass of HashMap doesn’t follow a contract. This change was compatible in all ways but all clients become incompatible. How to predict it, I don’t know.

Each of developer has experience when you can’t change something in your API because there is some clients that abuse it or implemented incorrectly. So it should have it’s own classification and developers should think about this kind of reverse incompatibility.

Complexity compatibility

I mean the complexity of program in wide sense: algorithm speed, it’s derivate and consumption of resources (memory, i/o, CPU, disk space), and even source code beautification and structural changes like refactoring. You know,  some algorithms may use more memory but use low processor.

For example, in some early versions of 64 bit JDK your application may fail with OutOfMemory error. This was change absolutely compatible in all categories mentioned before.

Another one sample is when new version of program is working more slowly than previous.

It may not change a contract and flow or anything else may it’s also may be changes that requires an attention.

 

Tool for checking API and BPI

Service provider interface (SPI)

https://stackoverflow.com/questions/2954372/difference-between-spi-and-api
https://en.wikipedia.org/wiki/Service_provider_interface

Also interesting

Реклама

[Grails] ConfigObject

A popular question about ConfigSlurper:

Hey guys, I had in a project the following:
String variable = grailsApplication.config.grails.property.name + grailsApplication.config.grails.anotherproperty.name

And was working for almost a year but suddenly it stop working and throwing an error regarding the ConfigObject doesn’t have a plus method, did something similar happened to anyone?
Did someone knows why it was working and suddenly stop working ?

It doesn’t work because one of ‘property.name’ or ‘anotherproperty.name’ is not set.

If some option is not set, then ConfigSlurper return instance of ConfigObject.
That’s a common mistake.
Good news is that empty ConfigObject can be casted to false by the Groovy Truth.
Thus, to avoid this kind of mistakes and get null instead of ConfigObject you can use Elvis operator write something like:

// return empty list if supportedLocales isn't set
grailsApplication.config.supportedLocales ?: []

// return null if defaultLocale isn't set
grailsApplication.config.defaultLocale ?: null

Conditional Verbosity With Temporary Log Queues

I found a great advise in article Optimal Logging and it worth to mention separately:

When errors occur, the log should contain a lot of detail. Unfortunately, detail that led to an error is often unavailable once the error is encountered. Also, if you’ve followed advice about not logging too much, your log records prior to the error record may not provide adequate detail. A good way to solve this problem is to create temporary, in-memory log queues. Throughout processing of a transaction, append verbose details about each step to the queue. If the transaction completes successfully, discard the queue and log a summary. If an error is encountered, log the content of the entire queue and the error. This technique is especially useful for test logging of system interactions.

It’s cool idea, I’ll try in practice.
And Michael Würtinger created a SLF4J extension for doing it.