
How to Write Unmaintainable Code (1999) - dhuramas
https://www.doc.ic.ac.uk/%7Esusan/475/unmain.html
======
Someone
They are missing the creatieve use of your version control system.

First, make sure none of your commits actually build out of the box; forget a
file for a few revisions, accidentally check in a corrupted XML file, etc.

Create a "trunkV2" directory, and keep committing to both trunk and trunkV2.
Add a third trunk inside the "branches" tree (/branches/featureX/newTrunk; I
have seen this n practice, with random customer branches sprinkled in)

In the tree of the service that your program calls, do something different,
for example by starting with a simple tag 'V1 frozen', adding the revisions of
the V2 version and then occasionally unfreezing the V1 one by committing a
combined "undo everything since V1" and "tiny fix to the v1 protocol that we
thought was frozen", followed by an "undo that, and do something else" commit.
Make sure to comment those commits as "version for customer X" and "bug fix #3
for customer Y"; do not mention "V1" or "V2".

Also, make sure that "customer X" has both V1 and V2 deployed, so that future
developers cannot learn that "customer X" implies "version 2".

~~~
bazzargh
One I saw happen: avoid merge conflicts by having each developer maintain
their own fork of trunk, or better still, multiple forks. Copy and paste is
easier than merge anyway. Automate builds for all these, and provide a way to
release any of them, without recording which you used. Never, ever tag. You
want to delete branches too? Sure, why not. Of course this makes it hard to
track dependencies, so be sure to check in the binaries of the projects you
depend on into your project, especially if those were built on your own
machine from source you haven't checked in instead of builds from the build
server.

(and when I say 'saw happen', I mean 'I spent a week in Kiev at 12 degrees
below freezing trying to figure out where the source code had gone'...we never
found all of it)

~~~
aidenn0
In Subversion, I've seen branches created, deleted, and then another branch
created with the same name from a different subtree of the repository.

I was also successfully able to export all of this to git with every deleted
branch now still in existence.

~~~
tracker1
I definitely like the git workflow more... branch, work, rebase, PR, review,
rework, rebase, review... merge.

short change cycles are easier to reason with.

------
buro9
They've missed the liberal use of dependency injection, triggers, or anything
that can create a side effect of an event without being documented in the
function being executed.

Much fun to be had there. Even just setting up PostgreSQL partition tables can
defeat the most diligent maintainer (as they suddenly find RETURNING id_column
fails everywhere).

------
macca321
There's only one rule:

1\. Don't write fast running behavioural tests that verify the software is
working as required.

With fast running tests I can maintain any old crap. Well, technically
speaking I can rewrite it, but no-one will mind.

~~~
deckar01
Write tests that ensure each subroutine is called with specific parameters, so
that functionally identical modifications cause the test to fail. Any change
to the code now requires a change to several tests.

~~~
tempodox
Isn't that what TDD is all about? The logical consequence is code that vitally
depends on the existence of specific tests.

~~~
macca321
TDD will leave you with a load of tests which prevent you from changing the
code. BDD on the other hand should leave you with a suite that isn't coupled
to a specific implementation.

Part of the information contained in a test is the intent of the verification
being performed, and part is code for mapping that intent onto the
implementation. The latter part can be discarded during a rewrite.
Cucumber/SpecFlow etc. make the difference between these explicit.

~~~
marcosdumay
> and part is code for mapping that intent onto the implementation

Wait, what?! The more I listen people talking about TDD, the more I discover I
always misunderstood it, and the less I want to actually understand it.

~~~
tempodox
The thing is, unit tests that are affordable to implement, are not wort it.
Their objectives should rather be verified with language choice, programming
techniques, and assertions. Tests that are worthwhile to write are those that
test interactions of multiple subsystems. But those are not unit tests any
more. If you end up _actually needing_ TDD, then that proves you are using the
wrong language and/or the wrong technique.

------
runholm
"Hugh McDonald, hughmcd@ican"

The guy has an e-mail address hosted at a top level domain. 1999 was a silly
time.

~~~
buro9
That is crazy.

I thought I was doing well to have my name be a valid domain:
[https://david.kitchen/](https://david.kitchen/)

------
arethuza
I've thought a particularly effective approach is actually to do the "right"
thing but take it to ridiculous lengths - the "Enterprise FizzBuzz" that was
posted on HN recently being a good example of this.

~~~
jschwartzi
Use all of the techniques described in the GOF book at the same time.Your
flyweight should collapse because the facade was too heavy with decorators to
support another observer.

------
davecridland
Also a later version at
[http://www.stateslab.org/HowToWriteUnmaintainableCode-
Green0...](http://www.stateslab.org/HowToWriteUnmaintainableCode-Green00.html)
which includes that crazy offbeat language, JavaScript (which was, amusingly,
my contribution).

------
sbov
> E.g. on the screen label the field "Postal Code" but in the code call the
> associated variable "zip".

If you support multiple countries this is probably an inevitability. Same with
province vs state, potentially others.

I guess you could have one variable called "postalCode" and one called "zip",
but that seems potentially more confusing.

Also, sometimes your UI shifts - should all your code change then? Because the
boss wants to call something different in the UI? "We were calling them
admins, now we want to call them CSR." Is it time to write a regexp to rename
everything?

~~~
tracker1
Adding... for web applications use IDs and Classes liberally in the html
output... for actual string injection, especially if you support
internationalization, this is needed so you can separate the text to display
from the controls in place.

------
JayOtter2
I had Susan as a tutor in my first year at Imperial. This made me chuckle.

~~~
mherrmann
Same here ;-)

------
nippoo
My favourite one must be number 20. Best ever quote of Thumper I've seen...!

"Never document gotchas in the code. If you suspect there may be a bug in a
class, keep it to yourself. [...] Remember the words of Thumper "If you can't
say anything nice, don't say anything at all". What if the programmer who
wrote that code saw your comments? What if the owner of the company saw them?
What if a customer did? You could get yourself fired."

------
emersonrsantos
How about obfuscated MUMPS?

P R I N T S (A,L)=1,(S,T)=I N G G I V E N A O F A=L:L:S Q:U=A R E S B=E L O W
(A*A),! I S (U,R,E)=T H 1 N K I T=S G O O D

~~~
geekingfrog
Does readable MUMPS even exist?

~~~
acveilleux
Yeah but it's not proper style.

------
wellpast
And yet give me a code base with clear contracts, narrow interfaces and
minimal dependencies with EVERY ONE of these so-called 'violations'...all of
which are are trivial to contend with if you have a good software
architecture.

Am wondering when our industry will see this forest for the trees...

------
sdf45
While the advice in the article is funny, on a deeper level the author seems
to argue that program text is a rather basic representation that often
obstructs insight into the semantics of the program.

The quest for other program representations is still open. The state of the
art uses text as "storage" format plus an IDE that does some semantic analysis
to help the developer navigate. Many of the ideas mentined in the article
(navigation, coloring, auto-format) have been integrated into IDEs and
editors.

With almost 20 years of research between the article then and now, what
semantic techniques are you dreaming of in your development environment? What
are you missing? What feature would greatly improve your productivity (but is
possibly too costly to implement by yourself)?

------
adrianN
Also relevant The Selfish Class[1]. How to write classes that thrive in the
struggle for programmer attention.

[1]
[http://www.laputan.org/selfish/selfish.html](http://www.laputan.org/selfish/selfish.html)

------
vog
_> You earn extra Brownie points whenever the beginning and end of a block
appear on separate pages in a printed listing._

I'm aware that this is from 1997-1999, but I'm curious: Do people still print
out source code for better reading?

~~~
Symbiote
The essay was presented half-seriously as part of a module on software
maintainability [1], which I took in 2007. Perl was given as an example of a
write-only language: modification of a typical Perl program requires at least
a partial re-write. (The extra joke was that many of the computing
department's internal systems were written in Perl.)

More seriously, there were discussions of library versioning schemes, backward
compatibility etc.

I see Susan no longer lectures, which is a shame, as she was one of my
favourite lecturers.

[1]
[https://www.doc.ic.ac.uk/~susan/475/](https://www.doc.ic.ac.uk/~susan/475/)

(The replacement course seems to be this:
[http://www.imperial.ac.uk/computing/current-
students/courses...](http://www.imperial.ac.uk/computing/current-
students/courses/475/) )

~~~
marcosscriven
I fondly recall her design patterns course, way back in '96!

------
samspot
Look! Responsive Web Design from 1999!

------
littletinman
This should be renamed to: "Common red flags to look for in merge requests and
code reviews" and handed to every rookie, mid-level, and senior developer on
your project!

~~~
omouse
Depending on the team you can get away with some of these. Have a manager/PHB
that actively discourages unit testing? You don't need to commit your unit
tests or write them at all! No one fixes an instance of copy/paste coding?
Great, now you too can be efficient by copying and pasting everywhere. No one
uses a code formatter or uses different formatting styles? Good! Now your
style can shine!

These are all good red flags to check for in existing code bases before you
join a team. If you see them, chances are their code review process is poor or
non-existent and you'll be fighting a battle against crap code every single
day.

~~~
littletinman
Looking through the codebase for these to assess the teams review health is a
fantastic idea!

------
JoeCoder_
I once worked with a programmer who would not indent any of his code. "It
makes it go faster" he said. Wrote all of his code in Windows Notepad too.

------
returntrip
I've found it helpful to write several functions with the same name throughout
the codebase. Also, when refactoring code, don't rewrite it completely, just
clone the directory and append "_new".

------
cosmolev
Writing unmaintainable code increases job security.

~~~
cheepin
You have to get away with it for a while first. Otherwise you get fired before
you are the only one that knows what is going on.

------
fgtx
"Never put in any { } surrounding your if/else blocks unless they are
syntactically obligatory."

------
landmark2
genius! :)

------
emailgregn
use perl

~~~
DodgyEggplant
javascript is OK too. Avoid Python.

