You might be dangerously close to three-star programming if:
- You have ever wished you could set a breakpoint within an expression.
- Any expression with more than one operation in it, even something as simple as "(a+b)*c", could benefit from this. Cramming more than two side effects in an expression (or one, if you want to be pedantic, though stuff like a = *b++ is one of the common CeeIdioms) is a more likely sign of ThreeStarProgramming.
- Perhaps you have a ThickBreadSmell.
- You have used a legal (probably immoral) expression that confused your debugger. This may mean you have a crappy debugger. gdb, in particular, is notoriously easy to confuse...
- You have used a legal (probably immoral) expression that confused your compiler -- not just one that causes a code generation error, but one that it refuses to compile. Bonus points if it fits in an 80-column line, and doesn't use any preprocessor macros.
- Of course, you may just have a lousy compiler. Should only apply to compilers known to be highly robust and stable. Bonus points if you make the compiler dump core.
- You spell string "char*". Extra points if done in C++.
- You have used the ConditionalOperator (?:) for the side effects, ignoring the return value, in order to avoid an 'if' statement.
- You have bitshifted the result of a boolean expression and used it as an array index to avoid using ?: or an if statement. I have done something similar in GWBASIC, for example to print positive numbers blue and negative numbers red and zero gray I would use: COLOR (1-(N<0)*3)-(N=0)*6
- You otherwise write code that makes assumptions about the value of true in CeeLanguage (other than the fact that it isn't zero), the signed-ness of char, the value of (int)(NULL) - it isn't always 0, or some other ImplementationDefined attribute of C.
- Right. It should be (N<0?1:0)
- You have used #ifdef sections within expressions. Extra points for "(FALSE || #ifdef ... #endif)" or "(TRUE && #ifdef ... #endif)". [[ Note: This will not compile if the conditional evaluates to false. The || or && must be within the #ifdef. And yes, I do this all the time. ArlieDavis. ]]
- Sure you can use #if and #ifdef within expressions (I have done so, too, as it is occasionally useful); but if you are doing that only for the purpose to make the error, can't you use the #error command instead?
- You've used the boolean operators to sequence commands - without an 'if'. e.g. (result = do_something()) && (result = do_something_else()); This may be unusual use in C/C++; but perfectly legal and standardized. It is a common idiom in other languages such as Perl and the various Unix shells -- its appearance in C code might well indicate a scripting background. "do() || die()" is not at all unusual or dangerous Its a common idiom back as far as K&R era C, and I suspect Perl inherited it from C.
- Or like that (in addition, this example is part of a literate program): if(*rule=='#' && (rule++,!is_weaving)) return;
- You have written a header (say, symbols.h) which exhibits radically different behaviors when #included, depending on #ifdef SOMEFLAG #else ... and which uses nested macros to re-interpret seemingly straightforward #define statements -- extra points if the macros are mixed case, hide side effects, #undef MYSYMBOL ... #include other dynamic header ... #define MYSYMBOL again, build arrays of structures including strings built from token-pasted constants whose indexes are DEFINED_SYMBOL values that seem to be some other sensible value. I can post an example. Understanding requires pentagram and blue mud. -- GarryHamilton
- Extra points if the purpose of this machinery is other than cross-platform support and/or an implementation of system headers. (Many system header files are precisely of this sort; due to the immense number of special cases that they have to deal with.)
- As well as the stuff above, furthermore you can make some of the macros to have mismatched parentheses (I have actually used this, together with other things such as token-pasting __LINE__ and so on). Did you have that too? I really would like to see your example.
- You deliberately write header files which aren't idempotent (Just plain not having include guards on header files isn't ThreeStarProgramming; it's just bad coding).
- Extra points if you do it in C++. (I've often done it in C as a crude approximation of templates).
- You use __attribute__ command to tell the optimizer things which simply aren't true, and hope to get away with this (although this is likely non-portable)
- You created structures which are never used by the program. (I have done it to generate compiler errors when sizeof(int) or sizeof(short) or whatever is not correct: "struct { void*x[sizeof(short)==2?1:-5]; }" )
Some higher-level, language-neutral signs you may be a ThreeStarProgrammer:
- You write code which (intentionally) depends on UndefinedBehavior or UnspecifiedBehavior.
- What if it does things which is undefined whether it is one way or another, with differing results in each case, although all the result that it might be are valid for use with the program?
- You modify the underlying language implementation in any fashion, except for in manners and under conditions approved/suggested by the language documentation (or as an emergency kludge to fix a nasty bug that resists more conventional remedies.)Many Smalltalk fans, for example, like to tinker with the standard classes -- including ridiculous things like redefining "true ifTrue:" and such to do other than the expected. Some of 'em call this a powerful feature of the language. I call it ThreeStarProgramming.
- Engage in excessive MetaProgramming -- in particular, writing your own domain-independent language on top of an existing one without a very good reason for doing so.
- This one is just wrong, in general. In a sufficiently introspective and expressive language, the design of domain specific languages (DSL's) is a very powerful and robust technique. Like other approaches, this can be done badly - but that doesn't speak to the fundamental value of the approach. Perhaps a more realistic claim would be that doing this in the wrong language (i.e. working 'against the grain') is a form of 3-star programming.
- Note the qualifer: without a very good reason for doing so. MetaProgramming is a powerful technique. However, I've run into too many second-rate programmers who do it to stroke the old ego - it makes 'em feel like elite coders - rather than for any technically sound reason. Good and useful MetaProgramming is hard; it requires both a thorough understanding of the problem domain to be modelled, and a reasonable set of language design skills. The good thing about Lisp is it makes metaprogramming much easier for the experts who should be doing it. The good thing about C and Java (C++ to a lesser extent) is it makes metaprogramming much harder for the nitwits who shouldn't. :) Go read StumblingBlocksForDomainSpecificLanguages.
- Both commentators should note that it says domain-independent not domain specific.
- Enjoy writing middleware, despite a business card that says "applications programmer". (At my employer, ReinventingTheDatabaseInApplication has long been a favored practice of our local ThreeStarProgrammers).
- Enjoy using any obscure features of a language, especially when more well-known features will suffice. (PointersToMembers? in C++ comes to mind... use of *. is a good indication of ThreeStarProgramming even though it only involves a single star...)
- And the maintainer who comes along later wants to make you see three stars.
- Pride yourself on creating the world's fastest OkCancelWidget. (Responds to that mouse-click in record time!)
- If you store your set of pointers in a container class, each of which set is managed by that same class.
- If looking at the raw bytecode in the debugger isn't low level enough.
- At least, we have Verilog and those things now.
- You've read any of the above and thought, "Hey, there are good reasons for doing that!"
To whomever contributed:
- Yes, I have done this. I would like to see your example, though, but I think I might understand without pentagram and blue mud. (And if I don't understand, I'm not sure that pentagram or blue mud might help me to understand it.)
This page is not the place to inject personal answers, except perhaps to clarify the point. Consider using a
HomePage.
- But what is the example with blue mud?