December 21, 2008
John Reimer wrote:

> Hello Lars,
> 
>> bearophile wrote:
>> 
>>> Walter Bright:
>>> 
>>>> Excess isn't the problem, I want to see if import cycles is.
>>>> 
>>> Generally all the modules in my dlibs import each other. This is nearly unavoidable, if a module contains string functions, and another one contains math stuff, the string module will want to use some math stuff and the math module may need string representations and processing. In the D specs I haven't seen an advice to not use cyclic imports, so I don't want such compiler flag, I prefer a compiler able to manage such cyclic imports efficiently.
>>> 
>> Cyclic imports is very often a sign of bad design, it typically mean (if it is unavoidable), that the modules shouldn't be separated in the first place. And in D it _is_ a bad idea because static initialization cannot depend on each other, that is cyclic imports of modules with static ctors.
>> 
> 
> 
> And yet it appears practically unavoidable in D in many situations,
> especially
> in porting software that with C, Java, or C++ heritage.

Being mostly a Java developer, I am well aware of the usage of cyclic dependencies in Java. Although it usually works fine technically, unless the dependencies are in the constructor itself, usage patterns are often made more difficult because of unnecessary cyclic dependencies and/or tight coupling. When porting something from Java, I don't really propose that you fix the errors of the original code, just saying that also the original code in that respect probably has made questionable design decisions.

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource, #d.tango & #D: larsivi
Dancing the Tango
December 21, 2008
John Reimer:
> Since other languages don't necessarily have the same module/package concept (except perhaps Java is the closest),

Despite few (bad) holes that need to be filled still, the closest is probably the Python module system.

Bye,
bearophile
December 21, 2008
Hello Lars,

> John Reimer wrote:
> 
>> Hello Lars,
>> 
>>> bearophile wrote:
>>> 
>>>> Walter Bright:
>>>> 
>>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>> 
>>>> Generally all the modules in my dlibs import each other. This is
>>>> nearly unavoidable, if a module contains string functions, and
>>>> another one contains math stuff, the string module will want to use
>>>> some math stuff and the math module may need string representations
>>>> and processing. In the D specs I haven't seen an advice to not use
>>>> cyclic imports, so I don't want such compiler flag, I prefer a
>>>> compiler able to manage such cyclic imports efficiently.
>>>> 
>>> Cyclic imports is very often a sign of bad design, it typically mean
>>> (if it is unavoidable), that the modules shouldn't be separated in
>>> the first place. And in D it _is_ a bad idea because static
>>> initialization cannot depend on each other, that is cyclic imports
>>> of modules with static ctors.
>>> 
>> And yet it appears practically unavoidable in D in many situations,
>> especially
>> in porting software that with C, Java, or C++ heritage.
> Being mostly a Java developer, I am well aware of the usage of cyclic
> dependencies in Java. Although it usually works fine technically,
> unless the dependencies are in the constructor itself, usage patterns
> are often made more difficult because of unnecessary cyclic
> dependencies and/or tight coupling. When porting something from Java,
> I don't really propose that you fix the errors of the original code,
> just saying that also the original code in that respect probably has
> made questionable design decisions.
> 


Since I'm not a Java developer (or, to be honest, any kind of developer beyond a language enthusiast), I'd say I'm not in a good position to question the design decision of Java source that uses cyclic dependencies (such as SWT). All I can say is that I can agree that it looks like a bad idea because I can certainly see the painful problems it can produce.  

I think what I was trying to say, though, is that I'm genuinely curious how such design decisions could have been corrected in the original projects (eg SWT).  After working with the code, I do indeed see an incredible example of "spaghetti" dependencies... but then I'm at a loss figuring out how the developers could have avoided it, given a language's limitations and the project's requirements.  So I guess I'm a little cautious about wagging my finger at them. :)  My guess is that in such a large project with so many widgets, if interdependencies were somehow lessoned, the bloat factor might have increased and, by implication, code reuse decreased.  It seems to me that the project might have grown significantly larger.  That's just conjecture, however.  I'm very curious to know how people solve this and why a group of highly skilled developers felt it necessary to ignore this.  The answer just might lie in SWT's historical roots, I'm guessing, since it started out from a Smalltalk project at IBM ages ago.  Perhaps they experienced the similar porting "design" decisions that we face now.  They were quite possibly stuck following the object heirarchy/interdepencies already in place.

But I know your intent was to emphasize that it was just one of those questionable things, not necessarily to be categorically denied any relevance all together. I can certianly understand why it should be avoided; it has always been source of annoyance to me  whenever I worked on dwt.

I apologize for bringing the focus so heavily on SWT/DWT.

-JJR


December 21, 2008
Hello bearophile,

> John Reimer:
> 
>> Since other languages don't necessarily have the same module/package
>> concept (except perhaps Java is the closest),
>> 
> Despite few (bad) holes that need to be filled still, the closest is
> probably the Python module system.
> 
> Bye,
> bearophile


You're probably right.

-JJR


December 21, 2008
"John Reimer" <terminal.node@gmail.com> wrote in message news:28b70f8cfcfe8cb30c0a0e2ac70@news.digitalmars.com...
> Hello Sean,
>
>> bearophile wrote:
>>
>>> Walter Bright:
>>>
>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>
>>> Generally all the modules in my dlibs import each other. This is nearly unavoidable, if a module contains string functions, and another one contains math stuff, the string module will want to use some math stuff and the math module may need string representations and processing. In the D specs I haven't seen an advice to not use cyclic imports, so I don't want such compiler flag, I prefer a compiler able to manage such cyclic imports efficiently.
>>>
>> Cyclic imports are a bad idea in general because of the impact they have on verifiability (unit testing).  But as you say, sometimes they're unavoidable.
>>
>> Sean
>>
>
>
> I'd going to wager that they are /often/ unavoidable, especially in ported projects from other languages that have either no concept or a different concept of modules/packages.
>
> DWT is perhaps the single worse example of cyclic imports.  I'm not sure
> how the design could have been improved in Java's SWT.  All it takes is
> the need to reference one symbol in each module (because each object
> apparently needs to just "know" about the other) to create a cyclic import
> issue in D.
> Static initialization has also been a problem in DWT such that a few
> significant workarounds were necessary.
>
> I agree that the interdepencies should be avoided in all new projects designed specifically for D.  I'm just not sure what the solution would be for the great mass of ported software.
>
> -JJR
>

This might be a naive idea, and wouldn't solve the problems with cyclic dependancies in the general case: But regarding the static initializaton issue (which I've come up against myself), what if static initializers allowed some sort of clause like this:

module foo;
import bar;

// Exact syntax not really important right now
this() dependsOn(bar) {
    // Do some initing that depends on
    // bar's static initializer having been run.
}

That would force foo's static initialization to be run sometime after bar's. Obviously, any cycles in the graph of "dependsOn"s would be an error.


December 21, 2008
Nick Sabalausky wrote:
> "John Reimer"<terminal.node@gmail.com>  wrote in message
> news:28b70f8cfcfe8cb30c0a0e2ac70@news.digitalmars.com...
>> Hello Sean,
>>
>>> bearophile wrote:
>>>
>>>> Walter Bright:
>>>>
>>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>>
>>>> Generally all the modules in my dlibs import each other. This is
>>>> nearly unavoidable, if a module contains string functions, and
>>>> another one contains math stuff, the string module will want to use
>>>> some math stuff and the math module may need string representations
>>>> and processing. In the D specs I haven't seen an advice to not use
>>>> cyclic imports, so I don't want such compiler flag, I prefer a
>>>> compiler able to manage such cyclic imports efficiently.
>>>>
>>> Cyclic imports are a bad idea in general because of the impact they
>>> have on verifiability (unit testing).  But as you say, sometimes
>>> they're unavoidable.
>>>
>>> Sean
>>>
>>
>> I'd going to wager that they are /often/ unavoidable, especially in ported
>> projects from other languages that have either no concept or a different
>> concept of modules/packages.
>>
>> DWT is perhaps the single worse example of cyclic imports.  I'm not sure
>> how the design could have been improved in Java's SWT.  All it takes is
>> the need to reference one symbol in each module (because each object
>> apparently needs to just "know" about the other) to create a cyclic import
>> issue in D.
>> Static initialization has also been a problem in DWT such that a few
>> significant workarounds were necessary.
>>
>> I agree that the interdepencies should be avoided in all new projects
>> designed specifically for D.  I'm just not sure what the solution would be
>> for the great mass of ported software.
>>
>> -JJR
>>
>
> This might be a naive idea, and wouldn't solve the problems with cyclic
> dependancies in the general case: But regarding the static initializaton
> issue (which I've come up against myself), what if static initializers
> allowed some sort of clause like this:
>
> module foo;
> import bar;
>
> // Exact syntax not really important right now
> this() dependsOn(bar) {
>      // Do some initing that depends on
>      // bar's static initializer having been run.
> }
>
> That would force foo's static initialization to be run sometime after bar's.
> Obviously, any cycles in the graph of "dependsOn"s would be an error.
>
>

I'm curios - why isn't this a problem in other languages like Java (and I assume .net languages as well)?
What's different in D that makes this so dificult? the static initializers? How is this handled in other languages?
December 21, 2008
Yigal Chripun Wrote:
> Nick Sabalausky wrote:
> > This might be a naive idea, and wouldn't solve the problems with cyclic dependancies in the general case: But regarding the static initializaton issue (which I've come up against myself), what if static initializers allowed some sort of clause like this:
> >
> > module foo;
> > import bar;
> >
> > // Exact syntax not really important right now
> > this() dependsOn(bar) {
> >      // Do some initing that depends on
> >      // bar's static initializer having been run.
> > }
> >
> > That would force foo's static initialization to be run sometime after bar's. Obviously, any cycles in the graph of "dependsOn"s would be an error.
> >
> >
> 
> I'm curios - why isn't this a problem in other languages like Java (and
> I assume .net languages as well)?
> What's different in D that makes this so dificult? the static
> initializers? How is this handled in other languages?

In Java static initializers are run during class loading. So cyclic dependencies in imports is not a problem. It's an error to make two or more static initializers depend on each other though.
December 21, 2008
Hello Yigal,

> Nick Sabalausky wrote:
> 
>> "John Reimer"<terminal.node@gmail.com>  wrote in message
>> news:28b70f8cfcfe8cb30c0a0e2ac70@news.digitalmars.com...
>> 
>>> Hello Sean,
>>> 
>>>> bearophile wrote:
>>>> 
>>>>> Walter Bright:
>>>>> 
>>>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>>> 
>>>>> Generally all the modules in my dlibs import each other. This is
>>>>> nearly unavoidable, if a module contains string functions, and
>>>>> another one contains math stuff, the string module will want to
>>>>> use some math stuff and the math module may need string
>>>>> representations and processing. In the D specs I haven't seen an
>>>>> advice to not use cyclic imports, so I don't want such compiler
>>>>> flag, I prefer a compiler able to manage such cyclic imports
>>>>> efficiently.
>>>>> 
>>>> Cyclic imports are a bad idea in general because of the impact they
>>>> have on verifiability (unit testing).  But as you say, sometimes
>>>> they're unavoidable.
>>>> 
>>>> Sean
>>>> 
>>> I'd going to wager that they are /often/ unavoidable, especially in
>>> ported projects from other languages that have either no concept or
>>> a different concept of modules/packages.
>>> 
>>> DWT is perhaps the single worse example of cyclic imports.  I'm not
>>> sure
>>> how the design could have been improved in Java's SWT.  All it takes
>>> is
>>> the need to reference one symbol in each module (because each object
>>> apparently needs to just "know" about the other) to create a cyclic
>>> import
>>> issue in D.
>>> Static initialization has also been a problem in DWT such that a few
>>> significant workarounds were necessary.
>>> I agree that the interdepencies should be avoided in all new
>>> projects designed specifically for D.  I'm just not sure what the
>>> solution would be for the great mass of ported software.
>>> 
>>> -JJR
>>> 
>> This might be a naive idea, and wouldn't solve the problems with
>> cyclic dependancies in the general case: But regarding the static
>> initializaton issue (which I've come up against myself), what if
>> static initializers allowed some sort of clause like this:
>> 
>> module foo;
>> import bar;
>> // Exact syntax not really important right now
>> this() dependsOn(bar) {
>> // Do some initing that depends on
>> // bar's static initializer having been run.
>> }
>> That would force foo's static initialization to be run sometime after
>> bar's. Obviously, any cycles in the graph of "dependsOn"s would be an
>> error.
>> 
> I'm curios - why isn't this a problem in other languages like Java
> (and
> I assume .net languages as well)?
> What's different in D that makes this so dificult? the static
> initializers? How is this handled in other languages?


For package scope, ie classes in the same directory, Java does /not/ seem to need an import statement, so somehow that suggests cyclic imports do not occur as they do in D for name resolution (in the specific case of package imports).  But I don't know what happens under the hood: does the fact that Java sees the whole package for symbol resolution imply that it reads in all symbols initially for a package during compilation?  If so, this would almost be equivalent to D, at compile time, reading all package modules as if they were one file somewhat similarly to what Derek was suggesting in another post.

This is too much speculation from me, though. :)

-JJR


December 21, 2008
Hello Nick,

> "John Reimer" <terminal.node@gmail.com> wrote in message
> news:28b70f8cfcfe8cb30c0a0e2ac70@news.digitalmars.com...
> 
>> Hello Sean,
>> 
>>> bearophile wrote:
>>> 
>>>> Walter Bright:
>>>> 
>>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>> 
>>>> Generally all the modules in my dlibs import each other. This is
>>>> nearly unavoidable, if a module contains string functions, and
>>>> another one contains math stuff, the string module will want to use
>>>> some math stuff and the math module may need string representations
>>>> and processing. In the D specs I haven't seen an advice to not use
>>>> cyclic imports, so I don't want such compiler flag, I prefer a
>>>> compiler able to manage such cyclic imports efficiently.
>>>> 
>>> Cyclic imports are a bad idea in general because of the impact they
>>> have on verifiability (unit testing).  But as you say, sometimes
>>> they're unavoidable.
>>> 
>>> Sean
>>> 
>> I'd going to wager that they are /often/ unavoidable, especially in
>> ported projects from other languages that have either no concept or a
>> different concept of modules/packages.
>> 
>> DWT is perhaps the single worse example of cyclic imports.  I'm not
>> sure
>> how the design could have been improved in Java's SWT.  All it takes
>> is
>> the need to reference one symbol in each module (because each object
>> apparently needs to just "know" about the other) to create a cyclic
>> import
>> issue in D.
>> Static initialization has also been a problem in DWT such that a few
>> significant workarounds were necessary.
>> I agree that the interdepencies should be avoided in all new projects
>> designed specifically for D.  I'm just not sure what the solution
>> would be for the great mass of ported software.
>> 
>> -JJR
>> 
> This might be a naive idea, and wouldn't solve the problems with
> cyclic dependancies in the general case: But regarding the static
> initializaton issue (which I've come up against myself), what if
> static initializers allowed some sort of clause like this:
> 
> module foo;
> import bar;
> // Exact syntax not really important right now
> this() dependsOn(bar) {
> // Do some initing that depends on
> // bar's static initializer having been run.
> }
> That would force foo's static initialization to be run sometime after
> bar's. Obviously, any cycles in the graph of "dependsOn"s would be an
> error.
> 

Some sort of explicit ordering would likely be a solution.  It would be /really/ nice if their were a clean way of implementing this... but it's really hard to say how it should be done.  I'm not sure how it is done (if at all) in other languages that implement a similar feature.

All I know is that, static initializations become almost useless at worst and extremely problematic at best in large projects, especially object based ones.  There are workarounds, of course.  One ends up having to learn not to be too dependent on this D feature.

-JJR


December 21, 2008
Mon, 22 Dec 2008 00:07:42 +0200, Yigal Chripun wrote:

> Nick Sabalausky wrote:
>> "John Reimer"<terminal.node@gmail.com>  wrote in message news:28b70f8cfcfe8cb30c0a0e2ac70@news.digitalmars.com...
>>> Hello Sean,
>>>
>>>> bearophile wrote:
>>>>
>>>>> Walter Bright:
>>>>>
>>>>>> Excess isn't the problem, I want to see if import cycles is.
>>>>>>
>>>>> Generally all the modules in my dlibs import each other. This is nearly unavoidable, if a module contains string functions, and another one contains math stuff, the string module will want to use some math stuff and the math module may need string representations and processing. In the D specs I haven't seen an advice to not use cyclic imports, so I don't want such compiler flag, I prefer a compiler able to manage such cyclic imports efficiently.
>>>>>
>>>> Cyclic imports are a bad idea in general because of the impact they have on verifiability (unit testing).  But as you say, sometimes they're unavoidable.
>>>>
>>>> Sean
>>>>
>>>
>>> I'd going to wager that they are /often/ unavoidable, especially in ported projects from other languages that have either no concept or a different concept of modules/packages.
>>>
>>> DWT is perhaps the single worse example of cyclic imports.  I'm not sure
>>> how the design could have been improved in Java's SWT.  All it takes is
>>> the need to reference one symbol in each module (because each object
>>> apparently needs to just "know" about the other) to create a cyclic import
>>> issue in D.
>>> Static initialization has also been a problem in DWT such that a few
>>> significant workarounds were necessary.
>>>
>>> I agree that the interdepencies should be avoided in all new projects designed specifically for D.  I'm just not sure what the solution would be for the great mass of ported software.
>>>
>>> -JJR
>>>
>>
>> This might be a naive idea, and wouldn't solve the problems with cyclic dependancies in the general case: But regarding the static initializaton issue (which I've come up against myself), what if static initializers allowed some sort of clause like this:
>>
>> module foo;
>> import bar;
>>
>> // Exact syntax not really important right now
>> this() dependsOn(bar) {
>>      // Do some initing that depends on
>>      // bar's static initializer having been run.
>> }
>>
>> That would force foo's static initialization to be run sometime after bar's. Obviously, any cycles in the graph of "dependsOn"s would be an error.
>>
>>
> 
> I'm curios - why isn't this a problem in other languages like Java (and
> I assume .net languages as well)?
> What's different in D that makes this so dificult? the static
> initializers? How is this handled in other languages?

In C/C++, if headers include each other and don't have any protection from multiple inclusion, they will include forever.  If they *do* have protection, you get weird errors about unknown symbols which are obviously should be known.  Only experience may tell you what happens.

In Java ME used in mobile phones, when class A is loaded, its static initializers are run.  If they refer to a class B which is not loaded yet, class B is loaded and its static initializers are run.  If B's initializers refer to static fields of class A, they consider A already loaded and get uninitialized values.  That is, crash at run-time.  I don't know what Java SE does in this case.