Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

My main platform (WinAPI) still heavily uses bits for control styles etc. (example).

When introducing custom controls, I'm permanently wondering whether to follow that style or rather use individual bool's. Let's pit them against each other:

enum EMyCtrlStyles
{
   mcsUseFileIcon = 1,
   mcsTruncateFileName = 2,
   mcsUseShellContextMenu = 4,
};

void SetStyle(DWORD mcsStyle);
void ModifyStyle(DWORD mcsRemove, DWORD mcsAdd);
DWORD GetStyle() const;

...
ctrl.SetStyle(mcsUseFileIcon | mcsUseShellContextMenu);

vs.

CMyCtrl & SetUseFileIcon(bool enable = true);
bool GetUseFileIcon() const;

CMyCtrl & SetTruncteFileName(bool enable = true);
bool GetTruncteFileName() const;

CMyCtrl & SetUseShellContextMenu(bool enable = true);
bool GetUseShellContextMenu() const;

ctrl.SetUseFileIcon().SetUseShellContextMenu();

As I see it,

Pro Style Bits

  • Consistent with platform
  • less library code (without gaining complexity), less places to modify for adding a new style
  • less caller code (without losing notable readability)
  • easier to use in some scenarios (e.g. remembering / transferring settings)
  • Binary API remains stable if new style bits are introduced

Now, the first and the last are minor in most cases.

Pro Individual booleans

  • Intellisense and refactoring tools reduce the "less typing" effort
  • Single Purpose Entities
  • more literate code (as in "flows more like a sentence")
  • No change of paradim for non-bool properties

These sound more modern, but also "soft" advantages. I must admit the "platform consistency" is much more enticing than I could justify, the less code without losing much quality is a nice bonus.

1. What do you prefer? Subjectively, for writing the library, or for writing client code?
2. Any (semi-) objective statements, studies, etc.?

share|improve this question
    
pro style bits each boolean is generally allocated as (at least) a byte, this means less copying –  ratchet freak Sep 25 '12 at 7:44
add comment

3 Answers

Actually, I don't believe that "consistency with platform" is a "minor" point in most cases. Quite to the contrary, you should design a library like others are likely to expect to use it. If the primary target audience for, or platform that is targetted by, your library uses bitfields, then you are probably better off using bitfields.

That said, bitfields do have their fair share of disadvantages. They debuted when memory constraints were a very real concern; if you're trying to squeeze something useful into a few dozen kilobytes of RAM or even less, then every byte counts. Consider that the Windows API goes back to the early 1980s, with Windows 1.0 released in 1985 and requiring a whopping 256 KB of RAM and either two floppy disk drives or a single hard drive. This is much less of a concern today now that pretty much all and sundry have several gigabytes of RAM available for server or desktop applications, as well as essentially unlimited, comparatively extremely fast swap space (I don't think Windows 1.0 ever did swapping at all, although I'm pretty sure it did memory page purging), plus JIT compilers, optimizers etc.

Bitfields are opaque; it's much easier to say if (frob.isFrobnicated() && frob.isGlobbified()) than if (frob.getState() & (FROB_FROBNICATED | FROB_GLOBBIFIED) == (FROB_FROBNICATED | FROB_GLOBBIFIED)), let alone when you are looking at the object in a debugger and see that frob.state == 0x27a and trying to figure out what that value means.

One big upside of using separate state variables and accessor/mutator functions is that it is much easier to enforce invariants between related states. For example, if state A has no special requirements, but state B requires that one of but not both of states C and D are set, this is trivial to enforce at compile time if you are using separate state mutator functions, but not quite so obvious when using bitfields.

I work primarily with .NET and Java, both of which frown at bitfields for exposed state in library routines. (There are exceptions, but they are rare.) C is almost certainly different even these days, and I imagine C++ kind of bridges the gap.

Bit fields have one huge advantage: they are atomic. If you access frob.state, you can examine the value safe in the knowledge that it cannot change between comparisons within the same statement (like for example in the if examples above). In a multithreaded application, if you are unlucky, the state of the frob might change between the two calls to isFrobnicated() and isGlobbified(). However, I would think that if this is a major source of bugs, then you have other issues that you need to deal with (like thread-common global state being modified while being used).

Bottom line: you certainly can use bit fields internally if you feel comfortable with them, but for exposed state, I would go with separate values unless there are specific reasons (such as platform usage expectations) for doing otherwise, and you are willing to live with the downsides of that choice. And even then, you may want to consider doing it as an alternative rather than as the only available approach.

share|improve this answer
add comment

The booleans have almost all the advantages. All the bit advantages you mentioned except "Consistent with platform" can be completely overcome by carefully packaging booleans into classes. Booleans make for dramatically cleaner code and better design.

However, bits do have one very big advantage. They are faster and use less memory. If you have 10 million objects, each with a set of 60 boolean values, your program will run faster and use a lot less memory if you use the bits. (This is why the platform still uses bits.) You have to decide at the start of a project how much performance matters, because it will be very hard to switch your booleans to bits later.

If I have a couple of booleans in a class that may end up with a couple hundred instances, I'll stick with booleans. If it's the 10 million and 60, and performance matters, I go with the bits. If it's in the middle, I end up thinking for a while.

share|improve this answer
    
The argument that bitfields use less memory is only relevant if you consider internal and external state to be one and the same and you are operating under memory constraints (which, as you correctly point out, you might even in a large-memory environment). There is nothing in general saying that you can't represent a state value internally as a bitfield while exposing it as a set of booleans and/or enums by way of a set of methods and functions, or properties (a.k.a. syntactic sugar for methods and functions). –  Michael Kjörling Sep 25 '12 at 14:47
    
@MichaelKjörling: True. While bitfields can get a bit ugly, it is usually pretty easy to hide them. If 60 bits can be stuffed neatly into one elegant class, there's almost no reason to prefer booleans (for actual storage, not methods/properties!), even when the performance benefits are minor. –  RalphChapin Sep 25 '12 at 15:26
add comment

I prefer using enum bitflags in both library and client code for a collection of boolean options that can be toggled independently. It's an idiom I'm familiar with, and allows me to save the configuration in a single int and pass it around without having to define a new struct or class to contain all the flags. It also cuts down on typing without really sacrificing clarity.

Objectively, a struct containing bools would be more type-safe in C++, as discussed in this SO question. Irrelevant if you're using plain C.

share|improve this answer
    
Thanks - The C++ 0x solution looks darn nice, though i have to delve deeper... –  peterchen Sep 25 '12 at 8:03
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.