Borrar filtros
Borrar filtros

proper namespace organisation with classes and enums

10 visualizaciones (últimos 30 días)
Dimitrii Nikolaev
Dimitrii Nikolaev el 26 de Mzo. de 2021
Respondida: Sameer el 7 de Jun. de 2024
Hi Folks,
I'm curious of how to proper organise a folder structure for xx
Setting
Consider I'm developing a driver class for some DeviceA made by Manufacturer.
I assume, that I will use this DeviceA in several more Projects and I probably will get another one DeviceB, which use the same manufacturer-specific enumerated definitions of something - let`s say the volume levels will be defined as:
classdef enumVolumeLevels < uint8
enumeration
volLow (0)
volMid (50)
volHigh (100)
end
end
So I will write some kine of driver class including everything manufacturer-specific either as constants or as enumerations.
Folder Structure
So my Folderstructure will look like:
%rootfolder:
.\+Manufacturer\@DeviceA\DeviceA.m % class definition including constructor and destructor methods and some property 'Volume'
.\+Manufacturer\@DeviceA\SomeMethod.m % Methods will be stored separately in class folder
.\+Manufacturer\enumVolumeLevels.m % enumeration class containing manufacturer-specific definitions of volume levels
Now if I'm going to write a setter and getter method, which both checks If the provided Value fits to the manufacturer-defined levels
classdef DeviceA
% [...]
methods
%getter
function value = get.Volume(obj)
value = Manufacturer.enumVolumeLevels(50); %some dummy getter method
end
%setter
function set.Volume(obj,level)
arguments
obj
mode Manufacturer.enumVolumeLevels
end
% some dummy setter method
end
end
%[...]
end
Standalone usage
Now I'm goind to test my class from the root folder of this project.
... and works fine if I define an object of this class and assign or read the property Volume
test = Manufacturer.DeviceA(); %call constructor
test.Volume = 50; %set property to something
disp(test.Volume); % display this property
Code Refactoring
Following the initial Idea of writing this driver class to use it in several Application specific projects I will include it into root folder of ProjectA, which looks like:
%rootfolder of ProjectA:
.\+Drivers\+Manufacturer\@DeviceA\DeviceA.m % class definition including constructor and destructor methods and some property 'Volume'
.\+Drivers\+Manufacturer\@DeviceA\SomeMethod.m % Methods will be stored separately in class folder
.\+Drivers\+Manufacturer\enumVolumeLevels.m % enumeration class containing manufacturer-specific definitions of volume levels
.\MyFunc.m %some script containing instancesof the DeviceA-class
But if I write MyFunc.m as follows:
function MyFunc
test = Drivers.Manufacturer.DeviceA(); % call constructor
test.Volume = 50; % set property to something
disp(test.Volume); % display this property
end
... it will fail after the 2nd line because from the setter point of view the enumeration class Manufacturer.enumVolumeLevels is not defined.
So my question is:
--> Is there a solution for organizing my namespace folders to avoid such visibility Problem?
Perhaps I'll need to chanhe the folder structure of my Manufacturer-package or the way I use the enumeration class in my class DeviceA, but I'm completely stuck right now and have no Idea, what should be the best practice in this case,

Respuestas (1)

Sameer
Sameer el 7 de Jun. de 2024
Hi Dimitrii,
The issue stems from how MATLAB handles namespaces and package folders, especially when you start nesting them or referencing them from different locations. When you moved your DeviceA class and the enumVolumeLevels enumeration into a +Drivers subpackage for use in ProjectA, MATLAB's ability to resolve the reference to enumVolumeLevels from within DeviceA was affected because the namespace in which "DeviceA" expects to find enumVolumeLevels has changed.
To resolve the visibility problem and maintain an organized folder structure that accommodates reuse across multiple projects, consider the following solutions:
1. Use Fully Qualified Names
One immediate solution is to use fully qualified names when referencing the enumeration class. This means specifying the entire package path whenever you refer to enumVolumeLevels inside your DeviceA methods.
For example, in your DeviceA setter method, instead of:
mode Manufacturer.enumVolumeLevels
You would use:
mode Drivers.Manufacturer.enumVolumeLevels
However, this approach tightly couples your DeviceA class to the Drivers package, reducing its reusability outside of this specific structure.
2. Dynamic Path Management
A more flexible solution involves dynamically adding the required package paths at runtime, ensuring that MATLAB can always resolve the enumeration class regardless of the project structure. This can be achieved by modifying the class constructor or creating an initialization script that adds the necessary package directories to MATLAB's path. For example:
classdef DeviceA
methods
function obj = DeviceA()
% Add the Manufacturer package to the path if not already present
manufacturerPath = fullfile(fileparts(mfilename('fullpath')), '..', 'Manufacturer');
if ~contains(path, manufacturerPath)
addpath(manufacturerPath);
end
end
end
end
This script checks if the Manufacturer package directory is on MATLAB's path and adds it if not. This way, references to enumVolumeLevels can be resolved regardless of the project structure. However, be cautious with dynamic path modifications, as they can lead to conflicts or unexpected behavior if not managed carefully.
3. Reconsider the Folder Structure
Another approach is to reconsider the folder structure to ensure that all related classes and enumerations are always within the same namespace, reducing the need for fully qualified names or dynamic path adjustments. For example, you could structure your folders like this:
+Manufacturer
+DeviceA
- @DeviceA
DeviceA.m
- SomeMethod.m
- enumVolumeLevels.m
And then, when incorporating it into ProjectA, instead of nesting it further, you could place it at a level where the Manufacturer namespace remains consistent:
+Drivers
+Manufacturer
...
ProjectA.m
In this structure, ProjectA.m or any function/script within the ProjectA context would reference DeviceA and enumVolumeLevels through the Drivers.Manufacturer namespace, maintaining consistency across projects.
I hope this helps!
Sameer

Categorías

Más información sobre Argument Definitions en Help Center y File Exchange.

Productos


Versión

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by