digitalmars.D.learn - code coverage and module constructors
- BCS (9/9) Jun 19 2006 If two modules mutually import each other, you can't use code coverage
If two modules mutually import each other, you can't use code coverage on both of them. This is (I think) because the code coverage is implemented with some sort of module constructor and generate a loop (static this in mod-a must be run before the static this in mod-b which must be run before the static this in mod-a ...). However this is bunk, -cov for one module shouldn't have any dependencies on any other module. D already has one case where a module constructor like thing is use that doesn't care about circular imports, unittests. Why then isn't the cov startup run the same way?
Jun 19 2006
BCS wrote:If two modules mutually import each other, you can't use code coverage on both of them. This is (I think) because the code coverage is implemented with some sort of module constructor and generate a loop (static this in mod-a must be run before the static this in mod-b which must be run before the static this in mod-a ...). However this is bunk, -cov for one module shouldn't have any dependencies on any other module. D already has one case where a module constructor like thing is use that doesn't care about circular imports, unittests. Why then isn't the cov startup run the same way?Yeah .... -cov simply highlights the problem if cyclic imports with static-ctors; simply becuase -cov injects a static-ctor into each module (or something like that). On the other hand, cyclic imports are kinda "poor form" - for want of a better description. You *can* eliminate them, potentially using an interface as an intermediary; and probably *should* eliminate them. Of course, that doesn't help when there's cyclic imports all over the library code that one happens to be using (the Win32 headers?). I understand where you're coming from on this, and wholly sympathise since I recently had to redesign a few substantial chunks of code to eliminate the problem. However, I suspect the end-result of my effort was worth it. Hope that doesn't muddy the waters too much?
Jun 19 2006
kris wrote:BCS wrote:Why are they poor form? (This is a non-rhetorical question, I would like to hear your reasoning.) Putting all your types off by them selves in there own modules can help some. But what about, say, a pair of structs that have methods that take each other as arguments but otherwise have no reason to be in the same module? e.g. struct foo { ... void UseBar(bar b){...} } struct bar { ... void UseFoo(foo f){...} } And interfaces cause a bit of a performance hit (they are bigger for one). Even if this can be eliminated in most cases. Sooner or later it won't be practical or desirable to do it. I would list this as a high priority item on the to list, right below getting -cov working.If two modules mutually import each other, you can't use code coverage on both of them. This is (I think) because the code coverage is implemented with some sort of module constructor and generate a loop (static this in mod-a must be run before the static this in mod-b which must be run before the static this in mod-a ...). However this is bunk, -cov for one module shouldn't have any dependencies on any other module. D already has one case where a module constructor like thing is use that doesn't care about circular imports, unittests. Why then isn't the cov startup run the same way?On the other hand, cyclic imports are kinda "poor form" - for want of a better description. You *can* eliminate them, potentially using an interface as an intermediary; and probably *should* eliminate them.Of course, that doesn't help when there's cyclic imports all over the library code that one happens to be using (the Win32 headers?). I understand where you're coming from on this, and wholly sympathise since I recently had to redesign a few substantial chunks of code to eliminate the problem.<nods> I've just lived without static constructors some times.However, I suspect the end-result of my effort was worth it. Hope that doesn't muddy the waters too much?
Jun 19 2006
BCS wrote:kris wrote:[snip]Well, my little gripe with cyclic imports is that they tend to tighly-couple implementation details. That's very much a design-dependent measure, so it's a bit airy fairy for most purposes. For example, some designs are intended to be tightly-coupled. One the other hand, there's something to be said for a large body of code that can be cleanly represented as a DAG (no cycles). Tends to make the overall system a whole lot easier to extend, easier to decouple as necessary, and so on. I suppose it's all about maintenance? Maybe a whiff of 'elegance'? Maybe not. [snip]On the other hand, cyclic imports are kinda "poor form" - for want of a better description. You *can* eliminate them, potentially using an interface as an intermediary; and probably *should* eliminate them.Why are they poor form? (This is a non-rhetorical question, I would like to hear your reasoning.) Putting all your types off by them selves in there own modules can help some. But what about, say, a pair of structs that have methods that take each other as arguments but otherwise have no reason to be in the same module?Yeah ... in my case, I had to get a fairly substantial library working with -cov, since it would seem rather bogus for a lib to conflict in that respect. Don't want to get off topic too much, but I found Dimple to be a true bobsend for visualizing import-relationships over a large (200+) swathe of modules. I've also discovered that attempts to make the diagrams look 'cleaner' (through refactoring) have an equally pleasant effect on the codebase design itself :)I understand where you're coming from on this, and wholly sympathise since I recently had to redesign a few substantial chunks of code to eliminate the problem.<nods> I've just lived without static constructors some times.
Jun 19 2006