views:

94

answers:

3

It's hard to explain my problem so give me a break if it's not very clear.

I have some ten properties that can be edited in the view. Most of them are booleans. These properties configure a test environment (like one property can be configured to show the solution).

Now, the problem is that some properties can't be set to true if others are set to false. Nothing would go wrong, but it's just useless. It's like one property would be configured not to show the correct button and another to show the solution. In our system, if you can't click on the correct button, then solution will never be shown.

Does this kind of problem have a name? Do such properties have a name (just like there are immutable properties)? Are there best-practices to implement such a story? We can hard code it in the view, but I would rather have a generic system.

+1  A: 

You could use an int or long to store the related properties and use a bit mask when setting a property to correctly clear invalid settings. This int or long could be in the form of a flagged enumeration.

[Flags]private enum BitValues
{
  Bit1 = 1 << 0, //Inclusive
  Bit2 = 1 << 1, //Exclusive to bit 3 and 4
  Bit3 = 1 << 2, //Exclusive to bit 2 and 4
  Bit4 = 1 << 3, //Exclusive to bit 2 and 3
  ExclusiveBits = Bit2 | Bit3 | Bit4 //All exclusive bits
}

private BitValues enValues;

public bool Bit1
{
  get { return (enValues & BitValues.Bit1) == BitValues.Bit1; }
  set
  {
    //Clear the bit
    enValues = (enValues ^ BitValues.Bit1) & enValues;

    //Set the bit
    enValues = enValues | BitValues.Bit1;
  }
}

public bool Bit2
{
  get { return (enValues & BitValues.Bit2) == BitValues.Bit2; }
  set
  {
    //Clear exclusive bits
    enValues = (enValues ^ BitValues.ExclusiveBits) & enValues;

    //Set bit
    enValues = enValues | BitValues.Bit2;
  }
}
Stevo3000
+1  A: 

You propably mismodeled your solution.

Try to think in a different way - perhaps U can eliminate some parameters that can be inferred from the others or u can use enumarations to combine few parameters into one.

Investigate your parameters' value space to find it out.

lbownik
Indeed, I was also thinking in that direction. But it's not that simple. If A is true, then it could be that B can be true and false. If A is false, then B can only be false. If A is set to true en B to true, do you alter B automatically when A changes to False? Or do you show an error saying that A cannot be False when B is True...
Lieven Cardoen
"If A is true, then it could be that B can be true and false. If A is false, then B can only be false." In which case, when A is true display B under A indented, and when A is false either hide B or display it greyed out.
TRiG
+2  A: 

The word you're looking for is orthogonality. The settings are not orthogonal, as they can't vary independently.

As to how to handle showing these properties, the completely generic way to do it (and your problem may not warrant the coding cost of this genericicity) would be to give each control an expression that references the other controls, where if the complete expression evaluates to true (or false), the control is disabled in the view.

Easier to code would be a control that exposed an isDisabled() method, which you could override as necessary. Here's a short Java example, which leverages Java anonymous classes to do the hard work. It assumes there's already a Control class, with a booleanValue() getter that converts it to a boolean, and that since AutoDisabledControl is-a Control, it can be used as a drop-in replacement for a Control:

  public class AutoDisabledControl extends Control {
    public isDisabled() { return false ; }
  }

  ..... usage ....
  // control1 is never disabled
  final Control1 = new AutoDisabledControl() ;
  // Control2 is disabled if control1 is false
  final Control2 = new  AutoDisabledControl() {
    public isDisabled() { return control1.booleanValue() == false; }
  };
  // conntrol 3 is enabled only if control1 and control2 are true
  final Control1 = new  AutoDisabledControl() {
    public isDisabled() { return ! (
                        control1.booleanValue()
                        && control2.booleanValue()) ; 
  };

Naturally, in the View's display, it checks each control's isDisabled() , and disables the ones that return true; when a Control's value is changed, the view redisplays. I'm assuming some sort of MVC Pattern.

tpdi
Very interesting. Off course, it gets hard for the user to know which control he has to change for another control to get enabled again...
Lieven Cardoen
Well, you'd either add that as static text in the view... or you could change the AutoDisabledControl to expose a textual reason it's disabled.
tpdi