www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem with one-class-per-file approach

reply Kris Herlaar <kris theredhead.nl> writes:
Hi folks,

Allow me to introduce myself, I'm Kris and new to this list and the D =
language in general, but have well over 20 years of programming =
experience using several other languages ranging from Wozniaks' integer =
basic to Hejlsbergs' c#.

My first venture using D is to create a set of classes implementing XML =
DOM using familiar syntax for people used to php or javascript and such. =
I was able to write the basics for this in D in a few hours using a =
bunch of classes:

- XMLDocument
- XMLNode
- XMLAttribute
- XMLElement
- XMLTextNode
- XMLComment
- XMLCDataSection
- XMLNodeList
- XMLAttributeList

All in the package "red.xml"

Being used to (and really liking!) the one-class-per-file approach, I =
instinctively created the classes in seperate files. When attempting to =
compile a simple test program however it quickly became totally =
unrealistic to use the one-class-per-file approach because I had to =
import each and every single file seperately in order to get a working =
build. When I moved all the classes into a single module =
(red.xml.xmldom) it worked flawlessly but I would really like to have =
the best of both approaches.

Is it possible to split the files up to use one class per file again, =
but add a red.xml.xmldom module imports and exposes them somehow?

I was hoping it'd be something like the following in the red.xml.dom =
module:

import red.xml.xmldocument;
import red.xml.xmlnNode;
import red.xml.xmlattribute;
import red.xml.xmlelement;
import red.xml.xmltextnode;
import red.xml.xmlcomment;
import red.xml.xmlcdatasection;
import red.xml.xmlnodelist;
import red.xml.xmlattributelist;

But that doesn't seem to work (I get a whole bunch of "module ... is in =
multiple defined" errors).

I'm compiling with the latest dmd compiler on the commandline in macos x =
(10.6) using a commandline tool I built in php that compiles a file =
"main.d" and adds all imported dependencies to the dmd commandline. The =
generated commandline statement looks like this:

dmd -of/Users/kris/Developer/D/xml-tests/main -unittest =
/Users/kris/Developer/D/xml-tests/main.d =
/Users/kris/Developer/D/xml-tests/red/generic/linkedlist.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlnode.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmldocument.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlattribute.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlattributelist.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlelement.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmltextnode.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlcomment.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlcdatasection.d =
/Users/kris/Developer/D/xml-tests/red/xml/xmlnodelist.d =
/Users/kris/Developer/D/xml-tests/red/xml/dom.d

more readable:

dmd -ofmain -unittest main.d=20
	red/generic/linkedlist.d=20
	red/xml/xmlnode.d=20
	red/xml/xmldocument.d=20
	red/xml/xmlattribute.d
	red/xml/xmlattributelist.d
	red/xml/xmlelement.d
	red/xml/xmltextnode.d
	red/xml/xmlcomment.d
	red/xml/xmlcdatasection.d
	red/xml/xmlnodelist.d
	red/xml/dom.d

I've also tried versions omitting the dom.d (same errors), and adding =
only dom.d (lots of "identifier ... is not defined" errors), but nothing =
works the way I'd hope and/or expect.

Is there any clean way to do this?

I can make my sourcecode available if anyone would like that (for the =
build tool as well).
Mar 08 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Kris Herlaar:

 Allow me to introduce myself, I'm Kris and new to this list and the D language
in general,

Welcome here and to D then.
 Being used to (and really liking!) the one-class-per-file approach, I
instinctively created the classes in seperate files.<

D gives you the freedom, if you want, to put single classes in files, but the normal D idiom is to put related classes in a single module (if they aren't too much long). And keep in mind that in D there are also free functions (and templates, inner functions, true closures, etc), so you don't need to use classes for everything.
 import red.xml.xmldocument;
 import red.xml.xmlnNode;
 import red.xml.xmlattribute;
 import red.xml.xmlelement;
 import red.xml.xmltextnode;
 import red.xml.xmlcomment;
 import red.xml.xmlcdatasection;
 import red.xml.xmlnodelist;
 import red.xml.xmlattributelist;

You can also write: public import red.xml.xmldocument, red.xml.xmlnNode, red.xml.xmlattribute, ... red.xml.xmlattributelist;
I'm compiling with the latest dmd compiler on the commandline in macos x (10.6)
using a commandline tool I built in php that compiles a file "main.d" and adds
all imported dependencies to the dmd commandline.<

There are several already written programs to do that :-) For example I use 'bud', there is also rdmd built in the distribution. Bye, bearophile
Mar 08 2010
prev sibling parent BCS <none anon.com> writes:
Hello Kris,

 Hi folks,
 
 Is it possible to split the files up to use one class per file again,
 but add a red.xml.xmldom module imports and exposes them somehow?

Take a look at the details of import. IIRC "public import" does something like what you want.
 
 I was hoping it'd be something like the following in the red.xml.dom
 module:
 
 import red.xml.xmldocument;
 import red.xml.xmlnNode;
 import red.xml.xmlattribute;
 import red.xml.xmlelement;
 import red.xml.xmltextnode;
 import red.xml.xmlcomment;
 import red.xml.xmlcdatasection;
 import red.xml.xmlnodelist;
 import red.xml.xmlattributelist;
 But that doesn't seem to work (I get a whole bunch of "module ... is
 in multiple defined" errors).

I don't know what's causing that, but my first guess would be to add module "red.xml.whatever;" lines to each module. -- ... <IXOYE><
Mar 08 2010