Namespace management for packages+sub-packages

21 views (last 30 days)
Hello all, I have a question regarding namespace management for a series of packages and sub-packages.
Let us create a folder structure like this
.\+Behaviors\+Quacking\quackBehavior.m
.\+Behaviors\+Quacking\Quack.m
.\+Behaviors\+Quacking\MuteQuack.m
With the interface class
classdef (Abstract) quackBehavior < handle
methods (Abstract)
perform(obj)
end
end
And the concrete subclasses
classdef Quack < quackBehavior
methods
function perform(~)
disp('Quack!')
end
end
end
and
classdef muteQuack < quackBehavior
methods
function perform(~)
disp('<<silence>>')
end
end
end
All of this is to implement something like
duck.vocalization = Behaviors.Quacking.Quack;
perform(duck.vocalization)
Ok, the issue is that due to the package namespace, both of the concrete subclasses throw errors of the form: The class 'quackBehavior' contains a parse error, cannot be found on MATLAB's search path, or is shadowed by another file with the same name.
Now, I know how to practically fix this, I need to change Quack.m to:
classdef Quack < Behaviors.Quacking.quackBehavior
methods
function perform(~)
disp('Quack!')
end
end
end
and similarly for muteQuack.m. This works, but seems to violate the desired behavior in two ways:
  • Quack.m is in the same +Quacking package as quackBehavior.m; why does it need to know the full package name? I know that this is also a requirement of static methods, since you aren't accessing an object of the class. Still, it strikes me as defeating the purpose of packaging the classes in the first place. It might be better from a code standpoint to leave everything in one massive root-folder in Matlab's path, but then I lose all of the control for overloading functions. What if I also had a duck species named 'Quack', and needed a seperate classdef ./+Ducks/Quack.m, so that duck = Ducks.Quack; duck.vocalization = Behaviors.Quacking.Quack. There does not seem to be any namespace ambiguity if I do not include the full package path in the classdef, as the behaviors are encapsulated in their own packages, as the ducks are in theirs.
  • If I later enclose +Behaviors in another package, e.g. ./+WaterfowlToolkit/+Behaviors/... then I have to manually modify all of the classdef lines in every class in every package below +WaterFowlToolkit. This strikes me as a minefield for code maintainence and reuse.
So, is there a better way of doing this that takes care of the above concerns? Is there a trick using import, e.g. import +WaterfowlToolkit/*, or something in that vein that would give the deisred behavior; the ability to nest packages as above to maintain some organizational sanity in large code sets and maintain overload/namespace control without needing to define the full package heirarchy in every classdef?

Accepted Answer

jg
jg on 27 May 2020
If you figure out let us know... this has been a major complaint for 4+ years and no response yet from Mathworks. It makes packages useless.
  2 Comments
Daniel Plotnick
Daniel Plotnick on 29 May 2020
Thanks. That is quite annoying, and good to see that a lot of the more reputable Matlab answers folks (per isakson, Guillame, etc.) have the same complaint. I'm going to put in a feature request and reference these posts.
ET
ET on 17 Aug 2021
I concur this is frustrating. I ran across this question looking for an answer to the similar issue. Matlab, please fix this.

Sign in to comment.

More Answers (2)

per isakson
per isakson on 28 May 2020
Yes, that's the way it is. And sprinkle the code with import doesn't really help.
Nevertheless, I find packages useful. A better tool to change the names, e.g. Find and Replace in Files or an editor like Notepad++ is useful.
  1 Comment
Daniel Plotnick
Daniel Plotnick on 29 May 2020
Thanks. it is both good and infuriating to know that this is how they actually built this. I'll throw another "feature request" into them .

Sign in to comment.


Steven Lord
Steven Lord on 17 Aug 2021
Quack.m is in the same +Quacking package as quackBehavior.m; why does it need to know the full package name?
Let's say you had three files.
foo.m
+package1/foo.m
+package1/baz.m
Under the current system, calling foo() inside package1.baz invokes the first file in that list. Calling package1.foo() inside package1.baz invokes the second.
If package files were "automatically imported" into other files in the same package, calling foo() inside package1.baz would invoke the second file in that list and there would at present be no way to invoke the first file (at least not without some tricky manipulation.) The package file would take precedent over the non-package file.
In your example you may say "The likelihood of someone having a top-level Quack.m and a package function Behavior.Quacking.Quack.m is low." But consider functions included in MATLAB: how likely is it that someone would have a specialized package plotting function named mypackage.plot() that itself could try to call the built-in plot function? Under your design that mypackage.plot() would be an infinite loop (unless you called builtin or the like.)
  1 Comment
Jim Svensson
Jim Svensson on 26 Aug 2021
Edited: Jim Svensson on 26 Aug 2021
You example is really moot. The person that designs package1 knows if he wants to call some global foo() elsewhere and would then not have a packag1.foo(). And secondly just because there is currently would be no way to call the global foo() does not mean it should remain that way.
Anyway, anyone that have worked with modern languages that understands the importance of namespaces understand that the current Matlab design is really bad and not suitable for large scale programming, or even medium scale programming. Which is very sad because Matlab is so powerful in many ways but really frustrating for some things. Clearly there are some clever people working with the backend, but the language itself needs more improvements. For example that we in 2021 don't even have "operator assignement" statements is a pity.
That someone working at Mathworks tries to justify the current bad design makes it even worse.
At least give us a way to refer to current package without the full package path. For example ".foo()" to mean "<current_package_path>.foo()", or "$.foo()", or something.

Sign in to comment.

Categories

Find more on Software Development Tools in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!