Include one source file into two libraries?

280 views
Skip to first unread message

George Moschovitis

unread,
Jan 5, 2013, 8:16:55 AM1/5/13
to mi...@dartlang.org
Is it possible to make one source file be part of two libraries? 

Here is an example: Let's say I am working on a new messaging protocol. I would like to offer two libraries, one for the server, one for the client.
Furthermore, I would like to define some protocol-specific constants (I miss enums/ADT) in a common source file that is part of both the server and the client library.

Any suggestions? Maybe there is another, idiomatic way to structure the code base for this scenario?

-g.

Kasper Lund

unread,
Jan 5, 2013, 8:33:09 AM1/5/13
to General Dart Discussion

I'd throw the shared constants into a separate library imported by both the client code and the server code. If necessary you can also reexport the constants from the client library and the server library.

Cheers,
Kasper

--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 

George Moschovitis

unread,
Jan 5, 2013, 1:16:17 PM1/5/13
to mi...@dartlang.org

I'd throw the shared constants into a separate library imported by both the client code and the server code. If necessary you can also reexport the constants from the client library and the server library.

Ah, yes, that's a solution.

Thanks,
-g.

George Moschovitis

unread,
Jan 6, 2013, 3:33:35 AM1/6/13
to mi...@dartlang.org
Out of curiosity,  why is the 'part of' directive required in the source files? Isn't the 'part' ref from the library file enough?
It's used just for documentation or does it somehow help with reasoning about the structure of the program?

-g.


PS: You should consider adding an article about the library concept, import 'uris', etc on dartlang.org

Ladislav Thon

unread,
Jan 6, 2013, 7:50:30 AM1/6/13
to mi...@dartlang.org
Out of curiosity,  why is the 'part of' directive required in the source files? Isn't the 'part' ref from the library file enough?

The part declaration in the main library file technically is enough to establish a library (and it used to be like that). The part of declaration serves as a back reference, so that the library and its files are linked from both sides. With that, you immediately know what library you are modifying when you are modifying a file. That is pretty important, I'd say. The only drawback is that one file can only be a part of one library -- which I think is essentially a good idea.

LT

P.S.: AFAIK you can have two libraries with the same name, which lets you put one file into more libraries. I believe that this should only be used for testing, so that the testing code can see _private identifiers.

Tom Yeh

unread,
Jan 6, 2013, 11:29:41 PM1/6/13
to mi...@dartlang.org
Can we make it a warning and allow to disable it with some option? It is a good check but not everyone needs it.

/ tom

Bob Nystrom

unread,
Jan 7, 2013, 1:40:11 PM1/7/13
to General Dart Discussion
On Sun, Jan 6, 2013 at 4:50 AM, Ladislav Thon <lad...@gmail.com> wrote:
The part declaration in the main library file technically is enough to establish a library (and it used to be like that). The part of declaration serves as a back reference, so that the library and its files are linked from both sides. With that, you immediately know what library you are modifying when you are modifying a file.

Well, you know its name, but you don't necessarily know what or where the library with that name is.
 
That is pretty important, I'd say. The only drawback is that one file can only be a part of one library -- which I think is essentially a good idea.

It can be a part of multiple libraries as long as they all have the same name.
 

LT

P.S.: AFAIK you can have two libraries with the same name, which lets you put one file into more libraries. I believe that this should only be used for testing, so that the testing code can see _private identifiers.

Exactly right. I believe this was done by design, though I personally find it confusing.

 - bob

Dirk Detering

unread,
Jan 8, 2013, 1:34:38 AM1/8/13
to mi...@dartlang.org

Am 06.01.2013 13:50 schrieb "Ladislav Thon" <lad...@gmail.com>:
> library and its files are linked from both sides. With that, you immediately know what library you are modifying when you are modifying a file. That is pretty important, I'd say. The only drawback is that one file can only be a part of one library -- which I think is essentially a good idea.
>

The interesting thing here is the notion of what a library _is_ , and what a _part of a library_ is in consequence.

So for every code that would be part of more than one lib we should ask why it is not a lib in itself, making "lib" a more fine grained concept than it may look at first.

When I look into Java land, a "lib" in this sense is a 'jar' file.Sharing code (classes) between jars here is almost always a result of the following
1.) The jars are all part of only one project and created during the same build cycle.
2.) The jars are heavily interrelated, e.g.
A) being a client and server side of one "library" product
B) being a compile-time API vs. a runtime implementation part of a "library" product.
C) being different versions of a "library" product, either timed versions or usage variants.

Each of the mentioned situations in 2. exist because a "library" in form of a jar is understood as being a deploy time packaging-and-delivery artefact, not a development time code separation and reuse artefact.
In the case the latter notion is applied, there is no shared code any more, but OTOH you cannot deliver "one library" any more too. Each deployment is then a bunch of interrelated jars (compare with maven dependencies).

Thus for packaging a product, Java people have invented "ears" or "wars", or whatever package format a specific packaging tool would provide.

Ladislav Thon

unread,
Jan 8, 2013, 1:55:31 AM1/8/13
to mi...@dartlang.org

The interesting thing here is the notion of what a library _is_ , and what a _part of a library_ is in consequence.

So for every code that would be part of more than one lib we should ask why it is not a lib in itself, making "lib" a more fine grained concept than it may look at first.

When I look into Java land, a "lib" in this sense is a 'jar' file.Sharing code (classes) between jars here is almost always a result of the following
1.) The jars are all part of only one project and created during the same build cycle.
2.) The jars are heavily interrelated, e.g.
A) being a client and server side of one "library" product
B) being a compile-time API vs. a runtime implementation part of a "library" product.
C) being different versions of a "library" product, either timed versions or usage variants.

Each of the mentioned situations in 2. exist because a "library" in form of a jar is understood as being a deploy time packaging-and-delivery artefact, not a development time code separation and reuse artefact.
In the case the latter notion is applied, there is no shared code any more, but OTOH you cannot deliver "one library" any more too. Each deployment is then a bunch of interrelated jars (compare with maven dependencies).

Thus for packaging a product, Java people have invented "ears" or "wars", or whatever package format a specific packaging tool would provide.


Yeah. In Dart world, I prefer to think about it like this: library is a unit of code reuse, package is a unit of deployment.

LT 

Kasper Lund

unread,
Jan 8, 2013, 2:00:47 AM1/8/13
to General Dart Discussion
Using the same part in two different libraries is likely to lead to
weird errors -- and it is certainly not something we're encouraging,
not even for testing. It's problematic because it is so easy to get
two identical, yet distinct classes (just one example) and you'll feel
thoroughly miserable trying to understand why 'is' checks and checked
mode complains about that instance of MyClass that works just like any
other MyClass yet isn't a MyClass instance if you ask it:

mylib.dart:
--
library mylib;
part 'myclass.dart';
final MyClass mySingleton = new MyClass();
--

myclass.dart:
--
part of mylib;
class MyClass {
static const XXX = 42;
yyy() => XXX;
}
--

test.dart:
--
library mylib; // hehe
import 'mylib.dart';
part 'myclass.dart';
main() {
MyClass m1 = mySingleton; // FAILS in checked mode
MyClass m2 = mySingleton; // FAILS in checked mode
assert(identical(m1, m2));
assert(m1 is MyClass); // FAILS
assert(m1.yyy() == MyClass.XXX);
}
--

The reason why we've decided to allow you to have two libraries with
the same name (and just warn about it) is that we'd like to be able to
run code that happens to include two third party libraries with the
same name -- in which case . We're considering making this a
compile-time error (rather than a warning) if the two libraries with
the same name aren't in separate partitions of the import graph.

Cheers,
Kasper

Paul Brauner

unread,
Jan 8, 2013, 2:23:51 AM1/8/13
to mi...@dartlang.org

Sounds reasonable but then would it make sense to have an "import show private" directive for testing?
The reason I don't like to make private methods public is not so much that it is "dangerous" but rather that it pollutes the dartdoc.

Kasper Lund

unread,
Jan 8, 2013, 2:36:52 AM1/8/13
to General Dart Discussion
On Tue, Jan 8, 2013 at 8:23 AM, Paul Brauner <po...@google.com> wrote:
> Sounds reasonable but then would it make sense to have an "import show
> private" directive for testing?

We have talked about a way of allowing tests to access private stuff.
No concrete plans yet though.

Cheers,
Kasper

George Moschovitis

unread,
Jan 8, 2013, 7:13:39 AM1/8/13
to mi...@dartlang.org

Yeah. In Dart world, I prefer to think about it like this: library is a unit of code reuse, package is a unit of deployment.

The term 'library' is rather unfortunate then, maybe 'module' should have been more appropriate.

-g.

Bob Nystrom

unread,
Jan 8, 2013, 1:00:29 PM1/8/13
to General Dart Discussion


On Mon, Jan 7, 2013 at 10:55 PM, Ladislav Thon <lad...@gmail.com> wrote:
Yeah. In Dart world, I prefer to think about it like this: library is a unit of code reuse, package is a unit of deployment.

For what it's worth, my definitions are a bit different here:

1. I think of a library as the unit of understanding: To hack on a chunk of code, I think it's reasonable to expect the person to know a bit about the entire library that contains it. (Conversely, I think you should be able to use a library without needing to know much about other libraries in the same package.)

2. I think of a package as the unit of reuse. It's actually specifically defined to be that. You can depend on packages. You can't depend on libraries.

3. I think of a package and its transitive dependencies as the unit of deployment. You can't deploy a package without its dependencies. (Well, you can, but it probably won't do much...)

- bob

Dirk Detering

unread,
Jan 8, 2013, 1:22:58 PM1/8/13
to mi...@dartlang.org

Am 08.01.2013 19:00 schrieb "Bob Nystrom" <rnys...@google.com>:
> 2. I think of a package as the unit of reuse. It's actually specifically defined to be that. You can depend on packages. You can't depend on libraries.
>

Please define: You
Please define: depend
Each code importing a library "depends" on said library imho.
Two libraries each importing a third library "reuse" it.

> 3. I think of a package and its transitive dependencies as the unit of deployment. You can't deploy a package without its dependencies. (Well, you can, but it probably won't do much...)

Please define: deploy
Seems we have a bit of different definitions here, where yours might be strongly based on pub perspective?
The way I use 'deploy', it may perhaps better be replaced by 'deliver'?

Ladislav Thon

unread,
Jan 8, 2013, 3:25:24 PM1/8/13
to mi...@dartlang.org
1. I think of a library as the unit of understanding: To hack on a chunk of code, I think it's reasonable to expect the person to know a bit about the entire library that contains it. (Conversely, I think you should be able to use a library without needing to know much about other libraries in the same package.)

My reason here is that you can't reuse anything smaller than a library. (Well, you can have a file that is meant to be part-ed into arbitrary libraries, but that's a special case and is generally discouraged.)

But unit of understanding is good too.

2. I think of a package as the unit of reuse. It's actually specifically defined to be that. You can depend on packages. You can't depend on libraries.

I'd actually say that you do depend on libraries, at least on the language level. Library is the thing you import. How do you get the library, that's a different thing (and it's a matter of deployment actually.) A package can have more libraries and you can reuse arbitrary selection of libraries in a package, therefore package can't be a unit of reuse.
 
3. I think of a package and its transitive dependencies as the unit of deployment. You can't deploy a package without its dependencies. (Well, you can, but it probably won't do much...)

Again, my reason here is that you can't deploy anything smaller than a package. If a package has mandatory dependencies, it obviously makes little sense to deploy it alone, but even then, the unit is the package.

But then, this is just a debate about terms. And since the deployment story in Dart is far from being finished (and it might as well be far from being started :-) ), it's a purely theoretical debate. Also, I might have my English wrong, maybe I should have used the word atom instead of unit in the above.

LT

Bob Nystrom

unread,
Jan 8, 2013, 3:54:36 PM1/8/13
to General Dart Discussion
I should have been clearer here:

On Tue, Jan 8, 2013 at 10:22 AM, Dirk Detering <mail...@googlemail.com> wrote:
> 2. I think of a package as the unit of reuse. It's actually specifically defined to be that. You can depend on packages. You can't depend on libraries.
>

Please define: You

Someone wanting to reuse some "external" Dart code where you don't want to be coupled to where that code is on your physical file system.

Please define: depend

"Depend" in the pub sense: have a declarative dependency on some other code where the mechanics of how that dependency is acquired is abstracted somehow.

Each code importing a library "depends" on said library imho.

True, but there's already a nice word for that "imports". I'd rather not use "depends" to mean the same thing because then it leaves me without a word to express what pub does at the package level.

For what it's worth, the language spec never uses "depends" to refer to libraries importing each other.

Two libraries each importing a third library "reuse" it.

> 3. I think of a package and its transitive dependencies as the unit of deployment. You can't deploy a package without its dependencies. (Well, you can, but it probably won't do much...)

Please define: deploy

Roughly, "make production accessible". In the common case of a web app, that probably means stuffing the app and its dependencies onto some server where it can be served up to a browser.

Seems we have a bit of different definitions here, where yours might be strongly based on pub perspective?

The pub perspective is the One True Perspective! ;) Yes, you're right, I am looking at this from the package management angle, but I think that's likely the most natural view for terminology like "dependency" and "deploy".

The way I use 'deploy', it may perhaps better be replaced by 'deliver'?

If you mean "deliver" in the sense of "send your finished work to some paying client" then, yes, I wouldn't use "deploy" in that sense. But you're right that if someone asks you to make package Foo, you can deliver the goods in that case without having to also send them Foo's dependencies if they can just get those themselves.

Cheers!

- bob

Tom Yeh

unread,
Jan 8, 2013, 9:37:22 PM1/8/13
to mi...@dartlang.org
Allow me to illustrate a more complicated case. Let us say I'd like to provide a library for handling Element. At client side, I can import dart:html. At the server side, I can import html5lib, which provides a nice set of Element, Document, etc. The only way I can figure out is to use George's approach: include the same source in two different libraries. Unfortunately, it is stopped by Dart compiler now. 

Any suggestion?

Bob Nystrom

unread,
Jan 9, 2013, 12:20:12 PM1/9/13
to General Dart Discussion
On Tue, Jan 8, 2013 at 6:37 PM, Tom Yeh <tom....@gmail.com> wrote:
Allow me to illustrate a more complicated case. Let us say I'd like to provide a library for handling Element. At client side, I can import dart:html. At the server side, I can import html5lib, which provides a nice set of Element, Document, etc.

This falls squarely within the problem that we're calling "configuration-specific code". This problem comes up at every single language design meeting and is understood to be a high priority.
 
The only way I can figure out is to use George's approach: include the same source in two different libraries. Unfortunately, it is stopped by Dart compiler now. 

Any suggestion?

In your case where you want to have code that works generically with types defined in two different libraries, there isn't an easy solution. You could do something some really complicated shenanigans with configuration libraries and forwarding methods and all sorts of overhead, and you'd probably have to remove all of your type annotations. But, honestly, at that point, you'd more likely just give up entirely.

Gilad is working on a proposal to address this, so I hope we can have a better answer here and soon.

Cheers,

- bob

Dirk Detering

unread,
Jan 9, 2013, 1:00:48 PM1/9/13
to mi...@dartlang.org

Am 08.01.2013 21:55 schrieb "Bob Nystrom"<rnys...@google.com>:

Thanks ,Bob, for your clarifying definitions.

> True, but there's already a nice word for that "imports". I'd rather not use "depends" to mean the same thing because then it leaves me without a word to express what pub does at the package level.
>

Interesting. I understood "depends" to be a more abstract concept, being more of a _property_ of the dependent code (in the sense of an adjective), while "import" is a more concrete way of how this dependency is solved in the case of libraries, using a verb (could be "use" in other case or "include" in another one).

>> Please define: deploy
>
> Roughly, "make production accessible". In the common case of a web app, that probably means stuffing the app and its dependencies onto some server where it can be served up to a browser.
>>

> If you mean "deliver" in the sense of "send your finished work to some paying client" then, yes, I wouldn't use "deploy" in that sense. But you're right that if someone asks you to make package Foo, you can deliver the goods in that case without having to also send them Foo's dependencies if they can just get those themselves.
>

That was exactly my point!

Bye
Det

Reply all
Reply to author
Forward
0 new messages