[Gtk-sharp-list] [PROPOSAL] Eliminating Application.Init ()

Jonathan Pryor jonpryor@vt.edu
Sat, 13 Sep 2003 22:45:01 -0400


So, you want to rely on the Library to handle initialization order?

Sorry for being bold and/or mean, but are you insane?

The problem is that static constructors guarantee NO ORDER.  The only
thing you can assume is that the static constructor will be invoked
before any static members are accessed, or any types are created.

You can't say "this .cctor should execute before this other .cctor
(which could be located in a completely different assembly!)."

Why would this be problematic?  Assume code like:

	class Library1 {
		static Library1 () {
			/* do something; MUST occur *before* 
			   Library2 initialized */
		}
		public Library1 () {}
		// ...
	}

	class Library2 {
		static Library2 () {
			/* do something; MUST occur *after*
			   Library1 is initialized */
		}
		public Library2 () {}
		// ...
	}

	public class User {
		public static void Main () {
			Library2 l2 = new Library2 (); // Oops!
			Library1 l1 = new Library1 ();
		}
	}

The problem is that there's no way to ensure that the programmer will do
the right thing, and create an instance of Library1 before creating an
instance of Library2.  If the order is wrong (as is done above), you may
get library errors.

This has the potential to be VERY hard to track down, and VERY
non-obvious, and VERY brittle in the face of future updates to the app
(it may make sense to re-order the creation of classes).

Automatic initialization is FOLLY, except for VERY simple
circumstances.  Period.

Want a better example?  COM/.NET under Windows.  .NET prefers
multithreaded COM apartments, but .NET won't actually set the COM
apartment until it needs to.  Creating a COM object in .NET will
implicitly set the apartment type for the creating thread, along with
some other implicit behaviors.

Note that this is *implicit*, just like your desired automatic
initialization.

The result?  Hard to track down bugs, when .NET assumed that the thread
would be in a multithreaded apartment, but a COM control was created
behind .NET's back, setting the apartment to single threaded.  This
leads to deadlocks and other non-nice things.

The solution?  The [STAThread] and [MTAThread] attributes, so that you
can *explicitly* specify the initial COM apartment.

Application.Init() may be a "wart", but it's The Right Thing To Do.  The
only real solution is good documentation and FAQs.  The programmer has
to keep track of these issues, as no one else knows what the programmer
is trying to accomplish.

 - Jon

On Sat, 2003-09-13 at 21:15, Michael Poole wrote:
> Mike Kestner writes:
> 
> > On Sat, 2003-09-13 at 13:22, Gonzalo Paniagua Javier wrote:
> >> El jue, 11-09-2003 a las 05:59, fd escribió:
> >> > More from the API beauty police...
> >
> > I don't understand what's so ugly about it.  main() {Init; ... Run;}.
> >
> > Any meaningful application is going to have 1000's of lines of code. 
> > Why are we worried about removing a single line that only occurs once in
> > any app?
> 
> It is one line of code, yet it is yet another place for developers to
> miss something essential.  It is a wart (small, yes, but highly
> visible) that could make Gtk# look bad.  But mostly, it is just
> fragile API design.
> 
> What happens when I create an application that needs Gtk# and several
> other libraries, each with their own Init() function?  What if there
> are dependencies between these libraries -- am I, as a developer,
> responsible for tracking that and making sure every pair of functions
> from different libraries is called in the correct order?
> 
> Michael
> _______________________________________________
> Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/gtk-sharp-list