MATLAB Answers

Readability of matlab code

조회 수: 58(최근 30일)
AM
AM 5 Mar 2021
편집: Bruno Luong 8 Mar 2021
Hi,
I am coding using matlab and have many functions, some of which have more than a dozen input arguments. The majority of the input arguments of my different functions are variables that I read from an external file and that remain unchanged all throughout the calculations. Basically I read the external file once in my main script then give what has been read as input arguments to the other functions. For the readability of my code, I would like to not have that many input arguments and was wondering what is the best solution that would not negatively impact the performance of my code. I thought of the following:
  • use global variables, however I've read that it is best to avoid them
  • read the external file and save the different variables as .mat then load the arguments inside each function
  • define a cell variable in which I store all my arguments, e.g. cell={a;b;c} and give that as an input to my functions, then inside the function declare the variables as a=cell{1} etc
If anyone could help me choose the best solution or give me more ideas I would greatly appreciate it!
  댓글 수: 2
AM
AM 5 Mar 2021
Scalar structures seem to be something that would work great in my case, I will look into them more, thank you very much!

댓글을 달려면 로그인하십시오.

채택된 답변

BC
BC 5 Mar 2021
I recently had a similar question, and one of the options that was suggested was to use structures, e.g.
Function1_Parameter.Variable1 = 1
Function1_Parameter.Variable2 = 2
Function1_Parameter.Variable3 = 3
So then you only need to have the name of the structure (Function1_Parameter) in the input arguments of a function, and you can index whichever value you need, similar to your last suggestion.
  댓글 수: 2
AM
AM 8 Mar 2021
Thank you!

댓글을 달려면 로그인하십시오.

추가 답변(3개)

John D'Errico
John D'Errico 5 Mar 2021
편집: John D'Errico 5 Mar 2021
AVOID GLOBAL VARIABLES. They will not improve your code. Intead they will make it difficult as hell to debug your code when there is a problem.
Next, don't just store all of your arguments in a cell array. That would simply force you to remember what parameter lies in ARGS{7}, etc. This is a recipe for buggy code, and certainly not readable code that can be maintained easily.
The various suggestions I see are all good ideas. Another idea is to use preferences, thus setpref and getpref. I use this sometimes when I want to set some general behavior for a function. Other things are property/value pairs, and structures. You can even combine all of these things in various ways. Let me give a few examples:
The examples I'll offer are my HPF toolbox, fmincon, and my SLM toolbox. How are each of these tools different?
For example, fmincon is a tool that has quite a few arguments, most of which are not used at least some of the time. The basic calling sequence for fmincon is something like this:
X = fmincon(FUN,X0,A,B,Aeq,Beq,LB,UB,NONLCON,OPTIONS)
Now much of the time, you may want to call fmincon, but only have a set of linear equality constraints on the objective. In that case, you call it like:
X = fmincon(FUN,X0,[],[],Aeq,Beq);
Or, if you have only bound constraints, then you need to write it as:
X = fmincon(FUN,X0,[],[],[],[],lb,ub);
And you need to know how many sets of empty brackets to put in there. This can be a confusing way to interact with the tool.
So an alternative way to have written fmincon might be to have only three arguments.
X = fmincon(FUN,X0,params);
Here params would be a structure, containing every possible piece of information fmincon would need. Thus if there are only upper and lower bounds on the problem, then we would have
params.lb = [1 2 3];
params.ub = [2 3 5];
If there were equality or inequality constraints on the problem, then params would have corresponding fields to supply them.
(Yes, the optimization toolbox tools in recent releases do now have better interfaces that allow for essentially this kind of interaction.)
I mentioned preferences before. In fact, if you have my hpf toolbox installed on your computer, then try accessing the prefs for 'hpf'. On my computer, I see this:
>> getpref('hpf')
ans =
struct with fields:
DefaultDecimalBase: 3
DefaultNumberOfDigits: [50 5]
In the preferences, that tool puts several pieces of information. The tool itself can then extract them as needed. Preferences are a convenient place to store such information. But as a tool, hpf only has a few such overarching parameters that you may wish to set. And that makes preferecnes a decent place to store and access them, especially since prefs are remembered across MATLAB sessions.
Next, look at my SLM toolbox. It has a function called slmset.
slmset
ans =
struct with fields:
C2: 'on'
ConcaveDown: 'off'
ConcaveUp: 'off'
ConstantRegion: []
Decreasing: 'off'
Degree: 3
EndConditions: 'estimate'
Envelope: 'off'
ErrorBar: []
Extrapolation: 'constant'
FminconAlgorithm: 'interior-point'
Increasing: 'off'
Integral: []
InteriorKnots: 'fixed'
Jerk: ''
Knots: 6
LeftMaxSlope: []
LeftMaxValue: []
LeftMinSlope: []
LeftMinValue: []
LeftSlope: []
LeftValue: []
LinearRegion: []
LsqlinAlgorithm: 'interior-point'
MaxFpp: []
MaxSlope: []
MaxValue: []
MinFpp: []
MinSlope: []
MinValue: []
NegativeInflection: []
Order: []
Plot: 'off'
PositiveInflection: []
Predictions: 1001
Regularization: 0.0001
Result: 'slm'
RightMaxSlope: []
RightMaxValue: []
RightMinSlope: []
RightMinValue: []
RightSlope: []
RightValue: []
Robust: 'off'
Scaling: 'on'
SegmentConstant: []
SegmentLinear: []
SimplePeak: []
SimpleValley: []
SumResiduals: []
Verbosity: 0
Weights: []
XY: []
XYP: []
XYPP: []
XYPPP: []
YScale: []
YShift: []
slmset is a function that returns a structer with the default value for every possible property. You can also call slmset with property value pairs to create a similar structure with your choice of properties. Calling the slmengine code with no other arguments than some data, and you get all the defaults from slmset applied, thus:
spl = slmengine(x,y)
x = 1:5;
y = rand(1,5);
slm = slmengine(x,y)
slm =
struct with fields:
form: 'slm'
degree: 3
knots: [6×1 double]
coef: [6×2 double]
stats: [1×1 struct]
prescription: [1×1 struct]
x: [5×1 double]
y: [5×1 double]
Extrapolation: 'constant'
As you see in the call to slmset, the default for 'knots' was 6. If you want to use some other value than the default, you override it by providing the specific property, as:
spl = slmengine(x,y,'knots',12)
So here 12 knots would be used, but all other properties reside at their default values.
Had I wanted to be even more user friendly, suppose you alwys find yourself changing my defaults for some property? Then I might have used preferences to allow that to work. (Note that this is NOT something that slmset checks, but I could have written it that way, to be even more user friendly.)
setpref('slm','knots',12)
I could now access that preference.
getpref('slm','knots')
ans =
12
There are surely many other schemes that can be used. And some schemes will be better than others in various applications.
  댓글 수: 1
AM
AM 8 Mar 2021
Thank you very much for taking the time to answer my question in such detail !

댓글을 달려면 로그인하십시오.


Cris LaPierre
Cris LaPierre 5 Mar 2021
편집: Cris LaPierre 5 Mar 2021
I would not recommend global variables.
Perhaps look into nested functions. All variables defined in the parent function are accessable inside a nested function without having to pass them in.
You can see an example in this answer.

Bruno Luong
Bruno Luong 8 Mar 2021
편집: Bruno Luong 8 Mar 2021
Why not use object oriented programing? Put your external parameters in properties. Put your functions as methods.
Implement an Initialization function that load the external file and populate the properties.
All the methods has then access to the properties.

제품


릴리스

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by