This should all work fine. Can you make a standalone example (as small as possible) that demonstrates the method signature problem and attach it to this thread?

The property question while also related to inheritance, is probably a different discussion, and I'd recommend working up a small example about that and starting a new discussion, but I'll leave it to your judgment if you think it would better fit here.

In general, classic single inheritance in Zen should work exactly as expected -- and has worked in my experience pretty much from day one.

If you copy the client method to a client method with a different name, do you still have the duplicate parameter in the new client method code?

What do you get for the output from the following commands? Replace "YourApp.Page" with the name of your page or component class (without any .cls or .zen extension).
Set sig=##class(%Dictionary.CompiledMethod).IDKEYOpen("YourApp.Page","doReturn").FormalSpecParsed
Write $LL(sig),! zzdump sig

In a database, your most important asset is your data -- business logic and code comes a close second. There should at least be someone paying attention to the data slots for sanity, even though in most cases, there is nothing to do. At the very least, any developer adding or modifying properties should "diff" the storage definition when submitting code to the source repository. The class compiler by default will handle everything correctly.

1. The simplest and best way to move from one version of a class to the next is to keep the same storage definition. The class compiler will create slots for any new properties and is completely non-destructive and conservative. When I retire properties, I generally manually rename the storage slot and give it a prefix such as zzz<retiredPropertyName>. This allows me to explicitly clean up and reuse these slots later if I so choose.

2. For the type of before/after compile triggers you are looking for, I would use the RemoveProjection/CreateProjection methods of a projection class which provide "a way to customize what happens when a class is compiled or removed".

3. You can use %Dictionary.CompiledStorage and related classes(Data) to have full access to the compiled storage definition of a class.

3a. An alternate approach is to use XSLT or XML parsing to read the storage definition from the exported class definition. I would only use this alternative if you need to capture details for separate source control purposes.

4. The simplest storage definitions use $ListBuild slots and a single global node. When subclasses and collection properties are used, the default storage definition gets more complicated -- that is where you will really want to stick to the simple approach (item 1).

I lean toward the manifest solution: By explicitly creating configuration changes in code, one avoids the problems of having to import and export the changes which carries the risk of missing something and also the risk of propagating a change unintentionally.


I prefer using configuration exports for detecting out-of-band changes to configuration and triggering a corrective workflow where needed; this allows for the [hopefully] rare cases where not all changes should be propagated between environments.