60

I have three views in my program (iOS app). Only one of them is ever active at the same time so I set the visibility off for two of them and switch visibility as the user presses buttons. The views are initialized as visible so I set the visibility off in code before the main view shows.

I can do

[view1 setAlpha:0.0f];
[view2 setAlpha:0.0f];

for two of the views, but now the third one (the one that should be visible at the start of the app) is not addressed. I put a

[view3 setAlpha:1.0f];

after the first two, because I think it keeps it clear that there are in fact three views, not two as one might think when seeing the code. How do other programmers do this? Is it purely preference or are there some conventions?

If the call is very heavy, it's obviously better to not call it when that isn't necessary, but I was wondering about small things like my example.

0

4 Answers 4

134

You have an invariant:

Only a single view (out of 3) is ever active (and visible).

Then, I suggest that you provide a function to switch the activity and visibility of ALL views at once:

[setActiveView viewID:2]

This function will:

  • check if the view is already active, avoiding unnecessary work
  • set the view as active, and visible
  • set the other 2 views as inactive and invisible

It has multiple advantages about a raw call to setVisibility:

  • friendly: calling it unnecessarily does not create a performance issue
  • defensive: its single parameter is much harder to botch, whereas for setVisibility it's harder to remember that the range of values is 0.0f - 1.0f and that only one must be set to 1.0f
  • resilient: the next guy cannot accidentally forget one of the views
  • adaptable: adding/removing a view does not require scrutinizing all the application code to find where the switches are, a single function (this one) need be updated

Ideally, to help enforce the invariant, no other function should be able to mess up with this setting...

7
  • Great suggestion. I'm gonna do this with my current example. But what about when such a design is not possible/wanted? Or do you decide on the spot what the best way is to handle it?
    – Kevin
    Aug 17, 2015 at 10:54
  • 4
    @Kevin: It depends really. Sometimes you can solve the issue by iterating over a collection, sometimes not, but the key principle is to avoid duplication and to make it easy to preserve invariants. The more "manual" actions need be remembered for things to work properly, the less chances you have that things will work properly. I hate to be vague here, but there are so many different situations that I am afraid a "generic" rule would just lead you astray. Aug 17, 2015 at 11:02
  • 24
    "make it easy to preserve invariants" is a generic rule worth remembering.
    – Gusdor
    Aug 17, 2015 at 14:06
  • 1
    @Tonny: I don't know if encouraging the use of a global variable is "doing it right", but indeed if you know exactly which was active before, you need only update two views. Another solution is for each view to remember its visibility and for setVisibility not to do anything if the visibility is already the one requested, which moves the responsibility down. Aug 17, 2015 at 15:19
  • 1
    @MatthieuM. I wrote in haste, but is actually what I meant too. If you know the previous state you only need to update 2 view at most. How to remember that state is another matter ;-). As for moving the responsibility down: If the view-class doesn't provide for that you would need to wrap the class in another object just to add that property. That is a clean solution, but maybe a bit overkill.
    – Tonny
    Aug 20, 2015 at 13:59
12

Alternate idea: if your goal is to prevent bugs occurring because people forget there's three views and do something with only two of them that they really should do with all of them, then make a function that makes it impossible to forget:

setViewVisibilities(0.0f, 0.0f, 1.0f)

Now you have something far more powerful - compile time guarantees you haven't forgotten. If you forget a parameter, the compiler will yell at you. This is far more useful than comments or unnecessary code, as it creates a strict named protocol that enforces the property you care about.

For the case where view3 doesn't need it's visibility changed, you could add some behavior where passing a special value like -1.0 or nil or something along those lines means "don't change the view visibility at all". This gets around the problem of setting visibilities unnecessarily.

2
  • 9
    If OP gets up to 10+ views, a parameter-per-view is going to become impossible to maintain. Your point about compile-time errors is correct, but this is a very unmaintainable solution, unfortunately. Aug 17, 2015 at 15:02
  • 3
    @ChrisCirefice: If the number of views grows, you can create some kind of "ViewState" object/class, which enforces this invariant. Then use that for switching etc. With so many views, some kind of manager object probably makes sense anyway.
    – sleske
    Aug 17, 2015 at 23:58
8

I would believe that adding a comment explaining that the call is unneeded (and why) is best.

(perhaps, the fact that a call is unneeded, or that you need a comment about that, might be a code smell)

8
  • 1
    @Niall If possible, an assertion would be even better than a comment. Aug 17, 2015 at 18:47
  • 9
    Comments are not the solution to unmaintainable and unreadable code
    – dj18
    Aug 17, 2015 at 19:06
  • 2
    @Kevin or you could write code that's perfectly readable without comments.
    – Jan
    Aug 18, 2015 at 12:13
  • 1
    @Jan Comments are more than just explaining what code does.......
    – Kevin
    Aug 18, 2015 at 13:01
  • 2
    @Kevin I would say comments should never exist to explain what code does, but rather to explain why it is doing it. And in such situations often a refactor will get the intent across without needing the comment (which sounds like Jan's point).
    – RJFalconer
    Aug 18, 2015 at 14:14
4

In this particular case, @Mattieu M. has the right solution.

In the more general case, where there is no similar transform, you have to ask yourself: Is there any chance a future programmer might mess this up?

The answer is usually yes. Which means, yes, you should add the call. Maybe some future version of the framework starts with all views OFF instead of ON.

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