You don't have to store a property in viewstate; it's just a best practice because viewstate preserves the data across post-backs and works at design-time, too. With a private variable, the data will be erased after each post-back, which is generally not the desired effect.
You can use control state, yes, and control state is viewstate essentially, but it can't be disabled. Also, to discourage developers from stuffing it up with too much data like a state bag, data is added with Pair objects. So, my advice is to use control state for critical data that absolutely must be preserved in view state at all times.
The (A ?? B) is a shorthand notation for A == null ? B : A. That is, - whatever is before the ?? is what to check for a null reference, and what is after, - what to return if it is a null reference. So, in this case, the value retreived from view state is checked for a null reference, and if it is null, String.Empty is returned. I find performing the check unnecessary, but actually it is a practice done by Visual Studio 2005, and when one creates a new web custom control in VS2005 in a library, the generated code automatically includes a Text property which upon retrieval checks the returned value from view state for null and if it is, returns String.Empty.
EnsureChildControls() is usually called in an overriden DataBind() method if the control used templates to render portions of its interface, and in CompositeControl, it's called upon accessing the Controls collection, to make sure that the controls have been created first.
If you're interested in providing design time support with template editing (overriding TemplateGroups property in a control designer and calling SetViewFlags(ViewFlags.TemplateEditing, true) in the Initialize(...) method) I'll tell you one more thing I think you should know about EnsureChildControls(), and that's that when you finish editing templates through the smart tag, the control isn't automatically updated because the call to DataBind() doesn't re-create the controls but the call to EnsureChildControls() considers them as already created and does nothing.
To solve this problem, instead of calling EnsureChildControls(), call CreateChildControls() and set ChildControlsCreated to true. I saw this technique in the MSDN library, although I wasn't sure what exactly it does.
Cheers.
...I hope you don't mind the rather lengthy response.