I do not understand the macro concept well. What is a macro? I do not understand how is it different from function? Both function and macro contain a block of code. So how does macro and function differ?
Programming Practices – What is a Macro and How it Differs from a Function
programming practices
Related Solutions
A typedef
is generally preferred unless there's some odd reason that you specifically need a macro.
macros do textual substitution, which can do considerable violence to the semantics of the code. For example, given:
#define MYINTEGER int
you could legally write:
short MYINTEGER x = 42;
because short MYINTEGER
expands to short int
.
On the other hand, with a typedef:
typedef int MYINTEGER:
the name MYINTEGER
is another name for the type int
, not a textual substitution for the keyword "int".
Things get even worse with more complicated types. For example, given this:
typedef char *char_ptr;
char_ptr a, b;
#define CHAR_PTR char*
CHAR_PTR c, d;
a
, b
, and c
are all pointers, but d
is a char
, because the last line expands to:
char* c, d;
which is equivalent to
char *c;
char d;
(Typedefs for pointer types are usually not a good idea, but this illustrates the point.)
Another odd case:
#define DWORD long
DWORD double x; /* Huh? */
One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes. Using metrics such as LCOM4 (Lack of Cohesive Methods), as pointed out by gnat in this answer here, you can identify classes that could be refactored. The reason you want to refactor methods or classes to be more cohesive is that it makes the code design simpler for others to use it. Trust me; most tech leads and maintenance programmers will love you when you fix these issues.
You can use tools in your build process such as Sonar to identify low cohesion in the code base. There are a couple of very common cases that I can think of where methods are low in "cohesiveness":
Case 1: Method is not related to the class at all
Consider the following example:
public class Food {
private int _foodValue = 10;
public void Eat() {
_foodValue -= 1;
}
public void Replenish() {
_foodValue += 1;
}
public void Discharge() {
Console.WriteLine("Nnngghhh!");
}
}
One of the methods, Discharge()
, lacks cohesion because it doesn't touch any of the class's private members. In this case there is only one private member: _foodValue
. If it doesn't do anything with the class internals, then does it really belong there? The method could be moved to another class that could be named e.g.FoodDischarger
.
// Non-cohesive function extracted to another class, which can
// be potentially reused in other contexts
public FoodDischarger {
public void Discharge() {
Console.WriteLine("Nnngghhh!");
}
}
In you're doing it in Javascript, since functions are first-class objects, the discharge can be a free function:
function Food() {
this._foodValue = 10;
}
Food.prototype.eat = function() {
this._foodValue -= 1;
};
Food.prototype.replenish = function() {
this._foodValue += 1;
};
// This
Food.prototype.discharge = function() {
console.log('Nnngghhh!');
};
// can easily be refactored to:
var discharge = function() {
console.log('Nnngghhh!');
};
// making it easily reusable without creating a class
Case 2: Utility Class
This is actually a common case that breaks cohesion. Everyone loves utility classes, but these usually indicate design flaws and most of the time makes the codebase trickier to maintain (because of the high dependency associated with utility classes). Consider the following classes:
public class Food {
public int FoodValue { get; set; }
}
public static class FoodHelper {
public static void EatFood(Food food) {
food.FoodValue -= 1;
}
public static void ReplenishFood(Food food) {
food.FoodValue += 1;
}
}
Here we can see that the utility class needs to access a property in the class Food
. The methods in the utility class has no cohesion at all in this case because it needs outside resources to do it's work. In this case, wouldn't it be better to have the methods in the class they're working with itself (much like in the first case)?
Case 2b: Hidden objects in Utility Classes
There is another case of utility classes where there are unrealized domain objects. The first knee-jerk reaction a programmer has when programming string manipulation is to write a utility class for it. Like the one here that validates a couple of common string representations:
public static class StringUtils {
public static bool ValidateZipCode(string zipcode) {
// validation logic
}
public static bool ValidatePhoneNumber(string phoneNumber) {
// validation logic
}
}
What most don't realize here is that a zip code, a phone number, or any other string repesentation can be an object itself:
public class ZipCode {
private string _zipCode;
public bool Validates() {
// validation logic for _zipCode
}
}
public class PhoneNumber {
private string _phoneNumber;
public bool Validates() {
// validation logic for _phoneNumber
}
}
The notion that you shouldn't "handle strings" directly is detailed in this blogpost by @codemonkeyism, but is closely related to cohesion because the way programmers use strings by putting logic in utility classes.
Best Answer
Note
I would like to add the following clarification after observing the polarising voting pattern on this answer.
The answer was not written keeping technical accuracy and broad generalization in mind. It was a humble attempt to explain in simple language, difference between macros and functions to a programming newbie, without trying to be complete or accurate (in fact it's far from being accurate). C programming language was in my mind when drafting the answer, but my apologies for not mentioning it clearly and causing any (potential) confusion.
I really regard the answer shared by Jörg W Mittag. It was insightful reading it (how less I know) and I upvoted it soon after it was posted. I just got started on Software Engineering Stack Exchange, and the experience and discussions so far have been really insightful.
I will leave this answer here as it may be helpful for other software development newbies, trying to understand a concept without getting bogged down into technical accuracies.
Both macro and function represent self contained unit of code. They both are tool which aid in modular design of a program. From the point of view of the programmer who's writing the source code, they appear quite similar. However, they differ in how they are handled during the program execution lifecycle.
A macro is defined once and used in a lot of places in a program. Macro gets expanded inline during the pre-processing stage. Thus, it technically doesn't remain a separate entity once the source code is compiled. The statements in macro definition becomes part of program instructions, just like other statements.
The motive behind writing a macro is to make writing and managing source code easier for the programmer. Macros are generally desired for simpler tasks where writing a full-fledged function would be a performance overhead/runtime penalty. Examples of situations where a macro is preferable over function are:
Using constant values (such as mathematical or scientific values), or some program specific parameter.
Printing log messages or handling assertions.
Performing simple calculations or condition checks.
When using macro, it's easy to make changes/corrections in one place which are instantly available everywhere the macro is used in the program. A simple recompilation of program is required for the changes to take effect.
Function code on the other hand is compiled as a separate unit within the program and gets loaded in the memory during program execution only if it's required. The function code retains it's independent identity from the rest of the program. The loaded code gets reused if the function is called more than once. When the function call is encountered in the running program, the control is passed to it by the runtime subsystem and the context of the running program (return instruction address) is preserved.
However, there's a slight performance penalty that needs to be encountered when calling a function (context switching, preserving return address of the main program instructions, passing parameters and handling return values etc.). Hence, the use of function is desired only for complex blocks of code (against macros which handles simpler cases).
With experience, a programmer makes a judicious decision as whether a piece of code will be a good fit as a macro or function in the overall program architecture.