Namespace management for packages+sub-packages
27 views (last 30 days)
Show older comments
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
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
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.
More Answers (2)
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.
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.)
2 Comments
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.
Ashley Trowell
on 4 Apr 2024
This is probably the worst defect of Matlab, because it punishes code reuse and organization for the life of your project. Furthermore, the punishment scales up as your project grows, as these refactors (which would be unnecisary in other languages) only grow in difficulty as the project grows.
As a result, it forces serious developers to migrate away from the language, which in turn ensures that the most dedicated MATLAB users won't stick around long enough to enrich the community with their contributions on File Exchange and the like. This creates a persistent brain drain on the community, which is a pity, because one of the most valuable things about any given language is the community which is attracted to that language.
See Also
Categories
Find more on Construct and Work with Object Arrays 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!