Programming Patterns
## Learning Objectives
- Apply MATLAB programming patterns
- Debug code effectively
- Handle errors properly
- Write maintainable code
## Code Organization
### Scripts vs Functions
```matlab
% Script: commands in sequence
% Use for: data processing, quick analysis
% Variables persist in workspace
a = 10;
b = 20;
c = a + b;
disp(c);
% Function: reusable, isolated scope
% Use for: reusable code, algorithms
function result = add(a, b)
result = a + b;
end
```
### Project Organization
```text
myproject/
main.m % Entry point
functions/
processData.m % Data processing
visualize.m % Plotting functions
utils/
helper.m % Utility functions
config/
settings.m % Configuration
```
## Debugging
### Debug Mode
```matlab
% Set breakpoints
% Click line number or use:
dbstop in functionName at lineNumber
% Run in debug mode
myFunction(input)
% Step through
dbstep % Execute next line
dbstep in % Step into function
dbstep out % Step out of function
% Inspect variables
whos % List workspace variables
disp(variable) % Display value
% Resume and quit
dbcont % Continue execution
dbquit % Exit debug mode
```
### dbstop Options
```matlab
dbstop in functionName % Stop at function entry
dbstop in functionName at line % Stop at specific line
dbstop if error % Stop on error
dbstop if warning % Stop on warning
dbstop if naninf % Stop on NaN or Inf
```
### Print Debugging
```matlab
% Display variable values
x = 10;
fprintf('x = %d\n', x);
% Conditional debug output
DEBUG = true;
if DEBUG
disp('Debug: entering loop');
end
% Using keyboard
function process()
% ...
keyboard; % Pauses execution, returns to prompt
% Type 'return' to continue
% Type 'dbquit' to exit
end
```
## Error Handling
### try-catch
```matlab
try
result = riskyOperation();
catch ME
disp('Error occurred:');
disp(ME.message);
end
```
### Detailed Error Information
```matlab
try
x = 10 / 0;
catch ME
disp(['Identifier: ', ME.identifier]);
disp(['Message: ', ME.message]);
disp(['Line: ', num2str(ME.stack(1).line)]);
disp(['Function: ', ME.stack(1).name]);
end
```
### Rethrowing
```matlab
try
x = notAFunction();
catch ME
disp('Custom error handling');
rethrow(ME); % Re-throw with original info
end
```
### Lastwarn and lasterr
```matlab
% Capture warnings
lastwarn(''); % Clear
x = sqrt(-1);
[msg, id] = lastwarn;
% Capture errors
lasterr % Last error message
```
## Conditional Execution
### Checking Inputs
```matlab
function result = processData(data, varargin)
% Validate required input
if ~isnumeric(data)
error('Data must be numeric');
end
% Parse optional parameters
p = inputParser;
p.addOptional('verbose', false, @islogical);
p.addOptional('maxIter', 100, @isnumeric);
p.parse(varargin{:});
opts = p.Results;
end
```
### Input Validation
```matlab
function y = compute(x)
% Validate type
validateattributes(x, {'numeric'}, {'finite'});
% Multiple conditions
validateattributes(x, {'numeric'}, {'positive', 'finite', 'nonnan'});
% Custom validation
if x < 0
error('x must be non-negative');
end
end
```
## Code Quality
### Naming Conventions
```matlab
% Variables: lowercase with underscores (optional)
iteration_count = 0;
totalSum = 0;
% Constants: UPPERCASE
MAX_ITERATIONS = 100;
PI = 3.14159;
% Functions: camelCase or snake_case
function output = calculateArea(radius)
output = pi * radius^2;
end
% Classes: PascalCase (if using OOP)
classdef MyClass
properties
Data
end
end
```
### Comments
```matlab
%{
Multi-line comment block
for longer explanations
%}
% Single line comments for:
% - Function headers
% - Complex calculations
% - TODO items
% TODO: Add error handling
% FIXME: Handle negative values
% NOTE: This algorithm is O(n^2)
```
## Vectorization Patterns
### Replace Loops with Vector Ops
```matlab
% Slow: Loop
result = zeros(1, 1000);
for i = 1:1000
result(i) = sin(i) * cos(i);
end
% Fast: Vectorized
x = 1:1000;
result = sin(x) .* cos(x);
```
### Logical Indexing
```matlab
% Find and replace
A = [1, 2, 3, 4, 5];
A(A > 3) = 10; % A = [1, 2, 3, 10, 10]
% Conditional assignment
B = zeros(size(A));
B(A > 2 & A < 5) = A(A > 2 & A < 5);
```
### Accumarray
```matlab
% Group and aggregate
id = [1, 1, 2, 2, 2, 3];
val = [10, 20, 30, 40, 50, 60];
result = accumarray(id(:), val(:), [], @sum);
% result = [30; 120; 60]
```
## Performance Tips
### Preallocation
```matlab
% Bad: Growing array
result = [];
for i = 1:1000
result = [result, i^2]; % Slow!
end
% Good: Preallocate
result = zeros(1, 1000);
for i = 1:1000
result(i) = i^2;
end
```
### Memory Efficiency
```matlab
% Use appropriate types
a = int8(10); % 1 byte vs 8 bytes for double
% Clear large variables when done
largeArray = rand(10000);
clear largeArray;
% Reuse memory
x = zeros(1000); % Preallocate
x(:) = newData; % Fill without new allocation
```
### Profiling
```matlab
% Profile code execution
profile on
% ... your code ...
profile viewer
% Check timing
tic
% ... code ...
elapsed = toc;
% Use timeit for function timing
f = @() myFunction(data);
t = timeit(f);
```
## Unit Testing
### Simple Test Framework
```matlab
function testResults = runTests()
tests = {
@testAdd,
@testMultiply,
@testDivide
};
passed = 0;
failed = 0;
for i = 1:numel(tests)
try
tests{i}();
passed = passed + 1;
fprintf('PASS: %s\n', func2str(tests{i}));
catch ME
failed = failed + 1;
fprintf('FAIL: %s - %s\n', func2str(tests{i}), ME.message);
end
end
fprintf('\nResults: %d passed, %d failed\n', passed, failed);
end
```
### Test Assertions
```matlab
function testAdd()
result = add(2, 3);
assert(result == 5, 'Expected 2+3=5');
end
function assert(condition, msg)
if ~condition
error(msg);
end
end
```
## Logging
### Simple Logging
```matlab
function logMessage(level, msg)
fprintf('[%s] %s: %s\n', datestr(now), level, msg);
end
logMessage('INFO', 'Processing started');
logMessage('WARN', 'Low memory');
logMessage('ERROR', 'File not found');
```
### Debug Flag
```matlab
function myFunction(data, debug)
if nargin < 2
debug = false;
end
if debug
fprintf('Input size: %d x %d\n', size(data));
end
% Main logic...
if debug
fprintf('Output size: %d x %d\n', size(result));
end
end
```
## Summary
- Use scripts for sequences, functions for reusable code
- Set breakpoints with `dbstop`, use `dbstep` to navigate
- Wrap risky code in `try-catch` blocks
- Validate inputs with `validateattributes`
- Vectorize loops for performance
- Preallocate arrays before filling
- Use `profile` and `tic/toc` for optimization
- Write tests to verify correctness
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →