Versioning of software

Stepping up with the P2 I download samples from the OBEX and found already some marvels. Now and then there is an update in a program. Due to the fact, that samples are like fire and forget, you always have to check for differences.
I now want to create a function in all my programs to return a version. The main then can check this version and react accordingly. This will allow me to put all the commonly used files in the library folder.
My setup now is: I have a "Samples" Folder, in this folder I place all the OBEX downloads and play around with them. Common drivers I copy to the library and move them to a subfolder of the sample, so they are available on demand, but the library is referenced as a standard. Any comments welcomed.
con version = 2025_03_04_00 library = 10001 ' first library and jm is the originator / maintainer pub null(Check) : Result '' This is not a top level object versioned if Result := check - version Result := library else Result +=1
So the version number of the library is a date stamp (with an extension). If the version number fits, a 1 is returned, if not the library number, which must be > 10000
The last four digits designate the origin of the library, the leading number enumerated the library itself.
The calling function can determine if the called function is correct. If no version exists, 0 is returned, valid version: 1.
A library may return the result of a called library to the main, so main can detect, that at least one library is outdated. A library that detects to be outdated returns, so the main will see the ID of the first library in the stack outdated.
Another aspect: What if you have a method, that has no version ID. This case is no taken care of.
It is a good idea, for every software written to have such a feature. Like I introduce the "null()" to my modules now, I'll continue with versions.
First usage: looks like a little bug in jm_str, last character of a string doubled. I reminded there is another example with this methods, and indeed: it' a newer version. The bug was in front of the screen anyway ;-)
Comments
It looks, it's working so far and step by step I'll update my modules...
I find the library versioning interesting, however, if I'm not wrong, the check is at runtime, right ?
I mean, if the calling program doesn't output something on the serial or debug, the developer never know that a library was updated, right ?
Generally, these things should be checked at compile time so the developer can immediately know that a library was updated, unfortunately PNut doesn't support expressions in the preprocessor directives, but Spin Tools IDE yes. With it you can do something like this:
Constants defined in the child objects can be used in the preprocessor expressions.
Discovering a mistake early can save you four years of debugging. So my project took long time, even when compared to the history of propeller. Yes, you have to signal a mismatch, and the example I prepared relies on a working terminal. A simple LED would do the job, but even this LED is not omnipresent. But, you always have to start with the first step.
In principal every method should be able to return an identity. And there has to be a repository to cross check validity. While the compiler is the first level to check, I envision a pool of processes in a distributed system processing messages. Just now we have different tools to develop, I'm stuck with the Proptool, just to focus on my application and not to chase phantoms.
I think I talk about a kind of "late linking" or "OLE". In a data base application I keep a list of methods with version in the data base, whenever I start the app, I first call all the methods to return their version and if the version is newer, I'm asked to update the data base. That allows me to modify methods on the fly, and I'm always reminded, that something might go wrong.
One point is keeping track with improvements. It may be useful to have a method, that can change behavior. Like: there is an existing method, called by a main. This method now is improved. Like: there is a new format descriptor. Then this method when called works like the old one, but a call with a certain parameter switches to the new mode. A dummy call with an parameter "$", not valid for the function, can switch between different modes .. ETC.
The concept of self-describing data is very powerful. E.g. you have JSON, the data is parsed to get the information and the type is removed. But one could imagine to parse the JSON to still have Type:Value objects and then you feed those object to a "+" method that will add integers, reals, vectors, strings...
There were such wonderful ideas in the early times of the P1 that never saw real light.
You realize the existence of freedom if you realize, that freedom is the right to hurt oneself. Autsch!
What you describe seems overloading. With the latest PNut (and Spin Tools) releases methods can have default parameter values:
You can call method as either
method(a)
,method(a,b)
ormethod(a,b,c)
, missing parameters assume the default value from the declaration.Anyway, improvements to existing methods that change the expected result should be avoided, either creating new versioned sources (and by versioned I mean with a different file name, like library_20250101 or library_20250305 so it doesn't break existing code) or with language specific methods like version constants (as above), method overload, annotations, etc.
Not easy with Spin since it doesn't even have strong types.
Annotations however may be a nice addition, I have to think about that...
Personally I like to keep track of changes with tools that are designed for that like git. Put your source code in a git repository and when you change something commit the changes with a message that describe what you have done. If changes are not compatible with existing code or requires updates, change the method name or number of parameters or whatever to avoid conflicts. Tags can be used to checkout specific library versions that are known to work with the user source.
OBEX was once backed by a git repository, not sure if it is still so or if it has some features to keep track of updates.
This doesn't seem to work in PNut v50p1. Spin Tools and flexspin both support it though.
Oh what... I was sure it was introduced in PNut... maybe I have implemented it because I saw it in a flexspin source... sorry for the misinformation.
What I envision is maybe not overloading in the common sense. I think about something like a state machine, e.g. represented by a Petri-Net, where distributed processes act on distributed data. This may sound very abstract, what indeed it is. There may be a Propeller in place A and another in place B, so we have 16 COGs. Every COG references a process control block (PCB_) consisting of pointers to variables, the first one dedicated to serve as a command. The variables can be shared between different COGs, so one process may have access to another processes command and so control that one. If some Propellerchips are linked via any means, a communication interface can mirror a PCB_ to another chip, so the COGs can communicate, even if distributed, transparently.
Such a network must be able to identify and share resources dynamically. And the first step is: I have to have a mechanism, that prevents me from accidently mixing versions of software, just because the reside locally and in a library.
And that is, what I now start with, as I have anyway to start from scratch and modify SW, I find in OBEX. One example is FDSe (Full Duplex Serial)