Next: Mimickry Principle
Up: Modularity Principle
Previous: Separating Parser from
If a function performs two tasks, there should be individual functions to implement the two tasks. This separation will allow calling one of the two parts separately, as well as the benefits described in the parser example.
In essence, TypeCheckExpr and CodeGenExpr help to encapsulate their respective design decisions, while ExprAction encapsulates the decision in how these two components are composed (e.g., how a type checking error is handled).
/* * ExprAction has at least two tasks to perform. * Rather than inlining them, separate them. This * allows using the typechecking and code generating * routines separately, debugging them separately, * and reusing them separately, etc. */ SymTabEntry ExprAction(SymTabEntry A, int Op, SymTabEntry B) { Type restype; restype = TypeCheckExpr(Op,A,B); /* first task */ if (restype != ErrorType) CodeGenExpr(restype,Op,A,B); /* second task */ return restype; }
Note that in general, a single function is not sufficient to encapsulate
a design decision. Usually a set of related functions is required. For
example, there must be additional functions for type checking procedure
declarations.