www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Working with modules

reply "Colin Grogan" <grogan.colin gmail.com> writes:
Hi all,

I have a question regarding how to lay out my code.

I wish to have a project directory structure that resembles java 
projects (As I'm comfortable working in that sort of environment

For example:
$PROJHOME
     |-/src     <- Source code
     |-/lib     <- third party libraries
     |-/bin     <- Compiled binaries
     |-build.sh <- script to build my project and stick the binary 
into 'bin' directory

So, my src directory is where all my source code is going. Under 
source code, im going to have a few different folders.

This is where my problem occurs. To illustrate:
$PROJHOME
     |-/src
         |- utils
              |- Logger.d
              |- Properties.d
              |- SSHTool.d
         |- engine

I want to put Logger.d, Properties.d and SSHTool.d into the 
module 'utils'. However, D's module system wont allow that, keeps 
throwing back errors to me saying 'utils' is conflicting (or 
something similar, cant remember the exact error).
So, I've done a bit of reading, and found out that I should put 
all those classes into once source file, and put that file in the 
module 'utils'.
Now, thats all fine and dandy, but I expect by the end of this 
experiment I will have quite a lot of utility classes and I 
really dont want them all in one source file. It becomes unwieldy 
imo.

Does anyone here have any alternatives for me so that in my 
'engine' or 'main' classes I can simply write:

     import utils;

and still have my source files neatly laid out in manageable 
chunks?

Thanks in advance...
Feb 15 2013
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
15-Feb-2013 13:51, Colin Grogan пишет:
[snip]

 This is where my problem occurs. To illustrate:
 $PROJHOME
      |-/src
          |- utils
               |- Logger.d
               |- Properties.d
               |- SSHTool.d
          |- engine

 I want to put Logger.d, Properties.d and SSHTool.d into the module
 'utils'. However, D's module system wont allow that, keeps throwing back
 errors to me saying 'utils' is conflicting (or something similar, cant
 remember the exact error).
 So, I've done a bit of reading, and found out that I should put all
 those classes into once source file, and put that file in the module
 'utils'.
 Now, thats all fine and dandy, but I expect by the end of this
 experiment I will have quite a lot of utility classes and I really dont
 want them all in one source file. It becomes unwieldy imo.

 Does anyone here have any alternatives for me so that in my 'engine' or
 'main' classes I can simply write:

      import utils;
Another way is to create utils/_.d file that contains: public import utils.Logger; public import utils.Properties; public import utils.SSHTool; and import it like this: import utils._; The other popular name for this module is 'all'.
 and still have my source files neatly laid out in manageable chunks?
Yeah, community at large wants a cleaner way to do this. It just wasn't sorted out yet: http://wiki.dlang.org/DIP14 http://wiki.dlang.org/DIP15
 Thanks in advance...
-- Dmitry Olshansky
Feb 15 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, February 15, 2013 10:51:00 Colin Grogan wrote:
 Does anyone here have any alternatives for me so that in my
 'engine' or 'main' classes I can simply write:
 
      import utils;
 
 and still have my source files neatly laid out in manageable
 chunks?
The only way that you can have a single import which imports multiple modules is if the module that you're importing publicly imports the other modules. And there is no way to do something like import utils.*; And remember that modules always correspond to files, and packages correspond to folders, so there's a one-to-one correspondance between what you'd import and what you'd put in the file system (unless you use public imports to make it so that importing a module imports stuff from outside that module). - Jonathan M Davis
Feb 15 2013
next sibling parent reply "Colin Grogan" <grogan.colin gmail.com> writes:
On Friday, 15 February 2013 at 10:01:35 UTC, Jonathan M Davis 
wrote:
 On Friday, February 15, 2013 10:51:00 Colin Grogan wrote:
 Does anyone here have any alternatives for me so that in my
 'engine' or 'main' classes I can simply write:
 
      import utils;
 
 and still have my source files neatly laid out in manageable
 chunks?
The only way that you can have a single import which imports multiple modules is if the module that you're importing publicly imports the other modules. And there is no way to do something like import utils.*; And remember that modules always correspond to files, and packages correspond to folders, so there's a one-to-one correspondance between what you'd import and what you'd put in the file system (unless you use public imports to make it so that importing a module imports stuff from outside that module). - Jonathan M Davis
Ah, ok. So, I have my structure like so: $PROJHOME |-src |-utils |- Logger.d // contains "module utils.Logger" |- Props.d // contains "module utils.Props" |- utils.d // contains "module utils; public import utils.Logger, utils.Props;" Then, i just 'import utils' in my code. Or would I have to have Logger.d in a directory called src/utils/Logger/Logger.d to be able to declare the module 'utils.Logger'?
Feb 15 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Friday, 15 February 2013 at 10:31:41 UTC, Colin Grogan wrote:
 Ah, ok.

 So, I have my structure like so:

 $PROJHOME
     |-src
        |-utils
           |- Logger.d // contains "module utils.Logger"
           |- Props.d //  contains "module utils.Props"
           |- utils.d //  contains "module utils;
                                    public import utils.Logger, 
 utils.Props;"

 Then, i just 'import utils' in my code.

 Or would I have to have Logger.d in a directory called 
 src/utils/Logger/Logger.d to be able to declare the module 
 'utils.Logger'?
Not exactly. With given layout you will need to use "import utils.utils;" in your code. There are no package imports in D currently at all. Separating modules into directories is not needed and will actually break everything. D module system maps to file system entities. File is a module. Directory is a package.
Feb 15 2013
parent reply "Colin Grogan" <grogan.colin gmail.com> writes:
On Friday, 15 February 2013 at 10:40:57 UTC, Dicebot wrote:
 On Friday, 15 February 2013 at 10:31:41 UTC, Colin Grogan wrote:
 Ah, ok.

 So, I have my structure like so:

 $PROJHOME
    |-src
       |-utils
          |- Logger.d // contains "module utils.Logger"
          |- Props.d //  contains "module utils.Props"
          |- utils.d //  contains "module utils;
                                   public import utils.Logger, 
 utils.Props;"

 Then, i just 'import utils' in my code.

 Or would I have to have Logger.d in a directory called 
 src/utils/Logger/Logger.d to be able to declare the module 
 'utils.Logger'?
Not exactly. With given layout you will need to use "import utils.utils;" in your code. There are no package imports in D currently at all. Separating modules into directories is not needed and will actually break everything. D module system maps to file system entities. File is a module. Directory is a package.
Ah ok, now I get it. Thanks for that everyone. Ill test it out once I get home. Cheers! I saw the wiki entry posted earlier with recommendations for different module/package management, is there any plans to implement any of these changes do you know?
Feb 15 2013
next sibling parent "Colin Grogan" <grogan.colin gmail.com> writes:
Ok, I had a minute so I tested it out.

I had the following:

 src/main.d:
    import utils._;

    void main(string[] args){
        logger l = new logger();
        props p = new props();
        l.print();
        p.print();
    }

 src/utils/_.d
    module utils._;
    public import utils.props, utils.logger;

 src/utils/logger.d
    module utils.logger;
    import std.stdio;

    public class logger{
        this(){}
        public void print(){
                writefln("This is logger...");
        }
    }

 src/utils/props.d
    module utils.props;

    import std.stdio;

    public class props{
        this(){}
        public void print(){
                writefln("This is props...");
        }
    }
Compiled and ran it, and it printed out This is logger... This is props... as I expected. That's perfect, solves my problem quite well I think! Thanks all!
Feb 15 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-02-15 12:04, Colin Grogan wrote:

 Ah ok, now I get it.
Note that in Java you declare a package wheres in D you declare a module. If you have something like this in Java: // Baz.java package bar.foo; You would do this in D: // Baz.d module bar.foo.Baz; -- /Jacob Carlborg
Feb 15 2013
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, February 15, 2013 11:31:40 Colin Grogan wrote:
 So, I have my structure like so:
 
 $PROJHOME
 
      |-src
      |
         |-utils
         |
            |- Logger.d // contains "module utils.Logger"
            |- Props.d //  contains "module utils.Props"
            |- utils.d //  contains "module utils;
 
                                     public import utils.Logger,
 utils.Props;"
 
 Then, i just 'import utils' in my code.
 
 Or would I have to have Logger.d in a directory called
 src/utils/Logger/Logger.d to be able to declare the module
 'utils.Logger'?
utils/logger.d would be utils.logger. utils/logger/logger.d would be utils.logger.logger. The file paths and the import paths are identical. It's just that the file paths have slashes, and the import paths have dots. And unlike Java, there is zero connection between classes and modules. You could have many classes in a single module or none at all. Also, it's common practice to use all lowercase for module and package names (primarily to avoid any risk of different OSes treating the casing differently I believe - i.e. Windows doesn't care about casing whereas *nix does; so, on Windows, you could screw up you're casing, and it would work, whereas on Linux, it wouldn't). - Jonathan M Davis
Feb 15 2013
prev sibling parent reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Friday, 15 February 2013 at 10:01:35 UTC, Jonathan M Davis 
wrote:
 On Friday, February 15, 2013 10:51:00 Colin Grogan wrote:
 Does anyone here have any alternatives for me so that in my
 'engine' or 'main' classes I can simply write:
 
      import utils;
 
 and still have my source files neatly laid out in manageable
 chunks?
The only way that you can have a single import which imports multiple modules is if the module that you're importing publicly imports the other modules. And there is no way to do something like import utils.*; And remember that modules always correspond to files, and packages correspond to folders, so there's a one-to-one correspondance between what you'd import and what you'd put in the file system (unless you use public imports to make it so that importing a module imports stuff from outside that module). - Jonathan M Davis
I was actually going to post a similar question, but it looks like this would be a better place to post! I know that a module can only be defined once, but I feel like there could be times where it would be helpful to be able to have the same module defined in separate files and I have an example. Right now, I am working on a binding and I am making use of the package access modifier to allow me to use internal objects that the end user will not be able to access directly. Problem is, my source files have many classes and are pretty convoluted. If I could define the module more than once I could split the source files up and it would be easier to work on, but I would still be able to share package declared objects and methods between modules like I do now. If I put the source files into their own packages, they are now hidden from source files I want them to be used in. Here's what I mean: mainpackage.system mainpackage.window mainpackage.graphics Anything defined with package is accessible between these. But... mainpackage.system.thing1 mainpackage.system.thing2 mainpackage.window.thing3 etc... Now things defined as package in mainpackage.system.thing1 are only accessible in mainpackage.system, but can't be accessed in mainpackage.window. Thoughts?
Feb 15 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/15/2013 07:50 PM, Jeremy DeHaan wrote:

 I know that a module can only be defined once, but I feel like there
 could be times where it would be helpful to be able to have the same
 module defined in separate files
There may be other ways of achieving that and I haven't given much thought to your question but there is also the import expression: http://dlang.org/expression.html#ImportExpression If needed, you can include D files similar to C's #include: mixin (import ("part_of_my_module.d")); mixin (import ("another_part_of_my_module.d")); Ali
Feb 15 2013
next sibling parent reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Saturday, 16 February 2013 at 04:14:41 UTC, Ali Çehreli wrote:
 On 02/15/2013 07:50 PM, Jeremy DeHaan wrote:

 I know that a module can only be defined once, but I feel
like there
 could be times where it would be helpful to be able to have
the same
 module defined in separate files
There may be other ways of achieving that and I haven't given much thought to your question but there is also the import expression: http://dlang.org/expression.html#ImportExpression If needed, you can include D files similar to C's #include: mixin (import ("part_of_my_module.d")); mixin (import ("another_part_of_my_module.d")); Ali
That is really cool! I'll look into this more, but I am using an IDE which would get angry if I included them in my project as .d files and didn't put in a module name, but I think you're on to something here.
Feb 15 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-02-16 05:19, Jeremy DeHaan wrote:

 That is really cool! I'll look into this more, but I am using an IDE
 which would get angry if I included them in my project as .d files and
 didn't put in a module name, but I think you're on to something here.
There's also template mixins that could help: http://dlang.org/template-mixin.html -- /Jacob Carlborg
Feb 16 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, February 15, 2013 20:14:41 Ali =C3=87ehreli wrote:
 On 02/15/2013 07:50 PM, Jeremy DeHaan wrote:
  > I know that a module can only be defined once, but I feel like the=
re
  > could be times where it would be helpful to be able to have the sa=
me
  > module defined in separate files
=20
 There may be other ways of achieving that and I haven't given much
 thought to your question but there is also the import expression:
=20
    http://dlang.org/expression.html#ImportExpression
=20
 If needed, you can include D files similar to C's #include:
=20
 mixin (import ("part_of_my_module.d"));
 mixin (import ("another_part_of_my_module.d"));
You can play games like this if you really want to, but in general, it = should=20 be kept in mind that modules in D are designed to have a one-to-one=20 correspondance with files, and packages are designed to have a one-to-o= ne=20 correspondance with directories. And in general, fighting that is just = going to=20 cause trouble and confusion. That doesn't necessarily mean that it shou= ld=20 never be done, but in most cases, it would be far better to just reorga= nize=20 your code so that it's not necessary. Also, AFAIK, mixing in imports is= a very=20 rare thing to do, so for the most part, people won't be expecting it, a= nd it=20 will likely cause maintenance issues for anyone else working on your pr= oject. What is more typically done when you need to split stuff up is to use i= nternal=20 modules which are only imported internally and are not presented as par= t of=20 the public API, but even that isn't terribly common, I don't think (but= unlike=20 mixing in imports, it's something that the standard library actually do= es in a=20 few places). - Jonathan M Davis
Feb 15 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-02-16 05:14, Ali Çehreli wrote:

 mixin (import ("part_of_my_module.d"));
 mixin (import ("another_part_of_my_module.d"));
How is that better than public imports. You'll get access to private declarations but besides that. -- /Jacob Carlborg
Feb 16 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/16/2013 04:58 AM, Jacob Carlborg wrote:
 On 2013-02-16 05:14, Ali Çehreli wrote:

 mixin (import ("part_of_my_module.d"));
 mixin (import ("another_part_of_my_module.d"));
How is that better than public imports. You'll get access to private declarations but besides that.
I don't think it is better than any other solution. I got reminded of this possibility; that's all. :) Ali
Feb 16 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-02-16 15:12, Ali Çehreli wrote:

 I don't think it is better than any other solution. I got reminded of
 this possibility; that's all. :)
Fair enough. :) -- /Jacob Carlborg
Feb 16 2013
prev sibling parent "Mike Parker" <aldacron gmail.com> writes:
On Saturday, 16 February 2013 at 03:50:12 UTC, Jeremy DeHaan 
wrote:
 I was actually going to post a similar question, but it looks 
 like this would be a better place to post!

 I know that a module can only be defined once, but I feel like 
 there could be times where it would be helpful to be able to 
 have the same module defined in separate files and I have an 
 example. Right now, I am working on a binding and I am making 
 use of the package access modifier to allow me to use internal 
 objects that the end user will not be able to access directly. 
 Problem is, my source files have many classes and are pretty 
 convoluted. If I could define the module more than once I could 
 split the source files up and it would be easier to work on, 
 but I would still be able to share package declared objects and 
 methods between modules like I do now. If I put the source 
 files into their own packages, they are now hidden from source 
 files I want them to be used in.

 Here's what I mean:


 mainpackage.system
 mainpackage.window
 mainpackage.graphics

 Anything defined with package is accessible between these.

 But...
 mainpackage.system.thing1
 mainpackage.system.thing2
 mainpackage.window.thing3
 etc...

 Now things defined as package in mainpackage.system.thing1 are 
 only accessible in mainpackage.system, but can't be accessed in 
 mainpackage.window.

 Thoughts?
On Saturday, 16 February 2013 at 03:50:12 UTC, Jeremy DeHaan wrote:
 I was actually going to post a similar question, but it looks 
 like this would be a better place to post!

 I know that a module can only be defined once, but I feel like 
 there could be times where it would be helpful to be able to 
 have the same module defined in separate files and I have an 
 example. Right now, I am working on a binding and I am making 
 use of the package access modifier to allow me to use internal 
 objects that the end user will not be able to access directly. 
 Problem is, my source files have many classes and are pretty 
 convoluted. If I could define the module more than once I could 
 split the source files up and it would be easier to work on, 
 but I would still be able to share package declared objects and 
 methods between modules like I do now. If I put the source 
 files into their own packages, they are now hidden from source 
 files I want them to be used in.

 Here's what I mean:


 mainpackage.system
 mainpackage.window
 mainpackage.graphics

 Anything defined with package is accessible between these.

 But...
 mainpackage.system.thing1
 mainpackage.system.thing2
 mainpackage.window.thing3
 etc...

 Now things defined as package in mainpackage.system.thing1 are 
 only accessible in mainpackage.system, but can't be accessed in 
 mainpackage.window.

 Thoughts?
I see this as more of a code architecture issue. It's up to you to decide which modules belong to which package, and that's that. If you see system and window as belonging to one package, then don't create subpackages. You can still split things up into separate modules if you need to: mainpackage.system mainpackage.systhing1 mainpackage.systhing2 mainpackage.window mainpackage.winthing3 You could keep your public-facing API in system and window or, if your design doesn't work that way, have things spread out over the various thing* modules and let system and window import them publicly. Either way, client code then imports system and window and pretends the rest don't exist. It would be nice to have a special module declaration to enforce this on the client side, something like: private module mainpackage.systhing1; Any module declared as such would not be importable outside of the package, but could still be explicitly imported into the namespace via a public import from another module in the same package.
Feb 15 2013