<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 8 Dec 2015, at 11:03 AM, Max Howell &lt;<a href="mailto:max.howell@apple.com" class="">max.howell@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">My question actually related to dependency (sub-dependency) conflict resolution which is listed as future feature.</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">For example, considering the initial state</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Module A -&gt; depends on Module B v.1 (1.0.0) -&gt; depends on Module D v.1</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Module A -&gt; depends on Module E v.1 (1.0.0) -&gt; depends on Module D v.1</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">In this case you would get a consistent dependency graph and everything would correctly compile statically into Module A. But if Module E makes a minor version update so that</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Module A -&gt; depends on Module B v.1 (1.0.0) -&gt; depends on Module D v.1</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Module A -&gt; depends on Module E v.1 (1.1.0) -&gt; depends on Module D v.2</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Without changing any code, Module A suddenly doesn’t have a consistent dependency graph, even if the changes to the public API of Module D don’t happen to impact the public APIs of Module E or Module A. Is this a concern or am I missing something here?</span><br style="font-family: Helvetica; font-size: 18px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote></div><br class=""><div class="">Thank you, I understand now.</div><div class=""><br class=""></div><div class="">Indeed, this is yet another possible dependency hell, so I’ll add it to our list [1]</div><div class=""><br class=""></div><div class="">We have at least one strategy that we hope we will be able to implement, i.e.: pure modules. We would like people to make their libraries small, focused and “pure”—in that they do not have any global state (even things like file system access). If they then declare their purity we can load both version 1 and version 2 of the same module into the same process.</div><div class=""><br class=""></div><div class="">This would work even if the modules are exposed publicly via API to another module lower in the graph, though in such cases it may be confusing to consumers of that library. So we may insist this sort of thing can only apply if the modules don’t get exported.</div><div class=""><br class=""></div><div class="">Another avenue we have explored is being more forceful with what package authors can do. That is, prohibiting such actions altogether. This has the benefit that dependency hell is much less likely. Ultimately we decided that sometimes you have to make such changes and it would be against our greater goals of providing flexible tools to have it operate this way.</div><div class=""><br class=""></div><div class="">Instead we plan to add a good deal of warnings to the tool that eventually will lint/publish packages. In the above case we would warn in big colorful letters to the user: “WARNING increasing the dependency version of Foo from v1 to v2 is irresponsible! Be sure you have good rationale before pushing!”</div><div class=""><br class=""></div><div class="">I would be interested to hear any more thoughts you have and if you think our approach will be successful. Thanks,</div><div class=""><br class=""></div><div class="">Max</div><div class=""><br class=""></div><div class="">[1]: <a href="https://github.com/apple/swift-package-manager/blob/master/Documentation/DependencyHells.md" class="">https://github.com/apple/swift-package-manager/blob/master/Documentation/DependencyHells.md</a></div></div></div></blockquote><br class=""></div><div>As you said, versioning is hard and these are the reasons why.</div><div><br class=""></div><div>I am guessing that to be able to load two versions of the same module into the same process the package builder re-namespace one or both to avoid a collision and change the referencing modules. Something like this should work, the only concern is making sure you limit the amount of ‘black magic’ that is going on - make sure its clearly explained what the package builder is doing otherwise there might be side effects - such as the size of a binary increasing because there are now two versions of a sub-module present - that suddenly appear without explanation.</div><div><br class=""></div><div>I think the approach of warning on these issues is a good one - at most having them as errors that fail the build but then can be explicitly ignored (as its very easy for devs to take the ‘well it compiled, must be good’ approach and completely ignore warnings). In terms 'make doing the correct/common thing easy and the rest possible’ its rare that you’d actually want to outright prohibit something so your approach seems solid with respect to that.</div><div><br class=""></div><div>I’m pretty excited by what I have seen so far with the package builder and it looks like its starting off with a good foundation. Let me know if there is anything I can contribute.</div><div><br class=""></div><div>-Simon</div><div><br class=""></div><div><br class=""></div><br class=""></body></html>