[NSWI004] Where to put it?

Lubomír Bulej bulej at d3s.mff.cuni.cz
Thu Oct 29 11:54:22 CET 2020


Hi,

if not the most authoritative, then definitely the most verbose :-) Anyway, I
would not change anything on what Petr recommends, so if you don't feel like
reading more, just ignore the rest of my message. Really.


First, with respect to replacing a literal with a macro (or a simple
expression with a function). This is generally good practice, because it adds
extra information to code, which I believe should be "written for humans".
This requires using problem-related concepts and vocabulary (avoiding
ambiguous constant literals) and making intent visible. The compiler or the
CPU could not care less, but humans do.

In general, a good practice is to split code into short functions with
descriptive names, as well as separate code with different responsibilities
into separate functions (some deal with implementation details, others do
coordination or error handling, etc.).

A simple rule that I apply is that whenever you write a block of code and put
a comment in front of it, consider extracting that code into a (private) function.

Functions are a great way to give a block of code a descriptive name. This
often obviates the need for one-line comments, reduces the number of live
variables in function scope, reduces the number of conditionals in a function
(many conditionals deal with implementation details instead of higher-level
decisions), makes data flow and ordering more pronounced, etc.

Anyway, as far as "code of humans" is concerned, tick.


If you actually need to use that macro/function multiple times, it will also
score on the DRY ("don't repeat yourself") principle. Tick.


Now that you have your macro/function, we are getting to the question at hand:
where to put it?

The general guideline is to "keep related things close/together".

This is sometimes misunderstood as keeping things of the same type together,
which is why many desktop environments still drive me mad by offering users
directories for "photos", "videos", "music", or "documents" instead of helping
them to organize things so as to keep "photos and videos from that trip to
Alps", or "photos and documents from that project" together. Frankly, grouping
things by type is the sort of view that software should be able to provide
automatically on demand, and let people actually add/keep the semantic bits.

Even when it comes to code organizations, you should prefer the "semantical"
point of view (in this case, relation to printing of numbers), not the
"syntactical" (is something a macro or a function) view, to tell whether two
things are related.

Exceptions are typically made for (subsets of) globally visible constants,
because you often do want to have them in a single file (or multiple
subsystem-specific files) to simplify maintenance.

Anyway, back to your specific case: the macro adds extra meaning to your
implementation code, but it is only used/useful locally, so that's where it
should be (in the C source, possibly even right before the function using it,
if it is the only one).


That said, there are also dangers to making things too abstract and generic.
Abstraction is a powerful tool, but keep in mind that it does have its costs,
and I don't mean runtime efficiency -- every abstraction requires people to
dedicate some mental capacity to it.

Coming up with a generic solution to a situation that does not really call for
it tends to complicate things.

So to keep things in balance, you should stick to the KISS principle, which
really just conveys (somewhat bluntly) an old wisdom. Observations that
"everything should be as simple as possible, but not simpler", or that
"perfection is achieved, not when there is nothing more to add, but when there
is nothing left to take away", or "when in doubt, leave it out" have been made
by some of the most brilliant people in their fields.


I hope you can still find your answer in the above -- I'm making a mental note
to myself: KISS :-)



Lubomir



On 28/10/2020 15:31, Petr Tuma wrote:
> Hi,
> 
> Lubomir Bulej will have the most authoritative opinion on what is good style
> :) I would just offer my view:
> 
>> I have a question about a code composition. I want to implement a macro
>> computing maximal
>> amount of hexadecimal digits one can use to house an integer. (I would've
>> been fine with just
>> using a constant but my team prefers a more generic approach to this matter.)
> 
> Not sure if you mean "use constant directly in code" or "define a macro that
> is a constant and use that in code". If the latter, then go for it :)
> 
> What is the reason your team prefers a more generic approach ? Will you use
> the macro with many different integer types ? (There are not that many there
> to begin with ...) You should not spend much time on creating generic
> constructs that will not be used.
> 
>>   * printk.c - I could put it directly in the .c file since is supposed to
>> be used only in it, but>     it seems awkward to me put macro in .c file
> 
> There are many good reasons for putting macros in .c file. If it is a local
> macro that only helps make your code more readable or efficient, and there is
> no reason it would be used by other source files, then this sounds like a
> perfectly fine solution to me.
> 
> Petr
> 
> P.S.: Now I have to hope Vojtech or Lubomir will not want to grade me :-)


More information about the NSWI004 mailing list