1

I just read the article "Idiomatic Programming" and it tried to stress an important concept: that the language should not dictate how you solve the problem, rather you should dictate how the language ought to solve a problem.

As an example, the author chose the C/C++ Preprocessor to do two things:

  1. Enforce Consistency

  2. Add Syntax and Grammar to the existing language.

Now, I know this article dates back to at least 2003 and is using the C language, but I have seen other people use at least point 1. before (Ogre 3D for example).

The example given is:

#define property(name, type)   :                             \
                            type m##name;                \
                            public:                      \
                             type name()                 \
                                { return m##name; }      \
                             void name(type t__##name)   \
                                { m##name = t__##name; }  

used like this:

class MyClass
{
  protected property(age, unsigned short);
  private   property(gpa, float);

  private:  // Other stuff can go here
};

Aside from the fact that macros are evil and we should use modern C++ variants, to my knowledge there is no suitable alternate solution, and I believe this is the sort of thing Boost.Wave and Boost.Preprocessor was made to clarify and enhance.

I believe this has some merit, but I would like to know from people having used/seen this, what are your thoughts? Do the author's points and example still have merit, or is it something to be read, taken into quiet consideration and stashed away as a nice-to-know tidbit?

EDIT

Thank you for the answers!

I wish to quickly elaborate on the nature of the question. It is not a "Is this example good to use or not?" question, it is an example of the type of changes and extensions the author proposes to enrich or enhance the existing language. Therefore, the question is: is it admissable to abuse the preprocessor to add language extensions and enforce consistency based on the example of this and other macro snippets?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
IAE
  • 2,213
  • 13
  • 37
  • 71
  • 2
    If it's always defined to a plain get/set, why not just have a struct with a public field? YAGNI, KISS, etc. – Alex B Jan 31 '12 at 09:55
  • You should never define a name containing a double underscore - those are reserved. – Mike Seymour Jan 31 '12 at 10:02
  • 1
    Macros aren’t even necessarily evil. But yes, calling a macro `property` is *very* evil (namespace pollution). As an aside, I’d argue that the above implementation is wrong: the field should *always* be `private` and the explicit visibility qualifier should apply to the methods. – Konrad Rudolph Jan 31 '12 at 10:03
  • @KonradRudolph: You're thinking of C. In C++, it's any name containing a double underscore. – Mike Seymour Jan 31 '12 at 10:05
  • @Mike I haven’t got the standard here right now but I read that section rather carefully before and I was certain that it was only `__` and `_` followed by capital letter at the beginning of identifiers, and `_` at the beginning of identifiers in global or namespace scope. – Konrad Rudolph Jan 31 '12 at 10:07
  • @KonradRudolph: 17.6.4.3.2: Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. – Mike Seymour Jan 31 '12 at 10:14
  • @Mike Thanks for looking it up. – Konrad Rudolph Jan 31 '12 at 10:16
  • I did not expect this much traffic for such a question :D To clarify, I don't think the author intended to change the existing syntax, like Bo Persson tries to mock, but extend the feature-set. The example given is supposed to enforce consistency because a wide range of classes existed that all needed this common interface. It is not a use-once, throw-away type of macro. I should have written this in the question, I apologize. – IAE Jan 31 '12 at 10:41

3 Answers3

2

IMHO, in this case encapsulating a property with a macro does not add any value, other than obfuscating slightly the code. Also, you cannot write a custom getter/setter and leave the other as it is.

I did this kind of things for some common list patterns in the place I used to work two years ago (search in my history for tags like C, macro, preprocessor and be amazed! :-p

Functional programming in C with macro "Higher Order Function" generators

C function decorators (wrappers) at compile time ), and now I think it wasn't the greatest idea.

People (and tools!) get confused very easily when you do "smart tricks". For example, in your example the chances are that if somebody used it's IDE auto-completion features, it won't show your methods or attributes.

So, unless you really need to do something smart and powerful, you have the proper tools and it is idiomatic in your environment (think about Python's data model where you can actually have property descriptors, or Common Lisp's macros), try to make things as explicit as possible. It will save you many WTF faces.

Community
  • 1
  • 1
fortran
  • 74,053
  • 25
  • 135
  • 175
  • 1
    As much as I want to say wtf, that first question is amazing and awesome :D I'm pretty sure I wouldn't write it in any professional codebase, but I do get the immediate urge to play around with that idea. – IAE Jan 31 '12 at 10:38
  • he he, have fun then! ;-) but I think there are better languages to toy around with meta-programming and syntax extensions than C/C++... – fortran Jan 31 '12 at 10:55
1

So, if I interpret your question correctly - you want to know if it is a good practice to use setters/getters.

My personal experience is that these methods do not add any value, increase the code size, and should not be used. Instead, you should make that member variable public.

However take a note that there are different opinions on this matter.


If the implementation is consistent, then it is a good practice. But if you have some cases where you have to have different getters/setters, then do not do it.

Community
  • 1
  • 1
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 1
    “different opinions” – it would be more honest to say that yours is an absolute minority opinion that violates commonly stated best practice. That said, having accessors at all is nowadays often considered bad design. – Konrad Rudolph Jan 31 '12 at 10:09
  • @KonradRudolph I believe you are right when you say that, but do you have some links to back up your claim? – BЈовић Jan 31 '12 at 10:13
  • Off the top of my head, no. But there are references in print, e.g. both *Effective Java* and *Effective C++* (either first or second volume). – Konrad Rudolph Jan 31 '12 at 10:14
  • @VJovic: Thank you for your answer. My question was more specific to the use of macros to extend the language or add, as the author put it, consistency. In his article, he mentioned that he had to write such classes ubiquitously, so having a macro "fill in" most of the repetitive details was the enforced consistency. – IAE Jan 31 '12 at 10:35
  • @SoulBeaver I extended it a bit. Hope it now answered your question – BЈовић Jan 31 '12 at 10:38
1

this cleverness often breaks the tools you use directly. there are clearer solutions for this problem using the language and basic types. in fact, this falls apart pretty quickly if the value cannot be copied, or you don't want to copy it. therefore, the real world variations needed are often as complex as implementations which use builtin language features, basic types, and no preprocessor magic. i do take this approach in order to work around compiler differences (very very rare) and occasionally define generated classes (which are then encapsulated and given proper interfaces), and that's about all.

justin
  • 104,054
  • 14
  • 179
  • 226