[MUD-Dev] Re: Why did it take years?
Cynbe ru Taren
cynbe at muq.org
Tue Oct 27 00:58:27 New Zealand Daylight Time 1998
Ola Fosheim <olag at ifi.uio.no> asks:
| "Bruce Mitchener, Jr." wrote:
| > Many of the people associated with these projects have a strong sense of
| > what the problems with the current (and previous) implementations are, and
| > how they would do things if they were to start from scratch. In some cases,
| > there are _years_ of work invested in those systems, getting them to where
| > they are today.
| Yes, and that leads to another question, why did it take years?
Which is a very fair question.
One quick answer:
* Muq proper is 100,000 lines of code.
* Industry estimates are that checking a 100,000 line for Y2K
compliance is enough to keep one programmer busy for one year.
* A typical industry estimate seems to be 20 lines of code per
day per programmer:
100,000 lines / 20 lines/day == 5000 days
5,000 days/ 364 days/year == 13.7 years.
(I'm presuming the progammer gets Christmas Day off work. :)
Naturally, this raises the question: Why does Muq need 100,000
lines of code? Is Cynbe just throwing too much stupid stuff in?
Here's the C-server breakdown:
FILE LINES FUNCTION
----- ----- --------
asm.t 3397 Binary encoding of bytecodes, including arity deduction.
blk.t 339 Blocks of arguments on stack.
bnm.t 5140 Big integers.
bot.t 332 Special bottom-of-stack guard class.
cdf.t 546 Class definition class.
cdt.t 622 Condition class.
cfg.t 1507 In-db Muq configuration display
cfn.t 798 Compiled-function class
chr.t 350 Character class
clo.t 690 Generic objects
dil.t 1017 B-tree support
ecn.t 464 Stack-allocated Lists.
err.t 143 Error logging
est.t 611 Stack-allocated structures.
evc.t 562 Stack-allocated vectors.
flt.t 332 Floating point numbers.
fun.t 785 Function source code objects.
int.t 338 Short integers.
jbs.t 558 Job sets, for internal job control.
job.t 33893 Implementations of various bytecodes.
jobbuild.t 3572 Generate opcode lookup tables & various functions.
jobd.t 580 Crypto primitive.
jobpass.t 429 Probes host and generates configuration header file.
joq.t 1341 Job queues.
key.t 1401 Keywords (much like UniqueStrings).
lbd.t 483 Lambda expressions (function all argument handling)
lib.t 495 Misc functions.
lok.t 461 Binary semaphores
lst.t 479 Lisp lists.
mod.t 304 Module list.
mss.t 1843 Message queues for interthread communication
mtd.t 496 Methods.
muf.t 7052 Bootstrap Multi-User-Forth compiler.
muq.t 1825 Display interpreter state to in-db code.
obj.t 5167 Generic object support.
pkg.t 581 Packages.
prx.t 469 Proxies, for transparent networking.
rdt.t 394 Readtables for lisp compiler.
rex.t 873 Regular expression support.
sdf.t 863 Structure definitions.
sha.t 688 Secure Hash Algorithm code.
sil.t 950 B-trees for properties on objects.
skt.t 5830 Network interface code for UDP and TCP.
spc.t 352 Special values like objectNotFound.
ssn.t 601 Sessions, for internal job control.
stc.t 700 Structures.
stg.t 1130 Strings.
stk.t 1053 Stacks.
stm.t 836 Generic streams.
sym.t 997 Symbols (package variables, essentially).
sys.t 1086 Display host system state to in-db code.
usq.t 640 User queues, part of job scheduling.
usr.t 2590 User objects.
vec.t 715 Vectors (fixed-length one-dimensional arrays).
vm.t 5418 Persistent heap manager.
z-muq.t 1025 Main(): arg parsing, startup and shutdown.
As Fred Brooks comments in the Mythical Man Month, it's the tarpit
that gets to you: It's not that any one part is hard, but that you
have to do -all- of them...
If you peer at the above list (or the source code itself), I think
you'll find almost all of it is pretty basic, generic functionality.
No multi-media support, unicode font support or anything exotic and
arguably easy to do without like that.
In addition to the 100,000 lines of hardcode, Muq currently has
40,000 lines of softcode:
FILE LINES FUNCTION
------------------ ------ -------
000-C-version.t 48 Library version number
010-C-condition.t 654 Standard conditions/exceptions
020-C-mos.t 1105 Muq Object System core
030-C-struct.t 669 Structures
060-C-lispread.t 453 Reader for lisp compiler.
070-C-lispprint.t 227 Printer for lisp compiler.
070-C-telnet.t 811 Per-user telnet daemon.
090-C-lisp.t 169 Lisp compiler core.
095-C-diffiehellman.t 145 Diffie-Hellman constants.
100-C-lists.t 1281 Softcoded List functions.
100-C-utils.t 2211 Random utility functions like 'ps'.
110-C-compile.t 339 State record for softcode Forth compiler.
120-C-muf.t 877 Core of softcode Forth compiler.
130-C-muf-syntax.t 2296 Additional syntax functions for Forth compiler.
140-C-defstruct.t 251 Defstruct syntax for Forth compiler.
140-C-init-shell.t 242 User shell for interactive Forth execution.
140-C-muf-shell.t 345 Ditto.
150-C-defclass.t 1313 Defclass syntax for Forth compiler.
155-C-stdconditions.t 228 Standard conditions/exceptions part II.
160-C-defgeneric.t 490 Defgeneric syntax for Forth compiler.
170-C-defmethod.t 440 Defmethod syntax for Forth compiler.
175-C-rex.t 1545 Regular expression syntax for Forth compiler.
180-C-make-instance.t 196 Creating class instances in Forth.
190-C-muqnet.t 3292 Muqnet daemon supporting transparent networking.
195-C-io.t 121 More transparent networking support.
200-O-edit.t 270 Trivial line editor in Forth.
250-C-debugger.t 655 Trivial exception handler ("debugger") in Forth.
280-O-vt100.t 225 vt100 cursor control in Forth.
300-X-nanomud.t 884 Demo extremely small mudserver in MUF.
310-X-nanomsh.t 644 Demo extremely small user shell for above.
330-W-oldmud.t 997 Core of the Micronesia mudserver.
335-W-oldop.t 123 Inter-daemon communication protocol definitions.
337-W-oldpub.t 425 String publishing for per-user daemons.
340-W-oldlive.t 175 Mixin for 'live' objects (mud-user-visible objs).
342-W-oldnop.t 171 NOP message handler for daemon protocol.
345-W-oldtask.t 726 Basic task support for daemon-daemon communication.
347-W-oldrequest.t 916 Usershell/Userdaemon API support.
350-W-olddaemon.t 608 Core daemon animating users objects.
360-W-oldping.t 139 Handler for PING protocol msg to an object.
363-W-oldlist-serv.t 516 Handler exporting lists of properties.
363-W-oldprop-serv.t 304 Handler exporting individual properties.
365-W-oldisle-list.t 1180 Handler exporting list of known isles. (Servers.)
365-W-oldnative-list.t 409 Handler exporting online users.
365-W-oldroom-host.t 249 Base class for rooms.
365-W-oldwho-list.t 395 Isle mixin supporting export of active-users.
365-W-oldwho-user.t 178 Avatar mixin supporting listing on who-list.
370-W-oldisle.t 530 Core class for Micronesia worlds/isles.
375-W-oldview.t 243 Base class for visible objects.
380-W-oldholder.t 777 Mixin for objects which can contain/be contained.
385-W-oldcanonical-room-name.t 120 Procedural building support.
385-W-oldecho-complete-string.t 153 User shell support.
385-W-oldhas-been-ejected.t 112 Handler for ejection messages.
385-W-oldhas-come.t 112 Procotol handler for avatar-arrival messages.
385-W-oldhas-left.t 112 Protocol handler for avatar-exit messages.
385-W-oldhear-page.t 111 Protocol handler recieving incoming pages.
385-W-oldhear-say.t 118 Protocol handler recieving incoming say/poses.
385-W-oldhear-whisper.t 111 Protocol handler recieving incoming whispers.
385-W-oldsubstring.t 147 Fetch a substring of a published string.
390-W-oldshell-host.t 117 State record for user shell.
395-W-oldthing.t 193 Basic holdable/visible mud object class.
400-W-oldexit.t 234 Basic exit class.
400-W-oldroom.t 257 Basic room class.
401-W-oldroom-cache.t 488 User-shell cache of objects in current room.
402-W-oldroom-cache2.t 546 API support code for above.
403-W-oldsay.t 155 Support code sending string to everyone in room.
405-W-oldavatar-view.t 269 Support code computing avatars description.
410-W-oldavatar.t 442 Basic avatar class.
420-W-badweight.t 177 Preliminary procedural-building support.
421-W-badset.t 157 Ditto.
422-W-badexit.t 141 Ditto.
423-W-badroom.t 229 Ditto.
425-W-badlands.t 244 Ditto.
465-W-oldsdb.t 131 Build sample isle.
470-W-oldmsh.t 186 Core defs for usershell.
475-W-oldmsh-ban.t 293 Class implementing @ban shell command.
475-W-oldmsh-boot.t 181 Class implementing @boot shell command.
475-W-oldmsh-dig.t 361 Class implementing @dig shell command.
475-W-oldmsh-doing.t 191 Class implementing @doing shell command.
475-W-oldmsh-eject.t 227 Class implementing @eject shell command.
475-W-oldmsh-gag.t 266 Class implementing @gag shell command.
475-W-oldmsh-go.t 243 Class implementing 'go' shell command.
475-W-oldmsh-help.t 195 Class implementing 'help' shell command.
475-W-oldmsh-hide.t 210 Class implementing @hide shell command.
475-W-oldmsh-home.t 174 Class implementing @home shell command.
475-W-oldmsh-inside.t 198 Class implementing @inside shell command.
475-W-oldmsh-look.t 470 Class implementing look shell command.
475-W-oldmsh-muf.t 186 Class implementing @muf shell command.
475-W-oldmsh-outside.t 198 Class implementing @outside shell command.
475-W-oldmsh-page.t 283 Class implementing @page shell command.
475-W-oldmsh-ping.t 204 Class implementing @ping shell command.
475-W-oldmsh-pose.t 204 Class implementing @pose shell command.
475-W-oldmsh-quit.t 259 Class implementing @quit shell command.
475-W-oldmsh-repeat.t 265 Class implementing @repeat shell command.
475-W-oldmsh-restart.t 184 Class implementing @restart shell command.
475-W-oldmsh-say.t 220 Class implementing @say shell command.
475-W-oldmsh-short.t 199 Class implementing @short shell command.
475-W-oldmsh-state.t 222 Class implementing @state shell command.
475-W-oldmsh-tunnel.t 355 Class implementing @tunnel shell command.
475-W-oldmsh-undig.t 224 Class implementing @undig shell command.
475-W-oldmsh-untunnel.t 224 Class implementing @untunnel shell command.
475-W-oldmsh-whisper.t 279 Class implementing 'whisper' shell command.
475-W-oldmsh-who.t 350 Class implementing @who shell command.
480-W-oldmsh-shell.t 545 Core driver for usershell.
490-W-root-oldmud.t 503 Root-privileged startup/shutdown/etc fns.
The above listing doesn't include:
softcode regression-suite code 10,000 lines
hardcode regression-suite code 3,000 lines
documentation source 40,000 lines
Those don't directly benefit the end-user, so they don't really
count, of course. :) But they still somehow wind up taking
time to write.
Total: About 200,000 lines of hand-generated files.
(Muq also has another 20,000 lines of source code not listed above,
which are automatically generated by its 'jobbuild' tool: Not writing
that code by hand avoided a fair amount of coding and debugging, and
made it enormously easier to reconfigure various things easily.
Possibly a point worth noting.)
I expect if you look at MOO or Cold or such you'll get a broadly
similar picture: There are no really killer individual coding
problems, but by the time you get it all done, it's a lot of little
DevMUD seems to me to be contemplating addressing a fair number of
difficult problems which Muq does not: With Muq, I've deliberately
tried to avoid doing anything terribly exotic, in favor of shipping
something solid relatively soon: If using Muq as an estimation base,
you may want to add (say) a *2 multiplier on for extra code required,
and another *2 for extra coding effort to break new ground rather than
following pretty familiar coding trails? If so, that would put you at
about 24 person-years to completion, it would seem, assuming no time
lost to defections or bickering.
Everyone still eager to dive in and get started? :) :) :)
(PS: I did a quick count of the number of source lines in
Golgotha: About 250,000.
On a quick scan, I see very little overlap between what the Muq
server does and what Golgotha does, so if you want an all-out
programmable distributed multimedia virtual world server/client, a
good quick estimate come from summing them: About 350,000 lines of
hardcode source and 500,000 total lines by the time you have a really
impressive softcode layer on top of it.
This is starting to approach the megaline barrier at which even
well-funded efforts run by experienced professionals start seeing
about a 50% failure rate, no...? Time for a thoughtful pause. :)
More information about the MUD-Dev