Upload
juin-der-lee
View
141
Download
1
Tags:
Embed Size (px)
Citation preview
•An Example of bad function
•Advantages of using functions
•Cohesion
•Coupling
•Defensive functions
Outline
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := Revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := Revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := Revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := Revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := revenue[i].Type3[i] endend
•Function name
•No comments
•Inconsistent Layout
•Frequently Access Global variables
•No error handling
•Magic numbers
•Some input arguments are not used
•Too many parameters
Problems
An Example of bad function
Procedure HandleStuff( Var InputRec: CORP_DATA,
CrntQtr: integer, Emprec: EMP_DATA,
Var EstimRevenue: Real, YTDRevenue: Real,
ScreenX: integer, ScreenY: integer,
Var NewColor: COLOR_TYPE, Var PreColor: COLOR_TYPE,
Var Status:STATUS_TYPE, ExpenseType: integer);
Begin
for I := 1 to 100 do begin
InputRec.revenue[i] := 0;
InputRec.expense[i] := CorpExpense[ CrntQtr, i]
end;
UpdateCorpDatabse( EmpRec );EstimRevenue := YTDRevenue * 4.0 / real( CrntQtr );NewColor := PrevColor;Status := Success;if ExpenseType = 1 then begin for I := 1 to 12 do Profit[i] := Revenue[i] – Expense. Type1[i] endelse if ExpenseType = 2 then begin Profit[i] := Revenue[i] – Expense.Type2[i] endelse if ExpenseType = 3 then begin Profit[i] := revenue[i].Type3[i] endend
Advantages of using functions
if ( Node <> NULL)
while ( Node.Next <> NULL ) do
Node = Node.Next
LeafName = Node.Name
else
LeafName = “”
End
•Reduce program complex
•Readability
•Avoid redundant code
•Information hiding
•Data structure
•Algorithm (how it does vs. what it does)
•Reusability
LeafName = GetLeafName (Node);
node
root
node
leaf
using functions even simple codes
Points = DeviceUnits * (POINTS_PER_INCH / DeviceUnitsPerInch());
DeviceUnitsToPoints(DeviceUnits Integer) : Integer;
begin
DeviceUnitsToPoints = DeviceUnits * (POINTS_PER_INCH / DeviceUnitsPerInch());
end
Points = DeviceUnitsToPoints( DeviceUnits );
•Functional Cohesion
•Sequential Cohesion
•Communicational Cohesion
•Temporal Cohesion
Cohesion
(Why those codes are put together into a function)
•Work together for a single purpose•sin()•GetCustomerName()•EraseFile()•CalcLoanPayment()•GetIconLocation()
Functional Cohesion
•Sequential operations
Sequential Cohesion
Function f()
//OpenFile
…
//ReadFile
…
//Calculate
…
//OutputResult
…
//CloseFile
…
return
Function f()
//Input Birthday
…
//Calculate Age
…
//Calculate Retire Date
…
return
•Access the same data
Communication Cohesion
Function f()
//Print Abstract
…
//Initialize Abstract
…
return
•In this example, no functional or sequential cohesion
•Operations at the same time
•Startup(), shutdown()
Temporal Cohesion
Function Startup()
//load configure file
…
//Initialize temporary file
…
//setup memory management program
…
//display startup screen
…
return
•Simple data coupling
•Structural data coupling
•Control coupling
•Global data coupling
•Content coupling (Basic and assembly language)
Coupling
(Relations between two functions)
•Parameters are simple data type•The fewer the number of parameters the better •sin(double angle)
Simple Data Coupling
•Parameters are complex data type (i.e. structure)
•It’s not a good idea to passing structure variable if not all fields are used
Structural Data Coupling
Struct EmpRec
{
String name;
String address;
String phoneNumber;
String birthday;
String IDNumber;
};
…
PrintLetter(EmpRec ER);
Void PrintLetter(EmpRec ER)
{
//print Name
…
//print address
…
}
Void PrintLetter(string name, string address)
{//…}
•Control the behavior of callee function
Control Coupling
Void PrintCalendar(int op)
{
if (op==1)
//print yearly
…
else if (op==2)
//print monthly
…
else if (op==3)
//print weekly
…
}
Void PrintCalendarYearly()
{
…
}
Void PrintCalendarMonthly(){ … }
Void PrintCalendarWeekly(){ … }
•Functions communicate through global data
Global Data Coupling
Function f1()
{
//do something to g_var
…
//call f2()
f2();
…
}
Function f2()
{
//do something to g_var
…
}
global g_var;
Assert
assert( assumption, error message);
Example:
assert( Denominator <> 0, ‘the denominator is zero’);
•Supported by C language, but not Matlab
function assert( assumption, errmsg)
if ~all(assumption),
error( errmsg );
end
return
Examples of using assert
function f(x)
%x is a 3-by-4 matrix
assert( size(x)==[3 4], ‘x is not a 3-by-4 matrix’);
…
return
Check data size:
assert( fclose(fid) ~= 0, ‘error closing file’);
Check operation status:
status = fclose(fid);
assert( status ~= 0, ‘error closing file’);