Top Banner
Notes about writing Notes about writing functions functions Juin-Der Lee
37
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Notes about writing functions

Notes about writing functionsNotes about writing functions

Juin-Der Lee

Page 2: Notes about writing functions

•Software Design

•Procedural Programming

•Factory

•Matlab

•Object-Oriented Programming

Page 3: Notes about writing functions

Input dataLocal data

function

Output data

Local data

function

Global data

Page 4: Notes about writing functions

•An Example of bad function

•Advantages of using functions

•Cohesion

•Coupling

•Defensive functions

Outline

Page 5: Notes about writing functions

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

Page 6: Notes about writing functions

•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

Page 7: Notes about writing functions

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

Page 8: Notes about writing functions

•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

Page 9: Notes about writing functions

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

Page 10: Notes about writing functions

•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

Page 11: Notes about writing functions

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

Page 12: Notes about writing functions

•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

Page 13: Notes about writing functions

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

Page 14: Notes about writing functions

•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

Page 15: Notes about writing functions

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

Page 16: Notes about writing functions

•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

Page 17: Notes about writing functions

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

Page 18: Notes about writing functions

•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

Page 19: Notes about writing functions

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

Page 20: Notes about writing functions

•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

Page 21: Notes about writing functions

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

Page 22: Notes about writing functions

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

Page 23: Notes about writing functions

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 );

Page 24: Notes about writing functions

•Functional Cohesion

•Sequential Cohesion

•Communicational Cohesion

•Temporal Cohesion

Cohesion

(Why those codes are put together into a function)

Page 25: Notes about writing functions

•Work together for a single purpose•sin()•GetCustomerName()•EraseFile()•CalcLoanPayment()•GetIconLocation()

Functional Cohesion

Page 26: Notes about writing functions

•Sequential operations

Sequential Cohesion

Function f()

//OpenFile

//ReadFile

//Calculate

//OutputResult

//CloseFile

return

Function f()

//Input Birthday

//Calculate Age

//Calculate Retire Date

return

Page 27: Notes about writing functions

•Access the same data

Communication Cohesion

Function f()

//Print Abstract

//Initialize Abstract

return

•In this example, no functional or sequential cohesion

Page 28: Notes about writing functions

•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

Page 29: Notes about writing functions

•Simple data coupling

•Structural data coupling

•Control coupling

•Global data coupling

•Content coupling (Basic and assembly language)

Coupling

(Relations between two functions)

Page 30: Notes about writing functions

•Parameters are simple data type•The fewer the number of parameters the better •sin(double angle)

Simple Data Coupling

Page 31: Notes about writing functions

•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)

{//…}

Page 32: Notes about writing functions

•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(){ … }

Page 33: Notes about writing functions

•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;

Page 34: Notes about writing functions

Defensive Functions

•Driving car

•Assumption

•Assert()

Page 35: Notes about writing functions

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

Page 36: Notes about writing functions

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’);

Page 37: Notes about writing functions

summary

•Take advantages of using functions whenever possible

•Maximize cohesion

•Minimize coupling

•Make functions defensive using assert()