I came across this must-read article. I was a maintenance programmer for 29 years and I've come across many of the deadly sins that he discusses and maybe even one or two that he does not. How to Write Unmaintainable Code by Roedy Green.

Recommended Answers

All 4 Replies

Yeah, definitely a must-read! It makes you laugh and cry. There are things in there that just sound so outrageous and deliberately vicious against the maintainers. And it makes you laugh until you realize that you've seen exact examples of that in real-life production code.... and it really turns bitter when you realize you've written code like that before.

I can also easily think of a few main-stream production-grade projects that easily obey at least half of those rules for writing unmaintainable code (cough.. cough.. LLVM/Clang cough.. cough..).

At one time, I used to write a lot of FORTRAN code. In FORTRAN, many of these gems were ingrained in the way you were taught (i,j,k as integer variables, etc.). As I read through this, I had deja vu all over again with some of the code I've come across. However, the height of obfuscation is not making the code look obfuscated. That is a black art unto itself. ;-)

I did maintenance/development (mostly maintenance) with FORTRAN code for 15 years. I was really pissed when I found

INTEGER NINE /5/

but the worst ever code was

      SUBROUTINE READALL(UNIT,BUFF,*,*,IFIRST)
C*TTL READALL READ FROM ANYTHING
C
C
C
C     THIS SUBROUTINE IS USED FOR READING COMPRESSED OR UNCOMPRESSED
C     DATA INPUT FILES FROM LFC 'UNIT' INTO 80 BYTE ARRAYY BUFF.
C     END RETURNS TO FIRST RETURN, ERROR RTETURNS TO SECOND
C     IFIRST IS LOGICAL WHICH CALLER PROVIDES TRUE ON
C     FIRST READ OFF OF THIS ALLOCATION OF THIS LFC, ELSE FALSE
C*PGMXX READALL  SAVD TOOLS    FS$READA ON 07/23/80 17:43:51 01819B00R01
      LOGICAL IFIRST
      INTEGER*1 BUFF(80)
      INTEGER*4 UNIT
      INTEGER*1 BYTE(120,2)
C
C
      INTEGER*1 IN(2)/2*0/,ISP(2)/2*0/,ITX(2)/2*0/,NB(2)/2*0/
      INTEGER*1 NBT(2)/2*1/
      INTEGER*1 KCR/ZBF/,KLR/Z9F/
      INTEGER*1 EOR/ZFF/
      INTEGER*2 NSEQ(2)/2*0/,ITY(6),ISEQ(60,2),ICKS(60,2)
      INTEGER*4 LFC(2)/2*0/
      INTEGER*4 K,N,IERR,IN0,ISP0,ITX0,NB0,IS,I,ISUM,J
C
C
      EQUIVALENCE (BYTE(3,1),ICKS(1,1)),(BYTE(5,1),ISEQ(1,1))
C
C
      IF(.NOT.IFIRST) GO TO 21
      DO 19 K=1,2
      IN(K) = 0
      ISP(K) = 0
      ITX(K) = 0
      NB(K) = 0
      NBT(K) = 1
      NSEQ(K) = 0
      LFC(K) = 0
19    CONTINUE
21    CONTINUE
      DO 101 N=1,2
      IF (UNIT.EQ.LFC(N)) GO TO 103
      IF (LFC(N).EQ.0) GO TO 102
101   CONTINUE
      GO TO 94
102   LFC(N) = UNIT
      CALL W:PDEV(UNIT,ITY)
      NBT(N) = 1
      IF (ITY(3).GE.4.AND.ITY(3).LE.6) NBT(N)=2
103   IERR = 0
      IN0 = IN(N)
      ISP0 = ISP(N)
      ITX0 = ITX(N)
      NB0 = NB(N)
1     IF (IN0.NE.0) GO TO 8
2     CALL BUFFERIN(UNIT,0,BYTE(1,N),30)
      CALL M:WAIT(UNIT)
      CALL STATUS(UNIT,IS,NB0)
      IF (IS-3) 3,80,90
3     IF (BYTE(1,N).EQ.KCR.OR.BYTE(1,N).EQ.KLR) GO TO 6
      NB0 = NB0*NBT(N)
      DO 4 I=1,NB0
      IF (BYTE(I,N).EQ.10.OR.BYTE(I,N).EQ.13) BYTE(I,N) = 1R
4     BUFF(I) = BYTE(I,N)
      IF (NB0.GE.80) GO TO 20
      I = I+1
      DO 5 I=I,80
5     BUFF(I) = 1R
      GO TO 20
6     NB0 = BYTE(2,N)
      IF (NB0.GT.114) GO TO 91
      ISUM = 0
      DO 7 I=1,NB0
7     ISUM = ISUM+BYTE(I+6,N)
      IF (ISUM.NE.ICKS(1,N)) GO TO 92
      IF (ISEQ(1,N).NE.NSEQ(N)) GO TO 93
      NSEQ(N) = NSEQ(N)+1
      IN0 = 7
8     DO 16 I=1,80
      IF (ISP0.NE.0) GO TO 9
      IF (ITX0.NE.0) GO TO 12
      IF (BYTE(IN0,N).EQ.EOR) GO TO 9
      ISP0 = BYTE(IN0,N)
      IF (ISP0.GT.81-I) GO TO 91
      IN0 = IN0+1
      GO TO 10
9     ISP0 = ISP0-1
10    IF (ISP0.EQ.0) GO TO 11
      BUFF(I) = 1R
      GO TO 16
11    IF (BYTE(IN0,N).EQ.EOR) GO TO 9
      ITX0 = BYTE(IN0,N)
      IF (ITX0.GT.81-I) GO TO 91
      IN0 = IN0+1
12    BUFF(I) = BYTE(IN0,N)
      IF (BUFF(I).EQ.10.OR.BUFF(I).EQ.13) BUFF(I) = 1R
      ITX0 = ITX0-1
13    IN0 = IN0+1
      IF (IN0.LE.NB0+6) GO TO 16
      CALL BUFFERIN(UNIT,0,BYTE(1,N),30)
      CALL M:WAIT(UNIT)
      CALL STATUS(UNIT,IS,NB0)
      IF (IS-3) 14,80,90
14    IF (BYTE(1,N).NE.KCR.AND.BYTE(1,N).NE.KLR) GO TO 91
      NB0 = BYTE(2,N)
      IF (NB0.GT.114) GO TO 91
      ISUM = 0
      DO 15 J=1,NB0
15    ISUM = ISUM+BYTE(J+6,N)
      IF (ISUM.NE.ICKS(1,N)) GO TO 92
      IF (ISEQ(1,N).NE.NSEQ(N)) GO TO 93
      NSEQ(N) = NSEQ(N)+1
      IN0 = 7
16    CONTINUE
      IF (BYTE(IN0,N).NE.EOR) GO TO 91
      ISP0 = 0
      IF (ITX0.NE.0) GO TO 91
      IN0 = IN0+1
      IF (IN0.GT.NB0+6) IN0 = 0
      IF (BYTE(1,N).EQ.KLR.AND.IN0.EQ.0) NSEQ(N) = 0
20    IN(N) = IN0
      ISP(N) = ISP0
      ITX(N) = ITX0
      NB(N) = NB0
      RETURN
80    NSEQ(N) = 0
      IN(N) = ISP(N) = ITX(N) = 0
      RETURN 1
90    IERR = 1
91    IERR = IERR+1
92    IERR = IERR+1
93    IERR = IERR+1
94    IERR = IERR+1
      IN(N) = ISP(N) = ITX(N) = 0
      BUFF(1) = IERR
      RETURN 2
      END

The vendor (in order to save space on a 300 MB disk) wrote this gem for their line editor to read from (somewhat) compressed text files. I eventually rewrote it but it took days to recode (most of the time was taken up in testing). Dontcha just love the extensive documentation?

@Jim, wow this code is a real piece of work. My head hurt just looking at all those labels and gotos. Now, I do use gotos in my C code in the Linux kernel, but that's pretty much the standard way to write drivers in Linux. Still, none of that even compares to the gem you've just shared.

Thanks for reminding me just how bad code can get.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.