[comp.lang.c++] A GNU Makefile

rfg@NCD.COM (Ron Guilmette) (02/08/91)

In article <1991Feb5.180503.24515@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>
>I agree 100% with Ron that HEADER FILES SHOULD BE AUTOMATICALLY GENERATED.
>I always heard people moaning about header file management and wondered
>what I was doing wrong because I never ran into those problems. Well, I 
>do something pretty similar to Ron's approach, except that I tag each
>individual item (class, struct, global data, function) with either EXPORT
>or PRIVATE (null-defined strings) and use an AWK script to extract the
>.h file.

Cay's approach is OK but (of course) I like mine a little bit better.
Mine was patterened after the idea of "public" and "private" parts of
packages in Ada.  Now I know that just mentioning the "A word" in this
group is normally the kiss of death for any ideas discussed in the same
message, but you will be missing out if you don't at least consider
some approach for automating the maintenance of your .h files.

I promised some people that I would post my GNU Makefile, so here it comes.

------------------------------------------------------
The following Makefile implements the approach to automatic maintenance
of include files (including the inline or non-inline version builds) that
I described in a previous posting.  Somebody asked me for a copy of this
and I decided that, rather than having to respond to too many requests,
I would just post it.

Some comments are appropriate here.

First, as I said in my previous posting, this Makefile makes use of several
extensions to plain "make" which may be available *only* in GNU make.

Second, I use the suffix .H for all of my include files which contain C++
code.  This fact is reflected in the following Makefile.

Third, the .H files which get automatically generated by this makefile all
comform to the general pattern:

	#ifndef FILENAME_H
	#define FILENAME_H
	#pragma once
		... interface stuff ...
	#endif

Since FILENAME is just the upshifted version of the base part of the actual
.C filename, you should not use any special characters in your filenames
(except maybe underscores).

This makefile assumes that each of your .C files has two parts as follows:

	... interface part ...
	//########################################################
	... implementation part ...

In this scheme, you may have #include directives either in the interface
part or in the implementation part, but it will usually be pretty
important to get each of your #include directives into the proper part.
Most often, your #include directives should go into the *implementation*
part, unless (for some reason) you absolutely *must* have them in the
upper interface part.

Having #includes in the upper (interface) part can lead to circularities
in your dependencies.

Note that all declarations of variables and functions in C++ (and in C) can
be either explicitly "extern" or explicitly "static" or neither.  Using the
following Makefile (and this whole scheme for maintaining header files
automatically) you should *never* place any non-extern declarations of
variables or functions into the interface part.  The interface part
should contain only the definitions of types (e.g. class, struct, union,
and enum type as well as typedefs) and extern declarations of functions
and objects.

In actuality, I usually maintain my .C files in *three* parts as follows:

	... interface part ...
	//########################################################
	... inline function definitions part ...
	//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	... implementation part ...

If I want to build a small and easily debuggable version of my program,
I just use the following Makefile as-is.  When I want to generate a fast
version (e.g. all inlining enabled) I just comment out the Makefile line:

	DEFINES= -Dinline=

and then I edit the line that says:

	@sed '/############/,$$d' $< >> $*.H+

So that all of the #'s are made into %'s instead.  Then I just do a
`make realclean' and then a `make all'.  It's that simple.

Using this approach to software development requires a lot of disipline
(which most programmers seem to lack).  If you are not prepared to
expend some effort in making this scheme work then don't even bother
trying it.  This scheme requires that you maintain your .C files in
a certain form and that you be very careful about the placement of
various declarations and definitions.  If you can live with that, then
using this scheme can be very helpful, especially on large projects.

Note that this scheme is very similar to Ada's approach to the problem 
of separate compilation.  In Ada, you have package `specifications' (i.e.
interface parts) and package `bodies' (i.e. implementation parts).  You
also have "with" clauses, which are somwhat similar to #include directives
in this scheme.  Unlike Ada however, the C/C++ programmer has no "hidden
agent" to trigger recompilations automatically on an "as-needed" basis.
The following Makefile attempts to duplicate that functionality using
GNU make to act as the "library maintainer" agent.

The following Makefile was developed by me on my own home system.  It
has nothing whatsoever to do with my work for NCD or for anybody else.
Up until the time I posted it to the net, it was my private property.
Now, it is in the public domain.

Cut here
-----------------------------------------------------------------------------
SHELL = /bin/sh

DEFINES= -Dinline=

GPLUSPLUS=g++ -Wall
CFRONT = CC +p +w
CPLUSPLUS= $(GPLUSPLUS)
#CPLUSPLUS= $(CFRONT)
CPLUSPLUS_FLAGS =  $(DEFINES) -g # -O

COMPILE=$(CPLUSPLUS)
LINK=$(COMPILE)

OBJECTS= \
	three.o \
	two.o \
	one.o \
	main.o

SOURCES= $(patsubst %.o,%.C,$(OBJECTS))

INCLUDES= $(patsubst %.o,%.H,$(OBJECTS))

TIMESTAMPS= $(patsubst %.o,.%.timestamp,$(OBJECTS))

EXECUTABLE = myprog

.PRECIOUS:	.%.timestamp %.H

%.o:	%.C %.H
	$(COMPILE) $(CPLUSPLUS_FLAGS) -c $<

.%.timestamp:	%.C
	@echo Checking $*.H
	@rm -f $*.H+
	@HNAME=`echo $* | tr '[a-z]' '[A-Z]'`_H; \
		echo '#ifndef' $$HNAME >> $*.H+; \
		echo '#define' $$HNAME >> $*.H+
	@echo '#pragma once' >> $*.H+
	@sed '/############/,$$d' $< >> $*.H+
	@echo '#endif' >> $*.H+
	@if cmp -s $*.H+ $*.H; then \
		rm -f $*.H+; \
	else \
		echo Replacing $*.H; \
		rm -f $*.H; \
		mv $*.H+ $*.H; \
	fi
	@touch $@

%.H:	.%.timestamp
	@true

all:	$(EXECUTABLE)

$(EXECUTABLE):	$(OBJECTS)
	$(LINK) $(LDFLAGS) -o $(EXECUTABLE) $(OBJECTS)

clean:
	rm -f $(OBJECTS) core

clobber:
	rm -f $(EXECUTABLE) core

realclean: clean clobber
	rm -f $(INCLUDES) $(TIMESTAMPS)

install:
	cp $(EXECUTABLE) /usr/local/bin/$(EXECUTABLE)

depend:	$(INCLUDES)
	sed '/^# DO NOT TOUCH THIS LINE/,$$d' Makefile > Makefile+
	echo '# DO NOT TOUCH THIS LINE' >> Makefile+
	-rm -f dependencies
	for base_file in $(SOURCES); do \
		$(GPLUSPLUS) -MM $$base_file \
		| tr -d '\012' | tr '\\' ' ' | tr -s ' ' ' ' >> Makefile+; \
		echo ' ' >> Makefile+; \
	done
	-rm -f Makefile-
	mv Makefile Makefile-
	mv Makefile+ Makefile
	rm -f Makefile-

.PHONY: all clean clobber realclean install depend

# DO NOT TOUCH THIS LINE
three.o : three.C 
two.o : two.C three.H
one.o : one.C two.H three.H
main.o : main.C one.H two.H three.H
-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

euamts@eua.ericsson.se (Mats Henricson) (02/11/91)

In article <1991Feb5.180503.24515@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>
>I agree 100% with Ron that HEADER FILES SHOULD BE AUTOMATICALLY GENERATED.

Maybe I've misunderstood the whole thing, but I think this is a bad idea.
The most important thing with a C++ class is its interface to the outside
world, i.e. the header file. That is why I design the header file first,
and then the .cc-file. That is also why I think .cc-file stubs should be
generated from .h-files in any decent programming environment.

Mats Henricson

rfg@NCD.COM (Ron Guilmette) (02/17/91)

In article <1991Feb11.081550.18057@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>In article <1991Feb5.180503.24515@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>>
>>I agree 100% with Ron that HEADER FILES SHOULD BE AUTOMATICALLY GENERATED.
>
>Maybe I've misunderstood the whole thing...

Perhaps you have.

>... but I think this is a bad idea.
>The most important thing with a C++ class is its interface to the outside
>world, i.e. the header file. That is why I design the header file first,
>and then the .cc-file.

And you never go back and make any changes to the "interface" part once
you have written it for the first time!?!?!?!

I'd like to meet you someday.  I've never had the opportunity to meet a
"perfect" programmer before!

>That is also why I think .cc-file stubs should be
>generated from .h-files in any decent programming environment.

In other words you want the "implementation" part to be automatically
derived from the "interface" or "specification" part, eh?

Well, join the club.  This idea of "automatic programming" has been the holy
grail of software for about 30+ years now.

Give us another 30 years or so and we'll call you. :-)

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

dag@control.lth.se (Dag Bruck) (02/18/91)

In article <3943@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>In article <1991Feb11.081550.18057@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>>The most important thing with a C++ class is its interface to the outside
>>world, i.e. the header file. That is why I design the header file first,
>>and then the .cc-file.
>
>And you never go back and make any changes to the "interface" part once
>you have written it for the first time!?!?!?!
>I'd like to meet you someday.  I've never had the opportunity to meet a
>"perfect" programmer before!
>In other words you want the "implementation" part to be automatically
>derived from the "interface" or "specification" part, eh?

These comments are so stupid that they have to be a deliberate joke.
Just in case they aren't, allow me to point out that:

1.  If the the design is well-understood and verified, for example by
implementing a prototype, we can generate header files and stubs from
the prototype. 

2.  If the design is good, there will be few changes in the
definition, so some automatic help generating the first set of stubs
will be helpful even if subsequent changes must be handcrafted.

3.  Some organizations do software development in a more "serious" way
than either you and I, for example, AT&T and Ericsson.  It should be
plain obvious that they rarely can afford changing the class interface
after it has entered the production environment.

Oh, well.  Excuse me for overreacting.

In any case, I cannot see the big difference of starting with the .H
file and generating the .C file, or going the other way.  The whole
idea of separate .H/.C files is old, and doesn't work too well.  A
better integrated system, like the module concept of Modula-2 (which
I'm experienced with), works much better.  What we need is something
like a database of class definitions, class implementations, typedefs,
etc.  In particular, I miss the possibility to "import" just part of
what is bundled in a .H file.

To answer the obvious question:  No, I don't think this should part of
the C++ language definition, it should be part of the environment.

Dag M. Bruck
--
Department of Automatic Control		E-mail: dag@control.lth.se
Lund Institute of Technology
P. O. Box 118				Phone:	+46 46-104287
S-221 00 Lund, SWEDEN			Fax:    +46 46-138118

hitz@sim5.csi.uottawa.ca (Martin Hitz) (02/19/91)

In article <3943@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>In article <1991Feb11.081550.18057@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>>In article <1991Feb5.180503.24515@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>>>
>>>I agree 100% with Ron that HEADER FILES SHOULD BE AUTOMATICALLY GENERATED.
>>
>>Maybe I've misunderstood the whole thing...
>
>Perhaps you have.
>
>>... but I think this is a bad idea.
>>The most important thing with a C++ class is its interface to the outside
>>world, i.e. the header file. That is why I design the header file first,
>>and then the .cc-file.
>
>And you never go back and make any changes to the "interface" part once
>you have written it for the first time!?!?!?!
>
>I'd like to meet you someday.  I've never had the opportunity to meet a
>"perfect" programmer before!

Neither have I. During early stages of the development process,
when the final shape of .h files is not yet totally well defined, we
simulate our .h files with a slightly elaborated version of the following
mechanism:

----------------- file x.h (preliminary version):
#ifndef X_H
#define X_H
#include "x.cc"
#endif
----------------- eof x.h
----------------- file x.cc (preliminary version):
// #include "x.h" - will be activated later 

class X {
 public:
	X();
};

extern X x;

#ifndef X_H  /* implementation part #1 */
X::X()
{
	/****************/
}

X x;
#endif  

class Y {
/***** etc. ****/
};

#ifndef X_H /* implementation part #2 */
/* Y implementation */
#endif
----------------- eof x.cc

Once the interface has stabilized, the real x.h is generated (by hand,
by sed, by awk, by the preprocessor ...) and the x.cc is shrunk.
Of course, this method needs a tailored makefile, too, where every .h
dependency is replaced by a corrseponding .cc dependency.

Martin (hitz@csi.UOttawa.CA)

harrison@necssd.NEC.COM (Mark Harrison) (02/21/91)

In article <1991Feb20.083327.2028@eua.ericsson.se>,
euamts@eua.ericsson.se (Mats Henricson) writes:

> >>... but I think this is a bad idea.
> >>The most important thing with a C++ class is its interface to the outside
> >>world, i.e. the header file. That is why I design the header file first,
> >>and then the .cc-file.
> 
> >And you never go back and make any changes to the "interface" part once
> >you have written it for the first time!?!?!?!
> 
> Of course I do! But, if you put enough work down on the header-file, you
> don't have to change it *that* often to justify any extra feature like the
> one you have suggested.

I agree with Mats on this.  A stable interface is one of the most important
factors in being able to reuse code.  I have more confidence in someone
who emphasizes generating a code stub from an interface defintion than
in someone who wants to write the code first and then generate the
interface.

The second approach is just too amenable to throwing something together,
generating an interface, and calling the thing a package.  Of course,
for single use or special purpose code this is not important, so it
would still be handy to do generate the header... Just realize that
it is not the best way for "permanent" reusable code.

Just imagine if Ken Thompson suddenly decided to spell "creat" with an "e". :-)

> >// Ron Guilmette  -  C++ Entomologist
> Mats Henricson / SWEDEN - Home of the perfect programmer ;-)


-- 
Mark Harrison             harrison@necssd.NEC.COM
(214)518-5050             {necntc, cs.utexas.edu}!necssd!harrison
standard disclaimers apply...

throop@aurs01.UUCP (Wayne Throop) (02/22/91)

> harrison@necssd.NEC.COM (Mark Harrison)
>>,>>>> euamts@eua.ericsson.se (Mats Henricson) writes:

>>>> ... but I think [..automatic .h generation..] is a bad idea. [...]
>>>> That is why I design the header file first, and then the .cc-file.
>> [...] you don't have to change it *that* often 
> I agree with Mats on this.  [...]  I have more confidence in someone
> who emphasizes generating a code stub from an interface defintion than
> in someone who wants to write the code first and then generate the
> interface.

Just because one edits a .cc file first is not an indication that one
is "writing the code first".  As I said before (in a different branch
of this discussion), I write the .cc file as a file full of stubs
(using templates to save typing, of course), and automatically generate
the .h files from the .cc files.  The advantages this gives me are:

    1) it becomes easier to enhance interfaces (on those rare
       ocasions where it is needed).  (Just because something is
       rare is no reason to make it a headache.)
    2) I have one-stop-shopping for editing things, as the interface
       and (eventually) implementation are presented together, 
       and teased apart by automated tools.

Now, note that both of these benefits are somewhat weak.  The first
has small leverage because of its (intended) rarity.  The second problem
can be held at bay by a multiple-window editing tool (emacs, X-windows
plus editor, whatever).

But however marginal the benefits, I still think the benefits are
actual, not illusory, and are worthwhile.

Wayne Throop       ...!mcnc!aurgate!throop

rfg@NCD.COM (Ron Guilmette) (02/26/91)

In article <1991Feb18.073640.1335@lth.se> dag@control.lth.se (Dag Bruck) writes:
>In article <3943@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>>In article <1991Feb11.081550.18057@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>>>The most important thing with a C++ class is its interface to the outside
>>>world, i.e. the header file. That is why I design the header file first,
>>>and then the .cc-file.
>>
>>And you never go back and make any changes to the "interface" part once
>>you have written it for the first time!?!?!?!
>>I'd like to meet you someday.  I've never had the opportunity to meet a
>>"perfect" programmer before!
>>In other words you want the "implementation" part to be automatically
>>derived from the "interface" or "specification" part, eh?
>
>These comments are so stupid that they have to be a deliberate joke.
>Just in case they aren't, allow me to point out that:
>
>1.  If the the design is well-understood and verified, for example by
>implementing a prototype, we can generate header files and stubs from
>the prototype. 

Dag, please take one or two more classes in English.  You twisted around
my statement until you got is completely backwards.  You say that we
can generate the header files (I assume you mean what I call the
"interface" to a C++ "module") in an automated way.  Perhaps that is
true.  I don't know.  But that's got no relationship at all to the point
I was making.  What I said (quoted above) was that it seemed that Mats
was asking for the whole *implementation* part to be generated from just
the *interface* part.

That's is absolutely impossible with current technology.

If you are still having trouble understanding what is meant by the terms
"interface part" and "implementation part" then please send me mail
and I will try to explain these terms to you so that you can understand
them and so that you will understand the meaning of my English sentences.

Please don't feel bad that you are having trouble understanding my use of
clear English. Other recent postings to this newsgroup indicate that
there are also many native speakers who don't seem to be able to
understand plain English either.

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

ksand@Apple.COM (Kent Sandvik) (02/26/91)

In article <4107@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>In article <1991Feb18.073640.1335@lth.se> dag@control.lth.se (Dag Bruck) writes:
>>In article <3943@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>>>In article <1991Feb11.081550.18057@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>>>>The most important thing with a C++ class is its interface to the outside
>>>>world, i.e. the header file. That is why I design the header file first,
>>>>and then the .cc-file.
>>>
>>>And you never go back and make any changes to the "interface" part once
>>>you have written it for the first time!?!?!?!
>>>I'd like to meet you someday.  I've never had the opportunity to meet a
>>>"perfect" programmer before!
>>>In other words you want the "implementation" part to be automatically
>>>derived from the "interface" or "specification" part, eh?
>>
>>These comments are so stupid that they have to be a deliberate joke.
>>Just in case they aren't, allow me to point out that:
>>
>>1.  If the the design is well-understood and verified, for example by
>>implementing a prototype, we can generate header files and stubs from
>>the prototype. 
>
>Dag, please take one or two more classes in English.  You twisted around
>my statement until you got is completely backwards.  You say that we
>can generate the header files (I assume you mean what I call the
>"interface" to a C++ "module") in an automated way.  Perhaps that is
>true.  I don't know.  But that's got no relationship at all to the point
>I was making.  What I said (quoted above) was that it seemed that Mats
>was asking for the whole *implementation* part to be generated from just
>the *interface* part.
>
>That's is absolutely impossible with current technology.
>
>If you are still having trouble understanding what is meant by the terms
>"interface part" and "implementation part" then please send me mail
>and I will try to explain these terms to you so that you can understand
>them and so that you will understand the meaning of my English sentences.
>
>Please don't feel bad that you are having trouble understanding my use of
>clear English. Other recent postings to this newsgroup indicate that
>there are also many native speakers who don't seem to be able to
>understand plain English either.

Well, I have to write myselfd a couple of clear English sentences in a non-
native language about this issue :-).

This whole thread seems to be a big misunderstanding from the beginning
to the current end. It starts with one person stating that he first 
designs header files, and after that starts working with implementation
files.

After this statement person no 2 says that this is stupid, because
header files are subject to change in design.

Person 3 says that there are prototype tools that could generate
header and method code automatically.

By which person 2 states that "I did not say that at all", and states
that he believed that the first person wrote that method code is 
automatically generated from the information in the header file.

Well, R.I.P.

Kent Sandvik, English Language Meta-Morphosis Cannibalist

PS: Usenet is fun, comp.lang.c++ discussions end up as English
language discussions :-)




-- 
Kent Sandvik, Apple Computer Inc, Developer Technical Support
NET:ksand@apple.com, AppleLink: KSAND  DISCLAIMER: Private mumbo-jumbo
Zippy++ says: "C++ was given to mankind, so that we might learn patience"

rfg@NCD.COM (Ron Guilmette) (03/03/91)

In article <1991Feb20.083327.2028@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>
>>And you never go back and make any changes to the "interface" part once
>>you have written it for the first time!?!?!?!
>
>Of course I do! But, if you put enough work down on the header-file, you
>don't have to change it *that* often to justify any extra feature like the
>one you have suggested.

How much work would constitute "enough work" so that you would try to use
a clever Makefile to eliminate some or all of that work?  (Keep in mind
that the clever Makefile was already provided, so you don't even have to
develop it.)

Now perhaps you code your "interface parts" very very carefully, right
from the start, and perhaps this means that you very rarely have to
change even so much as a comma in them.  That's fine.  In that case,
I agree that you would not benefit much from the Makefile that I posted.

Likewise, if you use Emacs or some other editor that allows you to easily
edit multiple files at one time, then the benefit of my scheme (based upon
the tricky Makefile) is diminished somewhat.

However if you are "evolving" some brand new code (in fast and furious mode,
sometimes called "hacking") then you may often find that you need to make
some change which affects *both* the interface and the implementation parts
(e.g. adding an additional member function or data member to a class
definition and then adding some references to the new member in some of
the implementation parts of existing member functions, or adding one
more parameter to the declaration of some member function within the
class declaration and also adding the additional parameter to the
implementation of that member function).

All I know is that my own experience of developing new C++ code led me
to feel that it would often be that case that I would need to make some
change which would need to be reflected in *both* the interface part and
in the implementation part.  I found myself repeatedly doing:

		start editor to edit .C file
		modify .C file
		exit editor (saving changes)
		start editor to edit corresponding .h file
		modify .h file
		exit editor (saving changes)
		start editor to edit .C file
		.
		.
		.

I no longer do that.  These days, when I am working on "refining" some
class, I have everything which relates to that class (both its interface
and its implementation) in one single file.  To "refine" the class, I
always know that I only have to edit one particular file.

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

euamts@eua.ericsson.se (Mats Henricson) (03/04/91)

rfg@NCD.COM (Ron Guilmette) writes:

>In article <1991Feb20.083327.2028@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
>>
>>>And you never go back and make any changes to the "interface" part once
>>>you have written it for the first time!?!?!?!
>>
>>Of course I do! But, if you put enough work down on the header-file, you
>>don't have to change it *that* often to justify any extra feature like the
>>one you have suggested.

>How much work would constitute "enough work" so that you would try to use
>a clever Makefile to eliminate some or all of that work?  (Keep in mind
>that the clever Makefile was already provided, so you don't even have to
>develop it.)

Quite a lot. It took me perhaps 2 weeks to specify the .h-file for a large
class (approx 50 final pages of code). And I enjoyed the work, since I think
that was when I was constructing something. The implementation was aslo OK,
but not as inspiring since I knew all the way almost exactly what to do.
I kind of see it as travelling - planning is the best thing. When you
finally take off, you know it's soon over.

>Now perhaps you code your "interface parts" very very carefully, right
>from the start, and perhaps this means that you very rarely have to
>change even so much as a comma in them.  That's fine.  In that case,
>I agree that you would not benefit much from the Makefile that I posted.

Yo.

>Likewise, if you use Emacs or some other editor that allows you to easily
>edit multiple files at one time, then the benefit of my scheme (based upon
>the tricky Makefile) is diminished somewhat.

I may be very lycky to be able to keep multiple editors open at the same
time, and a screen big enough to look at two files at the same time, but
that must soon be default for programmers, and programming environments not
designed for multiple editors open at the same time must be pretty out of
date.

>However if you are "evolving" some brand new code (in fast and furious mode,
>sometimes called "hacking") then you may often find that you need to make
>some change which affects *both* the interface and the implementation parts
>(e.g. adding an additional member function or data member to a class
>definition and then adding some references to the new member in some of
>the implementation parts of existing member functions, or adding one
>more parameter to the declaration of some member function within the
>class declaration and also adding the additional parameter to the
>implementation of that member function).

I find hacking OK, but my boss would rightly be screaming at me if I did.
At LOOK '91 in Denmark recently I listened to Steven Weiss, and he pointed
out that "A quality system is a system that is easy to maintain". My bitter
experience is that hacking may seem to give quality software, but if you
look at it from the maintenance point of view, it's not. I'm paid to do
quality software, and will do so carefully my way, since I'm not a hacker,
nor a specially good programmer (I'm still looking at the Andrew Koenig
paper on Function Objects in The C++ Journal * summer 1990, since my mind
just refuses to grasp how this rediculously short piece of code actually
works :-!  ).

>All I know is that my own experience of developing new C++ code led me
>to feel that it would often be that case that I would need to make some
>change which would need to be reflected in *both* the interface part and
>in the implementation part.  I found myself repeatedly doing:

>		start editor to edit .C file
>		modify .C file
>		exit editor (saving changes)
>		start editor to edit corresponding .h file
>		modify .h file
>		exit editor (saving changes)
>		start editor to edit .C file
>		.
>		.
>		.

I think you can justify to the money department at your company, that
they will make money if they buy you a larger monitor since you will be
more efficient that way.

>I no longer do that.  These days, when I am working on "refining" some
>class, I have everything which relates to that class (both its interface
>and its implementation) in one single file.  To "refine" the class, I
>always know that I only have to edit one particular file.

OK! It's a free world after all...

>-- 

>// Ron Guilmette  -  C++ Entomologist
>// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
>// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

Mats Henricson euamts@eua.ericsson.se

rfg@NCD.COM (Ron Guilmette) (03/10/91)

In article <1991Mar4.085153.13371@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
+rfg@NCD.COM (Ron Guilmette) writes:
+
+>In article <1991Feb20.083327.2028@eua.ericsson.se> euamts@eua.ericsson.se (Mats Henricson) writes:
+At LOOK '91 in Denmark recently I listened to Steven Weiss, and he pointed
+out that "A quality system is a system that is easy to maintain". My bitter
+experience is that hacking may seem to give quality software, but if you
+look at it from the maintenance point of view, it's not. I'm paid to do
+quality software, and will do so carefully my way, since I'm not a hacker,
+nor a specially good programmer (I'm still looking at the Andrew Koenig
+paper on Function Objects in The C++ Journal * summer 1990, since my mind
+just refuses to grasp how this rediculously short piece of code actually
+works :-!  ).

My use of the terms "hacker" and "hacking" were perhaps unfortunate,
since they undermined the point I myself was trying to make.  What I
meant to say was "rapid prototyping".  (1/2 :-)  I believe that I
(and some others) can write good quality code, and that such code can
be developed (by some people) both quickly and in an evolutionary way.

You need not necessarily plan every tiny detail of your trip in advance
in order to arrive at a good place (in the end).

+>All I know is that my own experience of developing new C++ code led me
+>to feel that it would often be that case that I would need to make some
+>change which would need to be reflected in *both* the interface part and
+>in the implementation part.  I found myself repeatedly doing:
+
+>		start editor to edit .C file
+>		modify .C file
+>		exit editor (saving changes)
+>		start editor to edit corresponding .h file
+>		modify .h file
+>		exit editor (saving changes)
+>		start editor to edit .C file
+>		.
+>		.
+>		.
+
+I think you can justify to the money department at your company, that
+they will make money if they buy you a larger monitor since you will be
+more efficient that way.

I have a VERY LARGE monitor, thank you.  (NCD makes terrific X-terminals
after all.)  I also have Emacs (even though I prefer not to use it most
of the time.)  That's not the point.  The point is that I'm a damn slow
typist, and no matter how big you screen, and no matter how many windows
your editor can keep open at a time, you have still got to type in another
filename each time you need to edit another (related) header file.

That's what my scheme allowed you to avoid.

Now I guess that you could get yourself a 32" monitor and have a script
or a mock-lisp routine (for Emacs) which you could execute once each
morning (when you fisrt came into work) which would bring up 82 windows
(one for each .h or .C file in the system you are working on now) and
then you would never have to open another window on another file, but
I for one think that it makes more sense to just keep my interface and
implementations parts in single individual files.  That cuts down on the
typing I do, and (perhaps even more importantly) I find this to be a
wonderful organizing principal.  It basically forces you into a certain
style of coding where you are forced to keep everything which is directly
related to a given class type (e.g. `foo') within one single source file.
You can then call the file `foo.C'.  Now, when some other `maintainer'
gets stuck with your code, and when he finds out that `foo' objects are
malfunctioning, he knows exactly where to look.
-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// New motto:  If it ain't broke, try using a bigger hammer.